build(deps): refactored TypeScript and package configuration across monorepo

- Added tsconfig.publish.json files to all packages with optimized publish-time configuration.
- Updated all package.json scripts with prepublishOnly hooks for correct type checking during publish.
- Added @oh-my-pi/omp-stats path mappings to root tsconfig.json for consistent imports.
- Added WASM generation script for photon module and integrated into install:dev script.
This commit is contained in:
can1357
2026-01-23 13:46:01 +01:00
parent d672458138
commit 0fe761dc4b
409 changed files with 1894 additions and 1551 deletions
+1 -1
View File
@@ -68,7 +68,7 @@ jobs:
key: bun-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- run: bun install --frozen-lockfile
- name: Generate WASM base64
run: printf 'export default "%s";\n' "$(base64 -w0 packages/coding-agent/src/vendor/photon/photon_rs_bg.wasm)" > packages/coding-agent/src/vendor/photon/photon_rs_bg.wasm.b64.js
run: bun packages/coding-agent/scripts/generate-wasm-b64.ts
- name: Build binaries
run: |
cd packages/coding-agent
+1 -1
View File
@@ -6,7 +6,7 @@
"packages/*"
],
"scripts": {
"install:dev": "bun install && bun --cwd=packages/coding-agent link && bun --cwd=packages/ai link",
"install:dev": "bun install && bun packages/coding-agent/scripts/generate-wasm-b64.ts && bun --cwd=packages/coding-agent link && bun --cwd=packages/ai link",
"dev": "bun packages/coding-agent/src/cli.ts",
"stats": "bun --cwd=packages/coding-agent src/cli.ts stats",
"check": "biome check --write . && bun --cwd=packages/coding-agent run check && bun --cwd=packages/omp-stats run check",
+2
View File
@@ -2,6 +2,8 @@
## [Unreleased]
### Changed
- Updated TypeScript configuration for better publish-time configuration handling with tsconfig.publish.json
## [8.0.0] - 2026-01-23
### Added
+12 -1
View File
@@ -5,12 +5,23 @@
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": {
"types": "./src/index.ts",
"import": "./src/index.ts"
},
"./*": {
"types": "./src/*",
"import": "./src/*"
}
},
"files": [
"src",
"README.md"
],
"scripts": {
"test": "vitest --run"
"test": "vitest --run",
"prepublishOnly": "cp tsconfig.publish.json tsconfig.json"
},
"dependencies": {
"@oh-my-pi/pi-ai": "workspace:*",
+1 -1
View File
@@ -13,7 +13,7 @@ import {
type StopReason,
type ToolCall,
} from "@oh-my-pi/pi-ai";
import { parseStreamingJson } from "@oh-my-pi/pi-ai/src/utils/json-parse";
import { parseStreamingJson } from "@oh-my-pi/pi-ai/utils/json-parse";
import { readSseEvents } from "@oh-my-pi/pi-utils";
// Create stream class matching ProxyMessageEventStream
+11
View File
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"noEmit": true,
"baseUrl": ".",
"paths": {
"@oh-my-pi/pi-agent-core": ["./src/index.ts"],
"@oh-my-pi/pi-agent-core/*": ["./src/*"]
}
},
"include": ["src/**/*.ts"]
}
+2 -2
View File
@@ -2,8 +2,8 @@
## [Unreleased]
### Added
- Added `isRetryableError` and `extractHttpStatusFromError` utility functions to identify transient errors suitable for retry (timeouts, 5xx, 408, 429, network failures)
### Changed
- Updated TypeScript configuration for better publish-time configuration handling with tsconfig.publish.json
## [8.0.0] - 2026-01-23
### Fixed
+16 -1
View File
@@ -5,6 +5,20 @@
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": {
"types": "./src/index.ts",
"import": "./src/index.ts"
},
"./utils/*": {
"types": "./src/utils/*.ts",
"import": "./src/utils/*.ts"
},
"./*": {
"types": "./src/*",
"import": "./src/*"
}
},
"bin": {
"pi-ai": "./src/cli.ts"
},
@@ -14,7 +28,8 @@
],
"scripts": {
"generate-models": "bun scripts/generate-models.ts",
"test": "bun test"
"test": "bun test",
"prepublishOnly": "cp tsconfig.publish.json tsconfig.json"
},
"dependencies": {
"@oh-my-pi/pi-utils": "workspace:*",
+100 -101
View File
@@ -1726,7 +1726,7 @@ export const MODELS = {
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 128000,
contextWindow: 64000,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"gpt-4o": {
@@ -1766,24 +1766,6 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 128000,
} satisfies Model<"openai-responses">,
"gpt-5-codex": {
id: "gpt-5-codex",
name: "GPT-5-Codex",
api: "openai-responses",
provider: "github-copilot",
baseUrl: "https://api.individual.githubcopilot.com",
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
reasoning: true,
input: ["text", "image"],
cost: {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 128000,
maxTokens: 128000,
} satisfies Model<"openai-responses">,
"gpt-5-mini": {
id: "gpt-5-mini",
name: "GPT-5-mini",
@@ -3641,7 +3623,7 @@ export const MODELS = {
cost: {
input: 1.25,
output: 10,
cacheRead: 0.13,
cacheRead: 0.125,
cacheWrite: 0,
},
contextWindow: 400000,
@@ -3692,7 +3674,7 @@ export const MODELS = {
cost: {
input: 0.25,
output: 2,
cacheRead: 0.03,
cacheRead: 0.025,
cacheWrite: 0,
},
contextWindow: 400000,
@@ -3709,7 +3691,7 @@ export const MODELS = {
cost: {
input: 0.05,
output: 0.4,
cacheRead: 0.01,
cacheRead: 0.005,
cacheWrite: 0,
},
contextWindow: 400000,
@@ -4314,6 +4296,23 @@ export const MODELS = {
contextWindow: 204800,
maxTokens: 131072,
} satisfies Model<"openai-completions">,
"glm-4.7": {
id: "glm-4.7",
name: "GLM-4.7",
api: "openai-completions",
provider: "opencode",
baseUrl: "https://opencode.ai/zen/v1",
reasoning: true,
input: ["text"],
cost: {
input: 0.6,
output: 2.2,
cacheRead: 0.1,
cacheWrite: 0,
},
contextWindow: 204800,
maxTokens: 131072,
} satisfies Model<"openai-completions">,
"glm-4.7-free": {
id: "glm-4.7-free",
name: "GLM-4.7",
@@ -4615,7 +4614,7 @@ export const MODELS = {
input: ["text"],
cost: {
input: 0.09,
output: 0.39999999999999997,
output: 0.44999999999999996,
cacheRead: 0,
cacheWrite: 0,
},
@@ -5028,7 +5027,7 @@ export const MODELS = {
cacheWrite: 0,
},
contextWindow: 262144,
maxTokens: 16384,
maxTokens: 32768,
} satisfies Model<"openai-completions">,
"cohere/command-r-08-2024": {
id: "cohere/command-r-08-2024",
@@ -5297,7 +5296,7 @@ export const MODELS = {
input: 0.09999999999999999,
output: 0.39999999999999997,
cacheRead: 0.024999999999999998,
cacheWrite: 0.0833,
cacheWrite: 0.08333333333333333,
},
contextWindow: 1048576,
maxTokens: 8192,
@@ -5311,10 +5310,10 @@ export const MODELS = {
reasoning: false,
input: ["text", "image"],
cost: {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
input: 0.09999999999999999,
output: 0.39999999999999997,
cacheRead: 0.024999999999999998,
cacheWrite: 0.08333333333333333,
},
contextWindow: 1048576,
maxTokens: 8192,
@@ -5348,7 +5347,7 @@ export const MODELS = {
input: 0.3,
output: 2.5,
cacheRead: 0.03,
cacheWrite: 0.08333333333333334,
cacheWrite: 0.08333333333333333,
},
contextWindow: 1048576,
maxTokens: 65535,
@@ -5365,7 +5364,7 @@ export const MODELS = {
input: 0.09999999999999999,
output: 0.39999999999999997,
cacheRead: 0.01,
cacheWrite: 0.0833,
cacheWrite: 0.08333333333333333,
},
contextWindow: 1048576,
maxTokens: 65535,
@@ -5382,10 +5381,10 @@ export const MODELS = {
input: 0.09999999999999999,
output: 0.39999999999999997,
cacheRead: 0.01,
cacheWrite: 0.0833,
cacheWrite: 0.08333333333333333,
},
contextWindow: 1048576,
maxTokens: 65536,
maxTokens: 65535,
} satisfies Model<"openai-completions">,
"google/gemini-2.5-flash-preview-09-2025": {
id: "google/gemini-2.5-flash-preview-09-2025",
@@ -5398,8 +5397,8 @@ export const MODELS = {
cost: {
input: 0.3,
output: 2.5,
cacheRead: 0.075,
cacheWrite: 0.0833,
cacheRead: 0.03,
cacheWrite: 0.08333333333333333,
},
contextWindow: 1048576,
maxTokens: 65535,
@@ -5432,7 +5431,7 @@ export const MODELS = {
cost: {
input: 1.25,
output: 10,
cacheRead: 0.31,
cacheRead: 0.125,
cacheWrite: 0.375,
},
contextWindow: 1048576,
@@ -5449,7 +5448,7 @@ export const MODELS = {
cost: {
input: 1.25,
output: 10,
cacheRead: 0.31,
cacheRead: 0.125,
cacheWrite: 0.375,
},
contextWindow: 1048576,
@@ -5467,7 +5466,7 @@ export const MODELS = {
input: 0.5,
output: 3,
cacheRead: 0.049999999999999996,
cacheWrite: 0,
cacheWrite: 0.08333333333333333,
},
contextWindow: 1048576,
maxTokens: 65535,
@@ -5754,12 +5753,12 @@ export const MODELS = {
input: ["text"],
cost: {
input: 0.27,
output: 1.12,
output: 1.1,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 196608,
maxTokens: 65536,
maxTokens: 196608,
} satisfies Model<"openai-completions">,
"mistralai/codestral-2508": {
id: "mistralai/codestral-2508",
@@ -6048,7 +6047,7 @@ export const MODELS = {
cacheWrite: 0,
},
contextWindow: 131072,
maxTokens: 131072,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"mistralai/mistral-saba": {
id: "mistralai/mistral-saba",
@@ -7869,6 +7868,23 @@ export const MODELS = {
contextWindow: 262144,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"qwen/qwen3-vl-235b-a22b-thinking": {
id: "qwen/qwen3-vl-235b-a22b-thinking",
name: "Qwen: Qwen3 VL 235B A22B Thinking",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text", "image"],
cost: {
input: 0.44999999999999996,
output: 3.5,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 262144,
maxTokens: 262144,
} satisfies Model<"openai-completions">,
"qwen/qwen3-vl-30b-a3b-instruct": {
id: "qwen/qwen3-vl-30b-a3b-instruct",
name: "Qwen: Qwen3 VL 30B A3B Instruct",
@@ -8430,6 +8446,23 @@ export const MODELS = {
contextWindow: 202752,
maxTokens: 65535,
} satisfies Model<"openai-completions">,
"z-ai/glm-4.7-flash": {
id: "z-ai/glm-4.7-flash",
name: "Z.AI: GLM 4.7 Flash",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text"],
cost: {
input: 0.07,
output: 0.39999999999999997,
cacheRead: 0.01,
cacheWrite: 0,
},
contextWindow: 200000,
maxTokens: 131072,
} satisfies Model<"openai-completions">,
},
"vercel-ai-gateway": {
"alibaba/qwen-3-14b": {
@@ -8562,7 +8595,7 @@ export const MODELS = {
cost: {
input: 1,
output: 5,
cacheRead: 0,
cacheRead: 0.19999999999999998,
cacheWrite: 0,
},
contextWindow: 1000000,
@@ -8619,23 +8652,6 @@ export const MODELS = {
contextWindow: 200000,
maxTokens: 4096,
} satisfies Model<"anthropic-messages">,
"anthropic/claude-3-opus": {
id: "anthropic/claude-3-opus",
name: "Claude 3 Opus",
api: "anthropic-messages",
provider: "vercel-ai-gateway",
baseUrl: "https://ai-gateway.vercel.sh",
reasoning: false,
input: ["text", "image"],
cost: {
input: 15,
output: 75,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 200000,
maxTokens: 8192,
} satisfies Model<"anthropic-messages">,
"anthropic/claude-3.5-haiku": {
id: "anthropic/claude-3.5-haiku",
name: "Claude 3.5 Haiku",
@@ -8786,7 +8802,7 @@ export const MODELS = {
cacheRead: 0.3,
cacheWrite: 3.75,
},
contextWindow: 200000,
contextWindow: 1000000,
maxTokens: 64000,
} satisfies Model<"anthropic-messages">,
"anthropic/claude-sonnet-4.5": {
@@ -8803,7 +8819,7 @@ export const MODELS = {
cacheRead: 0.3,
cacheWrite: 3.75,
},
contextWindow: 200000,
contextWindow: 1000000,
maxTokens: 64000,
} satisfies Model<"anthropic-messages">,
"bytedance/seed-1.6": {
@@ -8925,40 +8941,6 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 64000,
} satisfies Model<"anthropic-messages">,
"google/gemini-2.0-flash": {
id: "google/gemini-2.0-flash",
name: "Gemini 2.0 Flash",
api: "anthropic-messages",
provider: "vercel-ai-gateway",
baseUrl: "https://ai-gateway.vercel.sh",
reasoning: false,
input: ["text", "image"],
cost: {
input: 0.09999999999999999,
output: 0.39999999999999997,
cacheRead: 0.024999999999999998,
cacheWrite: 0,
},
contextWindow: 1000000,
maxTokens: 8192,
} satisfies Model<"anthropic-messages">,
"google/gemini-2.0-flash-lite": {
id: "google/gemini-2.0-flash-lite",
name: "Gemini 2.0 Flash Lite",
api: "anthropic-messages",
provider: "vercel-ai-gateway",
baseUrl: "https://ai-gateway.vercel.sh",
reasoning: false,
input: ["text", "image"],
cost: {
input: 0.075,
output: 0.3,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 1048576,
maxTokens: 8192,
} satisfies Model<"anthropic-messages">,
"google/gemini-2.5-flash": {
id: "google/gemini-2.5-flash",
name: "Gemini 2.5 Flash",
@@ -8966,15 +8948,15 @@ export const MODELS = {
provider: "vercel-ai-gateway",
baseUrl: "https://ai-gateway.vercel.sh",
reasoning: true,
input: ["text", "image"],
input: ["text"],
cost: {
input: 0.3,
output: 2.5,
cacheRead: 0.03,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 1000000,
maxTokens: 64000,
maxTokens: 65536,
} satisfies Model<"anthropic-messages">,
"google/gemini-2.5-flash-lite": {
id: "google/gemini-2.5-flash-lite",
@@ -9034,11 +9016,11 @@ export const MODELS = {
provider: "vercel-ai-gateway",
baseUrl: "https://ai-gateway.vercel.sh",
reasoning: true,
input: ["text", "image"],
input: ["text"],
cost: {
input: 1.25,
output: 10,
cacheRead: 0.125,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 1048576,
@@ -10449,7 +10431,7 @@ export const MODELS = {
cost: {
input: 0.19999999999999998,
output: 1.1,
cacheRead: 0,
cacheRead: 0.03,
cacheWrite: 0,
},
contextWindow: 128000,
@@ -10540,6 +10522,23 @@ export const MODELS = {
contextWindow: 202752,
maxTokens: 120000,
} satisfies Model<"anthropic-messages">,
"zai/glm-4.7-flashx": {
id: "zai/glm-4.7-flashx",
name: "GLM 4.7 FlashX",
api: "anthropic-messages",
provider: "vercel-ai-gateway",
baseUrl: "https://ai-gateway.vercel.sh",
reasoning: true,
input: ["text"],
cost: {
input: 0.06,
output: 0.39999999999999997,
cacheRead: 0.01,
cacheWrite: 0,
},
contextWindow: 200000,
maxTokens: 128000,
} satisfies Model<"anthropic-messages">,
},
"xai": {
"grok-2": {
+5 -5
View File
@@ -18,7 +18,7 @@ import {
ToolResultStatus,
} from "@aws-sdk/client-bedrock-runtime";
import { calculateCost } from "$ai/models";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import type {
Api,
AssistantMessage,
@@ -34,10 +34,10 @@ import type {
Tool,
ToolCall,
ToolResultMessage,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { parseStreamingJson } from "$ai/utils/json-parse";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { parseStreamingJson } from "@oh-my-pi/pi-ai/utils/json-parse";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import { transformMessages } from "./transform-messages";
export interface BedrockOptions extends StreamOptions {
+7 -7
View File
@@ -4,8 +4,8 @@ import type {
MessageCreateParamsStreaming,
MessageParam,
} from "@anthropic-ai/sdk/resources/messages";
import { calculateCost } from "$ai/models";
import { getEnvApiKey, OUTPUT_FALLBACK_BUFFER } from "$ai/stream";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import { getEnvApiKey, OUTPUT_FALLBACK_BUFFER } from "@oh-my-pi/pi-ai/stream";
import type {
Api,
AssistantMessage,
@@ -21,11 +21,11 @@ import type {
Tool,
ToolCall,
ToolResultMessage,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { parseStreamingJson } from "$ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { parseStreamingJson } from "@oh-my-pi/pi-ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "@oh-my-pi/pi-ai/utils/retry-after";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import { transformMessages } from "./transform-messages";
+6 -6
View File
@@ -3,8 +3,7 @@ import { appendFile } from "node:fs/promises";
import http2 from "node:http2";
import { create, fromBinary, fromJson, type JsonValue, toBinary, toJson } from "@bufbuild/protobuf";
import { ValueSchema } from "@bufbuild/protobuf/wkt";
import JSON5 from "json5";
import { calculateCost } from "$ai/models";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import type {
Api,
AssistantMessage,
@@ -23,10 +22,11 @@ import type {
Tool,
ToolCall,
ToolResultMessage,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { parseStreamingJson } from "$ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { parseStreamingJson } from "@oh-my-pi/pi-ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "@oh-my-pi/pi-ai/utils/retry-after";
import JSON5 from "json5";
import type { McpToolDefinition } from "./cursor/gen/agent_pb";
import {
AgentClientMessageSchema,
@@ -6,8 +6,8 @@ import type {
UsageProvider,
UsageReport,
UsageWindow,
} from "$ai/usage";
import { refreshGoogleCloudToken } from "$ai/utils/oauth/google-gemini-cli";
} from "@oh-my-pi/pi-ai/usage";
import { refreshGoogleCloudToken } from "@oh-my-pi/pi-ai/utils/oauth/google-gemini-cli";
const DEFAULT_ENDPOINT = "https://cloudcode-pa.googleapis.com";
const CACHE_TTL_MS = 60_000;
@@ -6,8 +6,7 @@
import { createHash } from "node:crypto";
import type { Content, ThinkingConfig } from "@google/genai";
import { abortableSleep } from "@oh-my-pi/pi-utils";
import { calculateCost } from "$ai/models";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import type {
Api,
AssistantMessage,
@@ -18,9 +17,10 @@ import type {
TextContent,
ThinkingContent,
ToolCall,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import { abortableSleep } from "@oh-my-pi/pi-utils";
import {
convertMessages,
convertTools,
+2 -2
View File
@@ -3,8 +3,8 @@
*/
import { type Content, FinishReason, FunctionCallingConfigMode, type Part, type Schema } from "@google/genai";
import type { Context, ImageContent, Model, StopReason, TextContent, Tool } from "$ai/types";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
import type { Context, ImageContent, Model, StopReason, TextContent, Tool } from "@oh-my-pi/pi-ai/types";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import { transformMessages } from "./transform-messages";
type GoogleApiType = "google-generative-ai" | "google-gemini-cli" | "google-vertex";
+5 -5
View File
@@ -5,7 +5,7 @@ import {
type ThinkingConfig,
ThinkingLevel,
} from "@google/genai";
import { calculateCost } from "$ai/models";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import type {
Api,
AssistantMessage,
@@ -16,10 +16,10 @@ import type {
TextContent,
ThinkingContent,
ToolCall,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { formatErrorMessageWithRetryAfter } from "@oh-my-pi/pi-ai/utils/retry-after";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import type { GoogleThinkingLevel } from "./google-gemini-cli";
import {
convertMessages,
+6 -6
View File
@@ -4,8 +4,8 @@ import {
GoogleGenAI,
type ThinkingConfig,
} from "@google/genai";
import { calculateCost } from "$ai/models";
import { getEnvApiKey } from "$ai/stream";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import { getEnvApiKey } from "@oh-my-pi/pi-ai/stream";
import type {
Api,
AssistantMessage,
@@ -16,10 +16,10 @@ import type {
TextContent,
ThinkingContent,
ToolCall,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { formatErrorMessageWithRetryAfter } from "@oh-my-pi/pi-ai/utils/retry-after";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import type { GoogleThinkingLevel } from "./google-gemini-cli";
import {
convertMessages,
@@ -1,16 +1,6 @@
import os from "node:os";
import { abortableSleep } from "@oh-my-pi/pi-utils";
import type {
ResponseFunctionToolCall,
ResponseInput,
ResponseInputContent,
ResponseInputImage,
ResponseInputText,
ResponseOutputMessage,
ResponseReasoningItem,
} from "openai/resources/responses/responses";
import { calculateCost } from "$ai/models";
import { getEnvApiKey } from "$ai/stream";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import { getEnvApiKey } from "@oh-my-pi/pi-ai/stream";
import type {
Api,
AssistantMessage,
@@ -23,11 +13,21 @@ import type {
ThinkingContent,
Tool,
ToolCall,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { parseStreamingJson } from "$ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { parseStreamingJson } from "@oh-my-pi/pi-ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "@oh-my-pi/pi-ai/utils/retry-after";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import { abortableSleep } from "@oh-my-pi/pi-utils";
import type {
ResponseFunctionToolCall,
ResponseInput,
ResponseInputContent,
ResponseInputImage,
ResponseInputText,
ResponseOutputMessage,
ResponseReasoningItem,
} from "openai/resources/responses/responses";
import packageJson from "../../package.json" with { type: "json" };
import {
CODEX_BASE_URL,
+17 -17
View File
@@ -1,15 +1,5 @@
import OpenAI from "openai";
import type {
ChatCompletionAssistantMessageParam,
ChatCompletionChunk,
ChatCompletionContentPart,
ChatCompletionContentPartImage,
ChatCompletionContentPartText,
ChatCompletionMessageParam,
ChatCompletionToolMessageParam,
} from "openai/resources/chat/completions";
import { calculateCost } from "$ai/models";
import { getEnvApiKey } from "$ai/stream";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import { getEnvApiKey } from "@oh-my-pi/pi-ai/stream";
import type {
AssistantMessage,
Context,
@@ -24,11 +14,21 @@ import type {
Tool,
ToolCall,
ToolResultMessage,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { parseStreamingJson } from "$ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { parseStreamingJson } from "@oh-my-pi/pi-ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "@oh-my-pi/pi-ai/utils/retry-after";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import OpenAI from "openai";
import type {
ChatCompletionAssistantMessageParam,
ChatCompletionChunk,
ChatCompletionContentPart,
ChatCompletionContentPartImage,
ChatCompletionContentPartText,
ChatCompletionMessageParam,
ChatCompletionToolMessageParam,
} from "openai/resources/chat/completions";
import { transformMessages } from "./transform-messages";
/**
+19 -19
View File
@@ -1,17 +1,5 @@
import OpenAI from "openai";
import type {
Tool as OpenAITool,
ResponseCreateParamsStreaming,
ResponseFunctionToolCall,
ResponseInput,
ResponseInputContent,
ResponseInputImage,
ResponseInputText,
ResponseOutputMessage,
ResponseReasoningItem,
} from "openai/resources/responses/responses";
import { calculateCost } from "$ai/models";
import { getEnvApiKey } from "$ai/stream";
import { calculateCost } from "@oh-my-pi/pi-ai/models";
import { getEnvApiKey } from "@oh-my-pi/pi-ai/stream";
import type {
Api,
AssistantMessage,
@@ -24,11 +12,23 @@ import type {
ThinkingContent,
Tool,
ToolCall,
} from "$ai/types";
import { AssistantMessageEventStream } from "$ai/utils/event-stream";
import { parseStreamingJson } from "$ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
} from "@oh-my-pi/pi-ai/types";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { parseStreamingJson } from "@oh-my-pi/pi-ai/utils/json-parse";
import { formatErrorMessageWithRetryAfter } from "@oh-my-pi/pi-ai/utils/retry-after";
import { sanitizeSurrogates } from "@oh-my-pi/pi-ai/utils/sanitize-unicode";
import OpenAI from "openai";
import type {
Tool as OpenAITool,
ResponseCreateParamsStreaming,
ResponseFunctionToolCall,
ResponseInput,
ResponseInputContent,
ResponseInputImage,
ResponseInputText,
ResponseOutputMessage,
ResponseReasoningItem,
} from "openai/resources/responses/responses";
import { transformMessages } from "./transform-messages";
/** Fast deterministic hash to shorten long strings */
@@ -1,4 +1,4 @@
import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from "$ai/types";
import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from "@oh-my-pi/pi-ai/types";
/**
* Normalize tool call ID for cross-provider compatibility.
+1 -1
View File
@@ -7,7 +7,7 @@ import type {
UsageReport,
UsageStatus,
UsageWindow,
} from "$ai/usage";
} from "@oh-my-pi/pi-ai/usage";
const DEFAULT_ENDPOINT = "https://api.anthropic.com/api/oauth";
const DEFAULT_CACHE_TTL_MS = 60_000;
+1 -1
View File
@@ -14,7 +14,7 @@ import type {
UsageReport,
UsageStatus,
UsageWindow,
} from "$ai/usage";
} from "@oh-my-pi/pi-ai/usage";
const COPILOT_HEADERS = {
"User-Agent": "GitHubCopilotChat/0.35.0",
+2 -2
View File
@@ -7,8 +7,8 @@ import type {
UsageReport,
UsageStatus,
UsageWindow,
} from "$ai/usage";
import { refreshAntigravityToken } from "$ai/utils/oauth/google-antigravity";
} from "@oh-my-pi/pi-ai/usage";
import { refreshAntigravityToken } from "@oh-my-pi/pi-ai/utils/oauth/google-antigravity";
interface AntigravityQuotaInfo {
remainingFraction?: number;
+2 -2
View File
@@ -1,5 +1,5 @@
import { Buffer } from "node:buffer";
import { CODEX_BASE_URL } from "$ai/providers/openai-codex/constants";
import { CODEX_BASE_URL } from "@oh-my-pi/pi-ai/providers/openai-codex/constants";
import type {
UsageAmount,
UsageCache,
@@ -9,7 +9,7 @@ import type {
UsageProvider,
UsageReport,
UsageWindow,
} from "$ai/usage";
} from "@oh-my-pi/pi-ai/usage";
const CODEX_USAGE_PATH = "wham/usage";
const DEFAULT_CACHE_TTL_MS = 60_000;
+1 -1
View File
@@ -7,7 +7,7 @@ import type {
UsageReport,
UsageStatus,
UsageWindow,
} from "$ai/usage";
} from "@oh-my-pi/pi-ai/usage";
const DEFAULT_ENDPOINT = "https://api.z.ai";
const QUOTA_PATH = "/api/monitor/usage/quota/limit";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { AssistantMessage, AssistantMessageEvent } from "$ai/types";
import type { AssistantMessage, AssistantMessageEvent } from "@oh-my-pi/pi-ai/types";
// Generic event stream class for async iteration
export class EventStream<T, R = T> implements AsyncIterable<T> {
@@ -2,8 +2,8 @@
* GitHub Copilot OAuth flow
*/
import { getModels } from "@oh-my-pi/pi-ai/models";
import { abortableSleep } from "@oh-my-pi/pi-utils";
import { getModels } from "$ai/models";
import type { OAuthCredentials } from "./types";
const decode = (s: string) => atob(s);
+1 -1
View File
@@ -1,4 +1,4 @@
import type { AssistantMessage } from "$ai/types";
import type { AssistantMessage } from "@oh-my-pi/pi-ai/types";
/**
* Regex patterns to detect context overflow errors from different providers.
+1 -1
View File
@@ -5,7 +5,7 @@ import addFormatsModule from "ajv-formats";
const Ajv = (AjvModule as any).default || AjvModule;
const addFormats = (addFormatsModule as any).default || addFormatsModule;
import type { Tool, ToolCall } from "$ai/types";
import type { Tool, ToolCall } from "@oh-my-pi/pi-ai/types";
// ============================================================================
// Type Coercion Utilities
+3 -3
View File
@@ -1,7 +1,7 @@
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete, stream } from "@oh-my-pi/pi-ai/stream";
import type { Api, Context, Model, OptionsForApi } from "@oh-my-pi/pi-ai/types";
import { describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete, stream } from "$ai/stream";
import type { Api, Context, Model, OptionsForApi } from "$ai/types";
import { resolveApiKey } from "./oauth";
// Resolve OAuth tokens at module level (async, runs before tests)
+4 -4
View File
@@ -13,11 +13,11 @@
import type { ChildProcess } from "node:child_process";
import { execSync, spawn } from "node:child_process";
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete } from "@oh-my-pi/pi-ai/stream";
import type { AssistantMessage, Context, Model, Usage } from "@oh-my-pi/pi-ai/types";
import { isContextOverflow } from "@oh-my-pi/pi-ai/utils/overflow";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete } from "$ai/stream";
import type { AssistantMessage, Context, Model, Usage } from "$ai/types";
import { isContextOverflow } from "$ai/utils/overflow";
import { resolveApiKey } from "./oauth";
// Resolve OAuth tokens at module level (async, runs before tests)
@@ -1,6 +1,6 @@
import { transformMessages } from "@oh-my-pi/pi-ai/providers/transform-messages";
import type { AssistantMessage, Model, ToolResultMessage } from "@oh-my-pi/pi-ai/types";
import { describe, expect, it } from "vitest";
import { transformMessages } from "$ai/providers/transform-messages";
import type { AssistantMessage, Model, ToolResultMessage } from "$ai/types";
/**
* Regression test for: "each tool_use must have a single result. Found multiple tool_result blocks with id"
+3 -3
View File
@@ -1,7 +1,7 @@
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete } from "@oh-my-pi/pi-ai/stream";
import type { Api, AssistantMessage, Context, Model, OptionsForApi, UserMessage } from "@oh-my-pi/pi-ai/types";
import { describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete } from "$ai/stream";
import type { Api, AssistantMessage, Context, Model, OptionsForApi, UserMessage } from "$ai/types";
import { resolveApiKey } from "./oauth";
// Resolve OAuth tokens at module level (async, runs before tests)
@@ -1,5 +1,5 @@
import { isThinkingPart, retainThoughtSignature } from "@oh-my-pi/pi-ai/providers/google-shared";
import { describe, expect, it } from "vitest";
import { isThinkingPart, retainThoughtSignature } from "$ai/providers/google-shared";
describe("Google thinking detection (thoughtSignature)", () => {
it("treats part.thought === true as thinking", () => {
+3 -3
View File
@@ -1,8 +1,8 @@
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete } from "@oh-my-pi/pi-ai/stream";
import type { Api, AssistantMessage, Context, Message, Model, Tool, ToolResultMessage } from "@oh-my-pi/pi-ai/types";
import { Type } from "@sinclair/typebox";
import { describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete } from "$ai/stream";
import type { Api, AssistantMessage, Context, Message, Model, Tool, ToolResultMessage } from "$ai/types";
// Tool for testing
const weatherSchema = Type.Object({
+3 -3
View File
@@ -70,10 +70,10 @@
import { execSync } from "node:child_process";
import { mkdirSync, rmSync } from "node:fs";
import { join } from "node:path";
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete } from "@oh-my-pi/pi-ai/stream";
import type { Api, Context, ImageContent, Model, OptionsForApi, UserMessage } from "@oh-my-pi/pi-ai/types";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete } from "$ai/stream";
import type { Api, Context, ImageContent, Model, OptionsForApi, UserMessage } from "$ai/types";
const TEMP_DIR = join(import.meta.dir, ".temp-images");
+3 -3
View File
@@ -1,10 +1,10 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
import type { Api, Context, Model, Tool, ToolResultMessage } from "@oh-my-pi/pi-ai/index";
import { complete, getModel } from "@oh-my-pi/pi-ai/index";
import type { OptionsForApi } from "@oh-my-pi/pi-ai/types";
import { Type } from "@sinclair/typebox";
import { describe, expect, it } from "vitest";
import type { Api, Context, Model, Tool, ToolResultMessage } from "$ai/index";
import { complete, getModel } from "$ai/index";
import type { OptionsForApi } from "$ai/types";
import { resolveApiKey } from "./oauth";
// Resolve OAuth tokens at module level (async, runs before tests)
+2 -2
View File
@@ -6,10 +6,10 @@
*/
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { getOAuthApiKey } from "@oh-my-pi/pi-ai/utils/oauth/index";
import type { OAuthCredentials, OAuthProvider } from "@oh-my-pi/pi-ai/utils/oauth/types";
import { homedir } from "os";
import { dirname, join } from "path";
import { getOAuthApiKey } from "$ai/utils/oauth/index";
import type { OAuthCredentials, OAuthProvider } from "$ai/utils/oauth/types";
const AUTH_PATH = join(homedir(), ".pi", "agent", "auth.json");
@@ -1,5 +1,5 @@
import { type RequestBody, transformRequestBody } from "@oh-my-pi/pi-ai/providers/openai-codex/request-transformer";
import { describe, expect, it } from "vitest";
import { type RequestBody, transformRequestBody } from "$ai/providers/openai-codex/request-transformer";
describe("openai-codex include handling", () => {
it("always includes reasoning.encrypted_content when caller include is custom", async () => {
+2 -2
View File
@@ -1,7 +1,7 @@
import { afterEach, describe, expect, it, vi } from "bun:test";
import { streamOpenAICodexResponses } from "@oh-my-pi/pi-ai/providers/openai-codex-responses";
import type { Context, Model } from "@oh-my-pi/pi-ai/types";
import { createTempDirSync } from "@oh-my-pi/pi-utils";
import { streamOpenAICodexResponses } from "$ai/providers/openai-codex-responses";
import type { Context, Model } from "$ai/types";
const originalFetch = global.fetch;
const originalAgentDir = process.env.OMP_CODING_AGENT_DIR;
+2 -2
View File
@@ -1,6 +1,6 @@
import { type RequestBody, transformRequestBody } from "@oh-my-pi/pi-ai/providers/openai-codex/request-transformer";
import { parseCodexError } from "@oh-my-pi/pi-ai/providers/openai-codex/response-handler";
import { describe, expect, it } from "vitest";
import { type RequestBody, transformRequestBody } from "$ai/providers/openai-codex/request-transformer";
import { parseCodexError } from "$ai/providers/openai-codex/response-handler";
const DEFAULT_PROMPT_PREFIX =
"You are an expert coding assistant. You help users with coding tasks by reading files, executing commands";
@@ -1,7 +1,7 @@
import { describe, expect, it } from "bun:test";
import { getModel } from "$ai/models";
import { convertMessages } from "$ai/providers/openai-completions";
import type { AssistantMessage, Context, Model, OpenAICompat, ToolResultMessage, Usage } from "$ai/types";
import { getModel } from "@oh-my-pi/pi-ai/models";
import { convertMessages } from "@oh-my-pi/pi-ai/providers/openai-completions";
import type { AssistantMessage, Context, Model, OpenAICompat, ToolResultMessage, Usage } from "@oh-my-pi/pi-ai/types";
const emptyUsage: Usage = {
input: 0,
+4 -4
View File
@@ -1,12 +1,12 @@
import { type ChildProcess, execSync, spawn } from "node:child_process";
import { readFileSync } from "node:fs";
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete, stream } from "@oh-my-pi/pi-ai/stream";
import type { Api, Context, ImageContent, Model, OptionsForApi, Tool, ToolResultMessage } from "@oh-my-pi/pi-ai/types";
import { StringEnum } from "@oh-my-pi/pi-ai/utils/typebox-helpers";
import { Type } from "@sinclair/typebox";
import { join } from "path";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete, stream } from "$ai/stream";
import type { Api, Context, ImageContent, Model, OptionsForApi, Tool, ToolResultMessage } from "$ai/types";
import { StringEnum } from "$ai/utils/typebox-helpers";
import { resolveApiKey } from "./oauth";
// Resolve OAuth tokens at module level (async, runs before tests)
+3 -3
View File
@@ -1,7 +1,7 @@
import { getModel } from "@oh-my-pi/pi-ai/models";
import { stream } from "@oh-my-pi/pi-ai/stream";
import type { Api, Context, Model, OptionsForApi } from "@oh-my-pi/pi-ai/types";
import { describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { stream } from "$ai/stream";
import type { Api, Context, Model, OptionsForApi } from "$ai/types";
import { resolveApiKey } from "./oauth";
// Resolve OAuth tokens at module level (async, runs before tests)
@@ -1,7 +1,7 @@
import { describe, expect, it } from "bun:test";
import type { Tool, ToolCall } from "@oh-my-pi/pi-ai/types";
import { validateToolArguments } from "@oh-my-pi/pi-ai/utils/validation";
import { Type } from "@sinclair/typebox";
import type { Tool, ToolCall } from "$ai/types";
import { validateToolArguments } from "$ai/utils/validation";
describe("Tool argument coercion", () => {
it("coerces numeric strings when schema expects number", () => {
@@ -1,8 +1,8 @@
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete } from "@oh-my-pi/pi-ai/stream";
import type { Api, Context, Model, OptionsForApi, Tool } from "@oh-my-pi/pi-ai/types";
import { Type } from "@sinclair/typebox";
import { describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete } from "$ai/stream";
import type { Api, Context, Model, OptionsForApi, Tool } from "$ai/types";
import { resolveApiKey } from "./oauth";
// Resolve OAuth tokens at module level (async, runs before tests)
+3 -3
View File
@@ -12,10 +12,10 @@
* - Other OpenAI-compatible providers: Uses native total_tokens field
*/
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete } from "@oh-my-pi/pi-ai/stream";
import type { Api, Context, Model, OptionsForApi, Usage } from "@oh-my-pi/pi-ai/types";
import { describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete } from "$ai/stream";
import type { Api, Context, Model, OptionsForApi, Usage } from "$ai/types";
import { resolveApiKey } from "./oauth";
// Resolve OAuth tokens at module level (async, runs before tests)
+3 -3
View File
@@ -1,8 +1,8 @@
import { getModel } from "@oh-my-pi/pi-ai/models";
import { complete } from "@oh-my-pi/pi-ai/stream";
import type { Api, Context, Model, OptionsForApi, ToolResultMessage } from "@oh-my-pi/pi-ai/types";
import { Type } from "@sinclair/typebox";
import { describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { complete } from "$ai/stream";
import type { Api, Context, Model, OptionsForApi, ToolResultMessage } from "$ai/types";
import { resolveApiKey } from "./oauth";
// Empty schema for test tools - must be proper OBJECT type for Cloud Code Assist
+3 -3
View File
@@ -1,7 +1,7 @@
import { getModel } from "@oh-my-pi/pi-ai/models";
import { stream } from "@oh-my-pi/pi-ai/stream";
import type { Context, Model } from "@oh-my-pi/pi-ai/types";
import { describe, expect, it } from "vitest";
import { getModel } from "$ai/models";
import { stream } from "$ai/stream";
import type { Context, Model } from "$ai/types";
function makeContext(): Context {
return {
+3 -3
View File
@@ -1,7 +1,7 @@
import { MODELS } from "@oh-my-pi/pi-ai/models.generated";
import { complete } from "@oh-my-pi/pi-ai/stream";
import type { Model } from "@oh-my-pi/pi-ai/types";
import { describe, expect, it } from "vitest";
import { MODELS } from "$ai/models.generated";
import { complete } from "$ai/stream";
import type { Model } from "$ai/types";
describe.skipIf(!process.env.OPENCODE_API_KEY)("OpenCode Zen Models Smoke Test", () => {
const zenModels = Object.values(MODELS.opencode);
+11
View File
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"noEmit": true,
"baseUrl": ".",
"paths": {
"@oh-my-pi/pi-ai": ["./src/index.ts"],
"@oh-my-pi/pi-ai/*": ["./src/*"]
}
},
"include": ["src/**/*.ts"]
}
+2
View File
@@ -44,6 +44,7 @@
- Added two-level mermaid caching with pending deduplication to prevent redundant renders
- Added Python kernel session pooling with MAX_KERNEL_SESSIONS limit and automatic eviction of oldest sessions
- Added automatic idle kernel session cleanup timer (5-minute timeout, 30-second interval)
- Added WASM binary generation script for photon module distribution
### Changed
- Changed changelog diff truncation limit to be configurable via settings
@@ -96,6 +97,7 @@
- Changed commit agent prompt to remove pre-computed observations guidance and encourage direct analyze_files usage
- Changed AuthStorage from constructor-based instantiation to async factory method (AuthStorage.create())
- Changed Python kernel resource management with gateway shutdown on session disposal
- Updated TypeScript configuration for better publish-time configuration handling with tsconfig.publish.json
### Fixed
- Fixed database busy errors during concurrent access by adding retry logic with exponential backoff when opening storage
+8 -2
View File
@@ -20,6 +20,11 @@
"./hooks": {
"types": "./src/extensibility/hooks/index.ts",
"import": "./src/extensibility/hooks/index.ts"
},
"./prompts/*": "./src/prompts/*",
"./*": {
"types": "./src/*",
"import": "./src/*"
}
},
"files": [
@@ -35,10 +40,11 @@
"clean": "rm -rf dist",
"build": "tsgo -p tsconfig.build.json && chmod +x dist/cli.js",
"build:binary": "bun run generate-wasm-b64 && bun build --compile ./src/cli.ts --outfile dist/omp",
"generate-wasm-b64": "bun scripts/generate-wasm-b64.ts",
"generate-template": "bun scripts/generate-template.ts",
"postinstall": "bun run generate-template || true",
"postinstall": "(bun run generate-wasm-b64 && bun run generate-template) || true",
"test": "bun test",
"prepublishOnly": "bun run generate-template"
"prepublishOnly": "cp tsconfig.publish.json tsconfig.json && bun run generate-template"
},
"dependencies": {
"@oh-my-pi/omp-stats": "workspace:*",
@@ -0,0 +1,24 @@
#!/usr/bin/env bun
/**
* Generates a base64-encoded JavaScript module from the photon WASM file.
* This allows bundling the WASM binary inline for single-file distribution.
*/
import { join } from "node:path";
const VENDOR_DIR = join(import.meta.dir, "../src/vendor/photon");
const WASM_PATH = join(VENDOR_DIR, "photon_rs_bg.wasm");
const OUTPUT_PATH = join(VENDOR_DIR, "photon_rs_bg.wasm.b64.js");
const wasmFile = Bun.file(WASM_PATH);
if (!(await wasmFile.exists())) {
console.error(`WASM file not found: ${WASM_PATH}`);
process.exit(1);
}
const wasmBytes = await wasmFile.arrayBuffer();
const base64 = Buffer.from(wasmBytes).toString("base64");
const content = `export default "${base64}";\n`;
await Bun.write(OUTPUT_PATH, content);
console.log(`Generated ${OUTPUT_PATH} (${Math.round(base64.length / 1024)}KB)`);
+2 -2
View File
@@ -3,9 +3,9 @@
*/
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "@oh-my-pi/pi-coding-agent/config";
import { BUILTIN_TOOLS } from "@oh-my-pi/pi-coding-agent/tools/index";
import chalk from "chalk";
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "$c/config";
import { BUILTIN_TOOLS } from "$c/tools/index";
export type Mode = "text" | "json" | "rpc";
+4 -4
View File
@@ -5,11 +5,11 @@
* Uses SETTINGS_DEFS as the source of truth for available settings.
*/
import { APP_NAME, getAgentDir } from "@oh-my-pi/pi-coding-agent/config";
import { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
import { SETTINGS_DEFS, type SettingDef } from "@oh-my-pi/pi-coding-agent/modes/components/settings-defs";
import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
import chalk from "chalk";
import { APP_NAME, getAgentDir } from "$c/config";
import { SettingsManager } from "$c/config/settings-manager";
import { SETTINGS_DEFS, type SettingDef } from "$c/modes/components/settings-defs";
import { theme } from "$c/modes/theme/theme";
// =============================================================================
// Types
@@ -5,10 +5,10 @@
import { existsSync, readFileSync, statSync } from "node:fs";
import { resolve } from "node:path";
import type { ImageContent } from "@oh-my-pi/pi-ai";
import { resolveReadPath } from "@oh-my-pi/pi-coding-agent/tools/path-utils";
import { formatDimensionNote, resizeImage } from "@oh-my-pi/pi-coding-agent/utils/image-resize";
import { detectSupportedImageMimeTypeFromFile } from "@oh-my-pi/pi-coding-agent/utils/mime";
import chalk from "chalk";
import { resolveReadPath } from "$c/tools/path-utils";
import { formatDimensionNote, resizeImage } from "$c/utils/image-resize";
import { detectSupportedImageMimeTypeFromFile } from "$c/utils/mime";
export interface ProcessedFiles {
text: string;
+2 -2
View File
@@ -3,8 +3,8 @@
*/
import type { Api, Model } from "@oh-my-pi/pi-ai";
import type { ModelRegistry } from "$c/config/model-registry";
import { fuzzyFilter } from "$c/utils/fuzzy";
import type { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
import { fuzzyFilter } from "@oh-my-pi/pi-coding-agent/utils/fuzzy";
/**
* Format a number as human-readable (e.g., 200000 -> "200K", 1000000 -> "1M")
+7 -3
View File
@@ -4,10 +4,14 @@
* Handles `omp plugin <command>` subcommands for plugin lifecycle management.
*/
import { APP_NAME } from "@oh-my-pi/pi-coding-agent/config";
import {
PluginManager,
parseSettingValue,
validateSetting,
} from "@oh-my-pi/pi-coding-agent/extensibility/plugins/index";
import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
import chalk from "chalk";
import { APP_NAME } from "$c/config";
import { PluginManager, parseSettingValue, validateSetting } from "$c/extensibility/plugins/index";
import { theme } from "$c/modes/theme/theme";
// =============================================================================
// Types
@@ -2,9 +2,9 @@
* TUI session selector for --resume flag
*/
import { SessionSelectorComponent } from "@oh-my-pi/pi-coding-agent/modes/components/session-selector";
import type { SessionInfo } from "@oh-my-pi/pi-coding-agent/session/session-manager";
import { ProcessTerminal, TUI } from "@oh-my-pi/pi-tui";
import { SessionSelectorComponent } from "$c/modes/components/session-selector";
import type { SessionInfo } from "$c/session/session-manager";
/** Show TUI session selector and return selected session path or null if cancelled */
export async function selectSession(sessions: SessionInfo[]): Promise<string | null> {
+2 -2
View File
@@ -4,10 +4,10 @@
* Handles `omp setup <component>` to install dependencies for optional features.
*/
import { APP_NAME } from "@oh-my-pi/pi-coding-agent/config";
import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
import { $ } from "bun";
import chalk from "chalk";
import { APP_NAME } from "$c/config";
import { theme } from "$c/modes/theme/theme";
export type SetupComponent = "python";
+1 -1
View File
@@ -4,8 +4,8 @@
* Handles `omp stats` subcommand for viewing AI usage statistics.
*/
import { APP_NAME } from "@oh-my-pi/pi-coding-agent/config";
import chalk from "chalk";
import { APP_NAME } from "$c/config";
// =============================================================================
// Types
+2 -2
View File
@@ -10,9 +10,9 @@ import { createWriteStream, existsSync, renameSync, unlinkSync } from "node:fs";
import { dirname } from "node:path";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";
import { APP_NAME, VERSION } from "@oh-my-pi/pi-coding-agent/config";
import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
import chalk from "chalk";
import { APP_NAME, VERSION } from "$c/config";
import { theme } from "$c/modes/theme/theme";
/**
* Detect if we're running as a Bun compiled binary.
@@ -1,19 +1,21 @@
import type { Api, Model } from "@oh-my-pi/pi-ai";
import agentUserPrompt from "@oh-my-pi/pi-coding-agent/commit/agentic/prompts/session-user.md" with { type: "text" };
import agentSystemPrompt from "@oh-my-pi/pi-coding-agent/commit/agentic/prompts/system.md" with { type: "text" };
import type { CommitAgentState } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import { createCommitTools } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools";
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import typesDescriptionPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/types-description.md" with {
type: "text",
};
import type { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
import { getMarkdownTheme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
import { createAgentSession } from "@oh-my-pi/pi-coding-agent/sdk";
import type { AgentSessionEvent } from "@oh-my-pi/pi-coding-agent/session/agent-session";
import type { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
import { Markdown } from "@oh-my-pi/pi-tui";
import chalk from "chalk";
import agentUserPrompt from "$c/commit/agentic/prompts/session-user.md" with { type: "text" };
import agentSystemPrompt from "$c/commit/agentic/prompts/system.md" with { type: "text" };
import type { CommitAgentState } from "$c/commit/agentic/state";
import { createCommitTools } from "$c/commit/agentic/tools";
import type { ControlledGit } from "$c/commit/git";
import typesDescriptionPrompt from "$c/commit/prompts/types-description.md" with { type: "text" };
import type { ModelRegistry } from "$c/config/model-registry";
import { renderPromptTemplate } from "$c/config/prompt-templates";
import type { SettingsManager } from "$c/config/settings-manager";
import { getMarkdownTheme } from "$c/modes/theme/theme";
import { createAgentSession } from "$c/sdk";
import type { AgentSessionEvent } from "$c/session/agent-session";
import type { AuthStorage } from "$c/session/auth-storage";
export interface CommitAgentInput {
cwd: string;
@@ -66,7 +68,7 @@ export async function runCommitAgentSession(input: CommitAgentInput): Promise<Co
enableMCP: false,
hasUI: false,
spawns,
toolNames: ["read"],
toolNames: ["__none__"],
contextFiles: input.contextFiles,
disableExtensionDiscovery: true,
skills: [],
@@ -1,6 +1,6 @@
import { basename } from "node:path";
import type { CommitProposal } from "$c/commit/agentic/state";
import type { CommitType, ConventionalAnalysis, NumstatEntry } from "$c/commit/types";
import type { CommitProposal } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import type { CommitType, ConventionalAnalysis, NumstatEntry } from "@oh-my-pi/pi-coding-agent/commit/types";
const TEST_PATTERNS = ["/test/", "/tests/", "/__tests__/", "_test.", ".test.", ".spec.", "_spec."];
const DOC_EXTENSIONS = new Set([".md", ".txt", ".rst", ".adoc"]);
@@ -1,21 +1,28 @@
import { relative } from "node:path";
import { createInterface } from "node:readline/promises";
import { type ExistingChangelogEntries, runCommitAgentSession } from "$c/commit/agentic/agent";
import { generateFallbackProposal } from "$c/commit/agentic/fallback";
import splitConfirmPrompt from "$c/commit/agentic/prompts/split-confirm.md" with { type: "text" };
import type { CommitAgentState, CommitProposal, HunkSelector, SplitCommitPlan } from "$c/commit/agentic/state";
import { computeDependencyOrder } from "$c/commit/agentic/topo-sort";
import { detectTrivialChange } from "$c/commit/agentic/trivial";
import { applyChangelogProposals } from "$c/commit/changelog";
import { detectChangelogBoundaries } from "$c/commit/changelog/detect";
import { parseUnreleasedSection } from "$c/commit/changelog/parse";
import { ControlledGit } from "$c/commit/git";
import { formatCommitMessage } from "$c/commit/message";
import { resolvePrimaryModel, resolveSmolModel } from "$c/commit/model-selection";
import type { CommitCommandArgs, ConventionalAnalysis } from "$c/commit/types";
import { renderPromptTemplate } from "$c/config/prompt-templates";
import { SettingsManager } from "$c/config/settings-manager";
import { discoverAuthStorage, discoverContextFiles, discoverModels } from "$c/sdk";
import { type ExistingChangelogEntries, runCommitAgentSession } from "@oh-my-pi/pi-coding-agent/commit/agentic/agent";
import { generateFallbackProposal } from "@oh-my-pi/pi-coding-agent/commit/agentic/fallback";
import splitConfirmPrompt from "@oh-my-pi/pi-coding-agent/commit/agentic/prompts/split-confirm.md" with {
type: "text",
};
import type {
CommitAgentState,
CommitProposal,
HunkSelector,
SplitCommitPlan,
} from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import { computeDependencyOrder } from "@oh-my-pi/pi-coding-agent/commit/agentic/topo-sort";
import { detectTrivialChange } from "@oh-my-pi/pi-coding-agent/commit/agentic/trivial";
import { applyChangelogProposals } from "@oh-my-pi/pi-coding-agent/commit/changelog";
import { detectChangelogBoundaries } from "@oh-my-pi/pi-coding-agent/commit/changelog/detect";
import { parseUnreleasedSection } from "@oh-my-pi/pi-coding-agent/commit/changelog/parse";
import { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import { formatCommitMessage } from "@oh-my-pi/pi-coding-agent/commit/message";
import { resolvePrimaryModel, resolveSmolModel } from "@oh-my-pi/pi-coding-agent/commit/model-selection";
import type { CommitCommandArgs, ConventionalAnalysis } from "@oh-my-pi/pi-coding-agent/commit/types";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
import { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
import { discoverAuthStorage, discoverContextFiles, discoverModels } from "@oh-my-pi/pi-coding-agent/sdk";
interface CommitExecutionContext {
git: ControlledGit;
@@ -6,11 +6,11 @@ Your job: decide what git information you need, gather it with tools, and finish
Workflow rules:
1. Always call git_overview first.
2. Keep tool calls minimal: prefer 1-2 git_file_diff calls covering key files.
2. Keep tool calls minimal: prefer 1-2 git_file_diff calls covering key files (hard limit: 2).
3. Use git_hunk only for very large diffs.
4. Use recent_commits only if you need style context.
5. Use analyze_files only when diffs are too large or unclear.
6. Avoid read unless git tools cannot answer the question.
6. Do not use read.
7. When confident, submit the final proposal with propose_commit or split_commit.
Commit requirements:
@@ -1,4 +1,9 @@
import type { CommitType, ConventionalAnalysis, ConventionalDetail, NumstatEntry } from "$c/commit/types";
import type {
CommitType,
ConventionalAnalysis,
ConventionalDetail,
NumstatEntry,
} from "@oh-my-pi/pi-coding-agent/commit/types";
export interface GitOverviewSnapshot {
files: string[];
@@ -1,16 +1,16 @@
import analyzeFilePrompt from "@oh-my-pi/pi-coding-agent/commit/agentic/prompts/analyze-file.md" with { type: "text" };
import type { CommitAgentState } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import { getFilePriority } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/git-file-diff";
import type { NumstatEntry } from "@oh-my-pi/pi-coding-agent/commit/types";
import type { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
import type { CustomTool, CustomToolContext } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import type { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
import { TaskTool } from "@oh-my-pi/pi-coding-agent/task";
import type { TaskParams } from "@oh-my-pi/pi-coding-agent/task/types";
import type { ToolSession } from "@oh-my-pi/pi-coding-agent/tools/index";
import { Type } from "@sinclair/typebox";
import analyzeFilePrompt from "$c/commit/agentic/prompts/analyze-file.md" with { type: "text" };
import type { CommitAgentState } from "$c/commit/agentic/state";
import { getFilePriority } from "$c/commit/agentic/tools/git-file-diff";
import type { NumstatEntry } from "$c/commit/types";
import type { ModelRegistry } from "$c/config/model-registry";
import { renderPromptTemplate } from "$c/config/prompt-templates";
import type { SettingsManager } from "$c/config/settings-manager";
import type { CustomTool, CustomToolContext } from "$c/extensibility/custom-tools/types";
import type { AuthStorage } from "$c/session/auth-storage";
import { TaskTool } from "$c/task";
import type { TaskParams } from "$c/task/types";
import type { ToolSession } from "$c/tools/index";
const analyzeFileSchema = Type.Object({
files: Type.Array(Type.String({ description: "File path" }), { minItems: 1 }),
@@ -1,7 +1,7 @@
import type { CommitAgentState } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import { Type } from "@sinclair/typebox";
import type { CommitAgentState } from "$c/commit/agentic/state";
import type { ControlledGit } from "$c/commit/git";
import type { CustomTool } from "$c/extensibility/custom-tools/types";
const TARGET_TOKENS = 30000;
const CHARS_PER_TOKEN = 4;
@@ -1,7 +1,7 @@
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import type { DiffHunk, FileHunks } from "@oh-my-pi/pi-coding-agent/commit/types";
import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import { Type } from "@sinclair/typebox";
import type { ControlledGit } from "$c/commit/git";
import type { DiffHunk, FileHunks } from "$c/commit/types";
import type { CustomTool } from "$c/extensibility/custom-tools/types";
const gitHunkSchema = Type.Object({
file: Type.String({ description: "File path" }),
@@ -1,8 +1,8 @@
import type { CommitAgentState, GitOverviewSnapshot } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import { extractScopeCandidates } from "@oh-my-pi/pi-coding-agent/commit/analysis/scope";
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import { Type } from "@sinclair/typebox";
import type { CommitAgentState, GitOverviewSnapshot } from "$c/commit/agentic/state";
import { extractScopeCandidates } from "$c/commit/analysis/scope";
import type { ControlledGit } from "$c/commit/git";
import type { CustomTool } from "$c/extensibility/custom-tools/types";
const EXCLUDED_LOCK_FILES = new Set([
"Cargo.lock",
@@ -1,17 +1,17 @@
import type { CommitAgentState } from "$c/commit/agentic/state";
import { createAnalyzeFileTool } from "$c/commit/agentic/tools/analyze-file";
import { createGitFileDiffTool } from "$c/commit/agentic/tools/git-file-diff";
import { createGitHunkTool } from "$c/commit/agentic/tools/git-hunk";
import { createGitOverviewTool } from "$c/commit/agentic/tools/git-overview";
import { createProposeChangelogTool } from "$c/commit/agentic/tools/propose-changelog";
import { createProposeCommitTool } from "$c/commit/agentic/tools/propose-commit";
import { createRecentCommitsTool } from "$c/commit/agentic/tools/recent-commits";
import { createSplitCommitTool } from "$c/commit/agentic/tools/split-commit";
import type { ControlledGit } from "$c/commit/git";
import type { ModelRegistry } from "$c/config/model-registry";
import type { SettingsManager } from "$c/config/settings-manager";
import type { CustomTool } from "$c/extensibility/custom-tools/types";
import type { AuthStorage } from "$c/session/auth-storage";
import type { CommitAgentState } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import { createAnalyzeFileTool } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/analyze-file";
import { createGitFileDiffTool } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/git-file-diff";
import { createGitHunkTool } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/git-hunk";
import { createGitOverviewTool } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/git-overview";
import { createProposeChangelogTool } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/propose-changelog";
import { createProposeCommitTool } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/propose-commit";
import { createRecentCommitsTool } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/recent-commits";
import { createSplitCommitTool } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools/split-commit";
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import type { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import type { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
export interface CommitToolOptions {
cwd: string;
@@ -1,7 +1,7 @@
import type { CommitAgentState } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import type { ChangelogCategory } from "@oh-my-pi/pi-coding-agent/commit/types";
import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import { Type } from "@sinclair/typebox";
import type { CommitAgentState } from "$c/commit/agentic/state";
import type { ChangelogCategory } from "$c/commit/types";
import type { CustomTool } from "$c/extensibility/custom-tools/types";
const changelogEntrySchema = Type.Object({
path: Type.String(),
@@ -1,5 +1,4 @@
import { Type } from "@sinclair/typebox";
import type { CommitAgentState } from "$c/commit/agentic/state";
import type { CommitAgentState } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import {
capDetails,
MAX_DETAIL_ITEMS,
@@ -7,11 +6,12 @@ import {
SUMMARY_MAX_CHARS,
validateSummaryRules,
validateTypeConsistency,
} from "$c/commit/agentic/validation";
import { validateAnalysis } from "$c/commit/analysis/validation";
import type { ControlledGit } from "$c/commit/git";
import type { CommitType, ConventionalAnalysis, ConventionalDetail } from "$c/commit/types";
import type { CustomTool } from "$c/extensibility/custom-tools/types";
} from "@oh-my-pi/pi-coding-agent/commit/agentic/validation";
import { validateAnalysis } from "@oh-my-pi/pi-coding-agent/commit/analysis/validation";
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import type { CommitType, ConventionalAnalysis, ConventionalDetail } from "@oh-my-pi/pi-coding-agent/commit/types";
import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import { Type } from "@sinclair/typebox";
const commitTypeSchema = Type.Union([
Type.Literal("feat"),
@@ -1,6 +1,6 @@
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import { Type } from "@sinclair/typebox";
import type { ControlledGit } from "$c/commit/git";
import type { CustomTool } from "$c/extensibility/custom-tools/types";
const recentCommitsSchema = Type.Object({
count: Type.Optional(Type.Number({ description: "Number of commits to fetch", minimum: 1, maximum: 50 })),
@@ -1,6 +1,9 @@
import { Type } from "@sinclair/typebox";
import type { CommitAgentState, SplitCommitGroup, SplitCommitPlan } from "$c/commit/agentic/state";
import { computeDependencyOrder } from "$c/commit/agentic/topo-sort";
import type {
CommitAgentState,
SplitCommitGroup,
SplitCommitPlan,
} from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
import { computeDependencyOrder } from "@oh-my-pi/pi-coding-agent/commit/agentic/topo-sort";
import {
capDetails,
MAX_DETAIL_ITEMS,
@@ -8,11 +11,12 @@ import {
SUMMARY_MAX_CHARS,
validateSummaryRules,
validateTypeConsistency,
} from "$c/commit/agentic/validation";
import { validateScope } from "$c/commit/analysis/validation";
import type { ControlledGit } from "$c/commit/git";
import type { ConventionalDetail } from "$c/commit/types";
import type { CustomTool } from "$c/extensibility/custom-tools/types";
} from "@oh-my-pi/pi-coding-agent/commit/agentic/validation";
import { validateScope } from "@oh-my-pi/pi-coding-agent/commit/analysis/validation";
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import type { ConventionalDetail } from "@oh-my-pi/pi-coding-agent/commit/types";
import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
import { Type } from "@sinclair/typebox";
const commitTypeSchema = Type.Union([
Type.Literal("feat"),
@@ -1,4 +1,4 @@
import type { SplitCommitGroup } from "$c/commit/agentic/state";
import type { SplitCommitGroup } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
export function computeDependencyOrder(groups: SplitCommitGroup[]): number[] | { error: string } {
const total = groups.length;
@@ -1,4 +1,4 @@
import type { CommitType } from "$c/commit/types";
import type { CommitType } from "@oh-my-pi/pi-coding-agent/commit/types";
export interface TrivialChangeResult {
isTrivial: true;
@@ -1,6 +1,6 @@
import { stripTypePrefix } from "$c/commit/analysis/summary";
import { validateSummary } from "$c/commit/analysis/validation";
import type { CommitType, ConventionalDetail } from "$c/commit/types";
import { stripTypePrefix } from "@oh-my-pi/pi-coding-agent/commit/analysis/summary";
import { validateSummary } from "@oh-my-pi/pi-coding-agent/commit/analysis/validation";
import type { CommitType, ConventionalDetail } from "@oh-my-pi/pi-coding-agent/commit/types";
export const SUMMARY_MAX_CHARS = 72;
export const MAX_DETAIL_ITEMS = 6;
@@ -1,10 +1,14 @@
import type { Api, AssistantMessage, Model, ToolCall } from "@oh-my-pi/pi-ai";
import { completeSimple, validateToolCall } from "@oh-my-pi/pi-ai";
import analysisSystemPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/analysis-system.md" with { type: "text" };
import analysisUserPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/analysis-user.md" with { type: "text" };
import type {
ChangelogCategory,
ConventionalAnalysis,
ConventionalDetail,
} from "@oh-my-pi/pi-coding-agent/commit/types";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
import { Type } from "@sinclair/typebox";
import analysisSystemPrompt from "$c/commit/prompts/analysis-system.md" with { type: "text" };
import analysisUserPrompt from "$c/commit/prompts/analysis-user.md" with { type: "text" };
import type { ChangelogCategory, ConventionalAnalysis, ConventionalDetail } from "$c/commit/types";
import { renderPromptTemplate } from "$c/config/prompt-templates";
const ConventionalAnalysisTool = {
name: "create_conventional_analysis",
@@ -1,4 +1,4 @@
export { generateConventionalAnalysis } from "$c/commit/analysis/conventional";
export { extractScopeCandidates } from "$c/commit/analysis/scope";
export { generateSummary, stripTypePrefix } from "$c/commit/analysis/summary";
export { validateAnalysis, validateScope, validateSummary } from "$c/commit/analysis/validation";
export { generateConventionalAnalysis } from "@oh-my-pi/pi-coding-agent/commit/analysis/conventional";
export { extractScopeCandidates } from "@oh-my-pi/pi-coding-agent/commit/analysis/scope";
export { generateSummary, stripTypePrefix } from "@oh-my-pi/pi-coding-agent/commit/analysis/summary";
export { validateAnalysis, validateScope, validateSummary } from "@oh-my-pi/pi-coding-agent/commit/analysis/validation";
@@ -1,5 +1,5 @@
import type { NumstatEntry } from "$c/commit/types";
import { isExcludedFile } from "$c/commit/utils/exclusions";
import type { NumstatEntry } from "@oh-my-pi/pi-coding-agent/commit/types";
import { isExcludedFile } from "@oh-my-pi/pi-coding-agent/commit/utils/exclusions";
interface ScopeCandidate {
path: string;
@@ -1,10 +1,10 @@
import type { Api, AssistantMessage, Model, ToolCall } from "@oh-my-pi/pi-ai";
import { completeSimple, validateToolCall } from "@oh-my-pi/pi-ai";
import summarySystemPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/summary-system.md" with { type: "text" };
import summaryUserPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/summary-user.md" with { type: "text" };
import type { CommitSummary } from "@oh-my-pi/pi-coding-agent/commit/types";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
import { Type } from "@sinclair/typebox";
import summarySystemPrompt from "$c/commit/prompts/summary-system.md" with { type: "text" };
import summaryUserPrompt from "$c/commit/prompts/summary-user.md" with { type: "text" };
import type { CommitSummary } from "$c/commit/types";
import { renderPromptTemplate } from "$c/config/prompt-templates";
const SummaryTool = {
name: "create_commit_summary",
@@ -1,4 +1,4 @@
import type { ConventionalAnalysis } from "$c/commit/types";
import type { ConventionalAnalysis } from "@oh-my-pi/pi-coding-agent/commit/types";
export interface ValidationResult {
valid: boolean;
@@ -1,5 +1,5 @@
import { dirname, resolve } from "node:path";
import type { ChangelogBoundary } from "$c/commit/types";
import type { ChangelogBoundary } from "@oh-my-pi/pi-coding-agent/commit/types";
const CHANGELOG_NAME = "CHANGELOG.md";
@@ -1,10 +1,10 @@
import type { Api, AssistantMessage, Model, ToolCall } from "@oh-my-pi/pi-ai";
import { completeSimple, validateToolCall } from "@oh-my-pi/pi-ai";
import changelogSystemPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/changelog-system.md" with { type: "text" };
import changelogUserPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/changelog-user.md" with { type: "text" };
import type { ChangelogGenerationResult } from "@oh-my-pi/pi-coding-agent/commit/types";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
import { Type } from "@sinclair/typebox";
import changelogSystemPrompt from "$c/commit/prompts/changelog-system.md" with { type: "text" };
import changelogUserPrompt from "$c/commit/prompts/changelog-user.md" with { type: "text" };
import type { ChangelogGenerationResult } from "$c/commit/types";
import { renderPromptTemplate } from "$c/config/prompt-templates";
const ChangelogTool = {
name: "create_changelog_entries",
@@ -1,10 +1,10 @@
import { relative, resolve } from "node:path";
import type { Api, Model } from "@oh-my-pi/pi-ai";
import { detectChangelogBoundaries } from "@oh-my-pi/pi-coding-agent/commit/changelog/detect";
import { generateChangelogEntries } from "@oh-my-pi/pi-coding-agent/commit/changelog/generate";
import { parseUnreleasedSection } from "@oh-my-pi/pi-coding-agent/commit/changelog/parse";
import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import { logger } from "@oh-my-pi/pi-utils";
import { detectChangelogBoundaries } from "$c/commit/changelog/detect";
import { generateChangelogEntries } from "$c/commit/changelog/generate";
import { parseUnreleasedSection } from "$c/commit/changelog/parse";
import type { ControlledGit } from "$c/commit/git";
const CHANGELOG_SECTIONS = ["Breaking Changes", "Added", "Changed", "Deprecated", "Removed", "Fixed", "Security"];
@@ -1,4 +1,4 @@
import type { UnreleasedSection } from "$c/commit/types";
import type { UnreleasedSection } from "@oh-my-pi/pi-coding-agent/commit/types";
const UNRELEASED_PATTERN = /^##\s+\[?Unreleased\]?/i;
const SECTION_PATTERN = /^###\s+(.*)$/;
+1 -1
View File
@@ -1,5 +1,5 @@
import type { CommitCommandArgs } from "@oh-my-pi/pi-coding-agent/commit/types";
import chalk from "chalk";
import type { CommitCommandArgs } from "$c/commit/types";
const FLAG_ALIASES = new Map<string, string>([
["-c", "--context"],
+1 -1
View File
@@ -1,4 +1,4 @@
import type { DiffHunk, FileDiff, FileHunks, NumstatEntry } from "$c/commit/types";
import type { DiffHunk, FileDiff, FileHunks, NumstatEntry } from "@oh-my-pi/pi-coding-agent/commit/types";
export function parseNumstat(output: string): NumstatEntry[] {
const entries: NumstatEntry[] = [];
@@ -2,11 +2,16 @@ import { randomUUID } from "node:crypto";
import { rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
parseDiffHunks,
parseFileDiffs,
parseFileHunks,
parseNumstat,
} from "@oh-my-pi/pi-coding-agent/commit/git/diff";
import { GitError } from "@oh-my-pi/pi-coding-agent/commit/git/errors";
import { commit, push, resetStaging, runGitCommand, stageFiles } from "@oh-my-pi/pi-coding-agent/commit/git/operations";
import type { FileDiff, FileHunks, NumstatEntry } from "@oh-my-pi/pi-coding-agent/commit/types";
import { logger } from "@oh-my-pi/pi-utils";
import { parseDiffHunks, parseFileDiffs, parseFileHunks, parseNumstat } from "$c/commit/git/diff";
import { GitError } from "$c/commit/git/errors";
import { commit, push, resetStaging, runGitCommand, stageFiles } from "$c/commit/git/operations";
import type { FileDiff, FileHunks, NumstatEntry } from "$c/commit/types";
export type HunkSelection = {
path: string;
+1 -1
View File
@@ -2,4 +2,4 @@
* Entry points for the omp commit command.
*/
export { runCommitCommand } from "$c/commit/pipeline";
export { runCommitCommand } from "@oh-my-pi/pi-coding-agent/commit/pipeline";
@@ -1,10 +1,10 @@
import type { Api, Model } from "@oh-my-pi/pi-ai";
import { parseFileDiffs } from "$c/commit/git/diff";
import { runMapPhase } from "$c/commit/map-reduce/map-phase";
import { runReducePhase } from "$c/commit/map-reduce/reduce-phase";
import { estimateTokens } from "$c/commit/map-reduce/utils";
import type { ConventionalAnalysis } from "$c/commit/types";
import { isExcludedFile } from "$c/commit/utils/exclusions";
import { parseFileDiffs } from "@oh-my-pi/pi-coding-agent/commit/git/diff";
import { runMapPhase } from "@oh-my-pi/pi-coding-agent/commit/map-reduce/map-phase";
import { runReducePhase } from "@oh-my-pi/pi-coding-agent/commit/map-reduce/reduce-phase";
import { estimateTokens } from "@oh-my-pi/pi-coding-agent/commit/map-reduce/utils";
import type { ConventionalAnalysis } from "@oh-my-pi/pi-coding-agent/commit/types";
import { isExcludedFile } from "@oh-my-pi/pi-coding-agent/commit/utils/exclusions";
const MIN_FILES_FOR_MAP_REDUCE = 4;
const MAX_FILE_TOKENS = 50_000;
@@ -1,11 +1,15 @@
import type { Api, AssistantMessage, Model } from "@oh-my-pi/pi-ai";
import { completeSimple } from "@oh-my-pi/pi-ai";
import { truncateToTokenLimit } from "$c/commit/map-reduce/utils";
import fileObserverSystemPrompt from "$c/commit/prompts/file-observer-system.md" with { type: "text" };
import fileObserverUserPrompt from "$c/commit/prompts/file-observer-user.md" with { type: "text" };
import type { FileDiff, FileObservation } from "$c/commit/types";
import { isExcludedFile } from "$c/commit/utils/exclusions";
import { renderPromptTemplate } from "$c/config/prompt-templates";
import { truncateToTokenLimit } from "@oh-my-pi/pi-coding-agent/commit/map-reduce/utils";
import fileObserverSystemPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/file-observer-system.md" with {
type: "text",
};
import fileObserverUserPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/file-observer-user.md" with {
type: "text",
};
import type { FileDiff, FileObservation } from "@oh-my-pi/pi-coding-agent/commit/types";
import { isExcludedFile } from "@oh-my-pi/pi-coding-agent/commit/utils/exclusions";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
const MAX_FILE_TOKENS = 50_000;
const MAX_CONTEXT_FILES = 20;
@@ -1,10 +1,10 @@
import type { Api, AssistantMessage, Model, ToolCall } from "@oh-my-pi/pi-ai";
import { completeSimple, validateToolCall } from "@oh-my-pi/pi-ai";
import reduceSystemPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/reduce-system.md" with { type: "text" };
import reduceUserPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/reduce-user.md" with { type: "text" };
import type { ChangelogCategory, ConventionalAnalysis, FileObservation } from "@oh-my-pi/pi-coding-agent/commit/types";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
import { Type } from "@sinclair/typebox";
import reduceSystemPrompt from "$c/commit/prompts/reduce-system.md" with { type: "text" };
import reduceUserPrompt from "$c/commit/prompts/reduce-user.md" with { type: "text" };
import type { ChangelogCategory, ConventionalAnalysis, FileObservation } from "$c/commit/types";
import { renderPromptTemplate } from "$c/config/prompt-templates";
const ReduceTool = {
name: "create_conventional_analysis",
+1 -1
View File
@@ -1,4 +1,4 @@
import type { ConventionalAnalysis } from "$c/commit/types";
import type { ConventionalAnalysis } from "@oh-my-pi/pi-coding-agent/commit/types";
export function formatCommitMessage(analysis: ConventionalAnalysis, summary: string): string {
const scopePart = analysis.scope ? `(${analysis.scope})` : "";
@@ -1,6 +1,10 @@
import type { Api, Model } from "@oh-my-pi/pi-ai";
import { parseModelPattern, parseModelString, SMOL_MODEL_PRIORITY } from "$c/config/model-resolver";
import type { SettingsManager } from "$c/config/settings-manager";
import {
parseModelPattern,
parseModelString,
SMOL_MODEL_PRIORITY,
} from "@oh-my-pi/pi-coding-agent/config/model-resolver";
import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
export async function resolvePrimaryModel(
override: string | undefined,
@@ -12,7 +16,7 @@ export async function resolvePrimaryModel(
): Promise<{ model: Model<Api>; apiKey: string }> {
const available = modelRegistry.getAvailable();
const model = override
? resolveModelFromString(override, available)
? resolveModelFromString(expandRoleAlias(override, settingsManager), available)
: resolveModelFromSettings(settingsManager, available);
if (!model) {
throw new Error("No model available for commit generation");
@@ -52,9 +56,14 @@ export async function resolveSmolModel(
}
function resolveModelFromSettings(settingsManager: SettingsManager, available: Model<Api>[]): Model<Api> | undefined {
const configured = settingsManager.getModelRole("default");
if (!configured) return available[0];
return resolveModelFromString(configured, available) ?? available[0];
const roles = ["commit", "smol", "default"];
for (const role of roles) {
const configured = settingsManager.getModelRole(role);
if (!configured) continue;
const resolved = resolveModelFromString(expandRoleAlias(configured, settingsManager), available);
if (resolved) return resolved;
}
return available[0];
}
function resolveModelFromString(value: string, available: Model<Api>[]): Model<Api> | undefined {
@@ -64,3 +73,12 @@ function resolveModelFromString(value: string, available: Model<Api>[]): Model<A
}
return parseModelPattern(value, available).model;
}
function expandRoleAlias(value: string, settingsManager: SettingsManager): string {
const lower = value.toLowerCase();
if (lower.startsWith("pi/") || lower.startsWith("omp/")) {
const role = lower.startsWith("pi/") ? value.slice(3) : value.slice(4);
return settingsManager.getModelRole(role) ?? value;
}
return value;
}
+17 -15
View File
@@ -1,26 +1,28 @@
import { relative } from "node:path";
import type { Api, Model } from "@oh-my-pi/pi-ai";
import { logger } from "@oh-my-pi/pi-utils";
import { runAgenticCommit } from "$c/commit/agentic";
import { runAgenticCommit } from "@oh-my-pi/pi-coding-agent/commit/agentic";
import {
extractScopeCandidates,
generateConventionalAnalysis,
generateSummary,
validateAnalysis,
validateSummary,
} from "$c/commit/analysis";
import { runChangelogFlow } from "$c/commit/changelog";
import { ControlledGit } from "$c/commit/git";
import { runMapReduceAnalysis, shouldUseMapReduce } from "$c/commit/map-reduce";
import { formatCommitMessage } from "$c/commit/message";
import { resolvePrimaryModel, resolveSmolModel } from "$c/commit/model-selection";
import summaryRetryPrompt from "$c/commit/prompts/summary-retry.md" with { type: "text" };
import typesDescriptionPrompt from "$c/commit/prompts/types-description.md" with { type: "text" };
import type { CommitCommandArgs, ConventionalAnalysis } from "$c/commit/types";
import { renderPromptTemplate } from "$c/config/prompt-templates";
import { SettingsManager } from "$c/config/settings-manager";
import { discoverAuthStorage, discoverModels } from "$c/sdk";
import { loadProjectContextFiles } from "$c/system-prompt";
} from "@oh-my-pi/pi-coding-agent/commit/analysis";
import { runChangelogFlow } from "@oh-my-pi/pi-coding-agent/commit/changelog";
import { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
import { runMapReduceAnalysis, shouldUseMapReduce } from "@oh-my-pi/pi-coding-agent/commit/map-reduce";
import { formatCommitMessage } from "@oh-my-pi/pi-coding-agent/commit/message";
import { resolvePrimaryModel, resolveSmolModel } from "@oh-my-pi/pi-coding-agent/commit/model-selection";
import summaryRetryPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/summary-retry.md" with { type: "text" };
import typesDescriptionPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/types-description.md" with {
type: "text",
};
import type { CommitCommandArgs, ConventionalAnalysis } from "@oh-my-pi/pi-coding-agent/commit/types";
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
import { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
import { discoverAuthStorage, discoverModels } from "@oh-my-pi/pi-coding-agent/sdk";
import { loadProjectContextFiles } from "@oh-my-pi/pi-coding-agent/system-prompt";
import { logger } from "@oh-my-pi/pi-utils";
const SUMMARY_MAX_CHARS = 72;
const RECENT_COMMITS_COUNT = 8;

Some files were not shown because too many files have changed in this diff Show More