@opengsd/gsd-pi 1.0.2-dev.235ebf3 → 1.0.2-dev.2c204d3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -12
- package/dist/resource-loader.d.ts +7 -0
- package/dist/resource-loader.js +42 -9
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/gsd/auto/loop.js +19 -0
- package/dist/resources/extensions/gsd/auto/phases.js +1 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +232 -49
- package/dist/resources/extensions/gsd/auto-worktree.js +2 -54
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -15
- package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -1
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/gsd/worktree-post-create-hook.js +117 -0
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/shared/package-manager-detection.js +36 -0
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +7 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/chunks/1834.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/package.json +0 -1
- package/dist/worktree-cli.d.ts +0 -2
- package/dist/worktree-cli.js +21 -9
- package/package.json +5 -2
- package/packages/cloud-mcp-gateway/bin/gsd-cloud-mcp-gateway.js +14 -0
- package/packages/cloud-mcp-gateway/package.json +4 -3
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/bin/gsd-mcp-server.js +14 -0
- package/packages/mcp-server/dist/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +13 -13
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/bin/pi-ai.js +14 -0
- package/packages/pi-ai/dist/models.generated.d.ts +40 -17
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +49 -30
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +50 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +5 -3
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/package.json +8 -8
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/deps.js +10 -0
- package/scripts/install/detect-existing.js +17 -3
- package/scripts/install/npm-global.js +103 -33
- package/scripts/install.js +1 -0
- package/src/resources/extensions/context7/index.ts +15 -2
- package/src/resources/extensions/gsd/auto/loop.ts +22 -0
- package/src/resources/extensions/gsd/auto/phases.ts +1 -1
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-start.ts +307 -56
- package/src/resources/extensions/gsd/auto-worktree.ts +2 -56
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -15
- package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +141 -1
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +56 -4
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/gsd/worktree-post-create-hook.ts +127 -0
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/shared/package-manager-detection.ts +39 -0
- package/dist/tsconfig.extensions.tsbuildinfo +0 -1
- /package/dist/web/standalone/.next/static/{-P554bKh56nzavKUmvFM2 → mijI90BL1BdUcMUnhC0HU}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{-P554bKh56nzavKUmvFM2 → mijI90BL1BdUcMUnhC0HU}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AssistantMessageDiagnostic } from \"./utils/diagnostics.js\";\nimport type { AssistantMessageEventStream } from \"./utils/event-stream.js\";\n\nexport type { AssistantMessageEventStream } from \"./utils/event-stream.js\";\n\nexport type KnownApi =\n\t| \"openai-completions\"\n\t| \"mistral-conversations\"\n\t| \"openai-responses\"\n\t| \"azure-openai-responses\"\n\t| \"openai-codex-responses\"\n\t| \"anthropic-messages\"\n\t| \"bedrock-converse-stream\"\n\t| \"google-generative-ai\"\n\t| \"google-vertex\";\n\nexport type Api = KnownApi | (string & {});\n\nexport type KnownImagesApi = \"openrouter-images\";\n\nexport type ImagesApi = KnownImagesApi | (string & {});\n\nexport type KnownProvider =\n\t| \"amazon-bedrock\"\n\t| \"anthropic\"\n\t| \"google\"\n\t| \"google-vertex\"\n\t| \"openai\"\n\t| \"azure-openai-responses\"\n\t| \"openai-codex\"\n\t| \"deepseek\"\n\t| \"github-copilot\"\n\t| \"xai\"\n\t| \"groq\"\n\t| \"cerebras\"\n\t| \"openrouter\"\n\t| \"vercel-ai-gateway\"\n\t| \"zai\"\n\t| \"mistral\"\n\t| \"minimax\"\n\t| \"minimax-cn\"\n\t| \"moonshotai\"\n\t| \"moonshotai-cn\"\n\t| \"huggingface\"\n\t| \"fireworks\"\n\t| \"together\"\n\t| \"opencode\"\n\t| \"opencode-go\"\n\t| \"kimi-coding\"\n\t| \"cloudflare-workers-ai\"\n\t| \"cloudflare-ai-gateway\"\n\t| \"xiaomi\"\n\t| \"xiaomi-token-plan-cn\"\n\t| \"xiaomi-token-plan-ams\"\n\t| \"xiaomi-token-plan-sgp\";\nexport type Provider = KnownProvider | string;\n\nexport type KnownImagesProvider = \"openrouter\";\n\nexport type ImagesProvider = KnownImagesProvider | string;\n\nexport type ThinkingLevel = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\nexport type ModelThinkingLevel = \"off\" | ThinkingLevel;\nexport type ThinkingLevelMap = Partial<Record<ModelThinkingLevel, string | null>>;\n\n/** Token budgets for each thinking level (token-based providers only) */\nexport interface ThinkingBudgets {\n\tminimal?: number;\n\tlow?: number;\n\tmedium?: number;\n\thigh?: number;\n}\n\n// Base options all providers share\nexport type CacheRetention = \"none\" | \"short\" | \"long\";\n\nexport type Transport = \"sse\" | \"websocket\" | \"websocket-cached\" | \"auto\";\n\nexport interface ProviderResponse {\n\tstatus: number;\n\theaders: Record<string, string>;\n}\n\nexport interface StreamOptions {\n\ttemperature?: number;\n\tmaxTokens?: number;\n\tsignal?: AbortSignal;\n\tapiKey?: string;\n\t/**\n\t * Preferred transport for providers that support multiple transports.\n\t * Providers that do not support this option ignore it.\n\t */\n\ttransport?: Transport;\n\t/**\n\t * Prompt cache retention preference. Providers map this to their supported values.\n\t * Default: \"short\".\n\t */\n\tcacheRetention?: CacheRetention;\n\t/**\n\t * Optional session identifier for providers that support session-based caching.\n\t * Providers can use this to enable prompt caching, request routing, or other\n\t * session-aware features. Ignored by providers that don't support it.\n\t */\n\tsessionId?: string;\n\t/**\n\t * Optional callback for inspecting or replacing provider payloads before sending.\n\t * Return undefined to keep the payload unchanged.\n\t */\n\tonPayload?: (payload: unknown, model: Model<Api>) => unknown | undefined | Promise<unknown | undefined>;\n\t/**\n\t * Optional callback invoked after an HTTP response is received and before\n\t * its body stream is consumed.\n\t */\n\tonResponse?: (response: ProviderResponse, model: Model<Api>) => void | Promise<void>;\n\t/**\n\t * Optional custom HTTP headers to include in API requests.\n\t * Merged with provider defaults; can override default headers.\n\t * Not supported by all providers (e.g., AWS Bedrock uses SDK auth).\n\t */\n\theaders?: Record<string, string>;\n\t/**\n\t * HTTP request timeout in milliseconds for providers/SDKs that support it.\n\t * For example, OpenAI and Anthropic SDK clients default to 10 minutes.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum retry attempts for providers/SDKs that support client-side retries.\n\t * For example, OpenAI and Anthropic SDK clients default to 2.\n\t */\n\tmaxRetries?: number;\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately\n\t * with an error containing the requested delay, allowing higher-level retry logic\n\t * to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n\t/**\n\t * Optional metadata to include in API requests.\n\t * Providers extract the fields they understand and ignore the rest.\n\t * For example, Anthropic uses `user_id` for abuse tracking and rate limiting.\n\t */\n\tmetadata?: Record<string, unknown>;\n}\n\nexport type ProviderStreamOptions = StreamOptions & Record<string, unknown>;\n\nexport interface ImagesOptions {\n\tsignal?: AbortSignal;\n\tapiKey?: string;\n\t/**\n\t * Optional callback for inspecting or replacing provider payloads before sending.\n\t * Return undefined to keep the payload unchanged.\n\t */\n\tonPayload?: (payload: unknown, model: ImagesModel<ImagesApi>) => unknown | undefined | Promise<unknown | undefined>;\n\t/**\n\t * Optional callback invoked after an HTTP response is received.\n\t */\n\tonResponse?: (response: ProviderResponse, model: ImagesModel<ImagesApi>) => void | Promise<void>;\n\t/**\n\t * Optional custom HTTP headers to include in API requests.\n\t * Merged with provider defaults; can override default headers.\n\t */\n\theaders?: Record<string, string>;\n\t/**\n\t * HTTP request timeout in milliseconds for providers/SDKs that support it.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum retry attempts for providers/SDKs that support client-side retries.\n\t */\n\tmaxRetries?: number;\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately\n\t * with an error containing the requested delay, allowing higher-level retry logic\n\t * to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n\t/**\n\t * Optional metadata to include in API requests.\n\t * Providers extract the fields they understand and ignore the rest.\n\t */\n\tmetadata?: Record<string, unknown>;\n}\n\nexport type ProviderImagesOptions = ImagesOptions & Record<string, unknown>;\n\n// Unified options with reasoning passed to streamSimple() and completeSimple()\nexport interface SimpleStreamOptions extends StreamOptions {\n\t/** Workspace root for providers that spawn local processes. */\n\tcwd?: string;\n\treasoning?: ThinkingLevel;\n\t/** Custom token budgets for thinking levels (token-based providers only) */\n\tthinkingBudgets?: ThinkingBudgets;\n}\n\n// Generic StreamFunction with typed options.\n//\n// Contract:\n// - Must return an AssistantMessageEventStream.\n// - Once invoked, request/model/runtime failures should be encoded in the\n// returned stream, not thrown.\n// - Error termination must produce an AssistantMessage with stopReason\n// \"error\" or \"aborted\" and errorMessage, emitted via the stream protocol.\nexport type StreamFunction<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> = (\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: TOptions,\n) => AssistantMessageEventStream;\n\nexport type ImagesFunction<TApi extends ImagesApi = ImagesApi, TOptions extends ImagesOptions = ImagesOptions> = (\n\tmodel: ImagesModel<TApi>,\n\tcontext: ImagesContext,\n\toptions?: TOptions,\n) => Promise<AssistantImages>;\n\nexport interface TextSignatureV1 {\n\tv: 1;\n\tid: string;\n\tphase?: \"commentary\" | \"final_answer\";\n}\n\nexport interface TextContent {\n\ttype: \"text\";\n\ttext: string;\n\ttextSignature?: string; // e.g., for OpenAI responses, message metadata (legacy id string or TextSignatureV1 JSON)\n}\n\nexport interface ThinkingContent {\n\ttype: \"thinking\";\n\tthinking: string;\n\tthinkingSignature?: string; // e.g., for OpenAI responses, the reasoning item ID\n\t/** When true, the thinking content was redacted by safety filters. The opaque\n\t * encrypted payload is stored in `thinkingSignature` so it can be passed back\n\t * to the API for multi-turn continuity. */\n\tredacted?: boolean;\n}\n\nexport interface ImageContent {\n\ttype: \"image\";\n\tdata: string; // base64 encoded image data\n\tmimeType: string; // e.g., \"image/jpeg\", \"image/png\"\n}\n\nexport interface ToolCall {\n\ttype: \"toolCall\";\n\tid: string;\n\tname: string;\n\targuments: Record<string, any>;\n\tthoughtSignature?: string; // Google-specific: opaque signature for reusing thought context\n\t/** Result from an externally executed tool (e.g. Claude Code SDK). Skips local dispatch. */\n\texternalResult?: {\n\t\tcontent?: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: Record<string, unknown>;\n\t\tisError?: boolean;\n\t};\n}\n\n/** GSD compat: server-side tool invocation block (e.g. web search). */\nexport interface ServerToolUse {\n\ttype: \"serverToolUse\";\n\tid: string;\n\tname: string;\n\tinput: unknown;\n\texternalResult?: {\n\t\tcontent?: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: Record<string, unknown>;\n\t\tisError?: boolean;\n\t};\n}\n\n/** GSD compat: server-side tool result block paired with serverToolUse. */\nexport interface WebSearchResult {\n\ttype: \"webSearchResult\";\n\ttoolUseId: string;\n\tcontent: unknown;\n}\n\n/** GSD compat alias for {@link ServerToolUse}. */\nexport type ServerToolUseContent = ServerToolUse;\n\n/** GSD compat alias for {@link WebSearchResult}. */\nexport type WebSearchResultContent = WebSearchResult;\n\nexport interface Usage {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotalTokens: number;\n\tcost: {\n\t\tinput: number;\n\t\toutput: number;\n\t\tcacheRead: number;\n\t\tcacheWrite: number;\n\t\ttotal: number;\n\t};\n}\n\nexport type StopReason = \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\";\n\nexport interface UserMessage {\n\trole: \"user\";\n\tcontent: string | (TextContent | ImageContent)[];\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport interface AssistantMessage {\n\trole: \"assistant\";\n\tcontent: (TextContent | ThinkingContent | ToolCall | ServerToolUse | WebSearchResult)[];\n\tapi: Api;\n\tprovider: Provider;\n\tmodel: string;\n\tresponseModel?: string; // Concrete `chunk.model` when different from the requested `model` (e.g. OpenRouter `auto` -> `anthropic/...`)\n\tresponseId?: string; // Provider-specific response/message identifier when the upstream API exposes one\n\tdiagnostics?: AssistantMessageDiagnostic[]; // Redacted provider/runtime diagnostics for failures and recoveries.\n\tusage: Usage;\n\tstopReason: StopReason;\n\terrorMessage?: string;\n\t/** Server-requested retry delay in milliseconds (from Retry-After or rate limit headers). */\n\tretryAfterMs?: number;\n\t/** Provider inference performance metrics (e.g. tokens/sec from local models). */\n\tinferenceMetrics?: InferenceMetrics;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\n/** Inference performance metrics reported by providers that support it (e.g. Ollama). */\nexport interface InferenceMetrics {\n\t/** Tokens generated per second during eval phase. */\n\ttokensPerSecond: number;\n\t/** Wall-clock duration of the full request in milliseconds. */\n\ttotalDurationMs: number;\n\t/** Duration of the eval (generation) phase in milliseconds. */\n\tevalDurationMs: number;\n\t/** Duration of the prompt eval phase in milliseconds. */\n\tpromptEvalDurationMs: number;\n}\n\nexport interface ToolResultMessage<TDetails = any> {\n\trole: \"toolResult\";\n\ttoolCallId: string;\n\ttoolName: string;\n\tcontent: (TextContent | ImageContent)[]; // Supports text and images\n\tdetails?: TDetails;\n\tisError: boolean;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport type Message = UserMessage | AssistantMessage | ToolResultMessage;\n\nexport type ImagesInputContent = TextContent | ImageContent;\nexport type ImagesOutputContent = TextContent | ImageContent;\n\nexport interface ImagesContext {\n\tinput: ImagesInputContent[];\n}\n\nexport type ImagesStopReason = \"stop\" | \"error\" | \"aborted\";\n\nexport interface AssistantImages {\n\tapi: ImagesApi;\n\tprovider: ImagesProvider;\n\tmodel: string;\n\toutput: ImagesOutputContent[];\n\tresponseId?: string;\n\tusage?: Usage;\n\tstopReason: ImagesStopReason;\n\terrorMessage?: string;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nimport type { TSchema } from \"typebox\";\n\nexport interface Tool<TParameters extends TSchema = TSchema> {\n\tname: string;\n\tdescription: string;\n\tparameters: TParameters;\n}\n\nexport interface Context {\n\tsystemPrompt?: string;\n\tmessages: Message[];\n\ttools?: Tool[];\n}\n\n/**\n * Event protocol for AssistantMessageEventStream.\n *\n * Streams should emit `start` before partial updates, then terminate with either:\n * - `done` carrying the final successful AssistantMessage, or\n * - `error` carrying the final AssistantMessage with stopReason \"error\" or \"aborted\"\n * and errorMessage.\n */\nexport type AssistantMessageEvent =\n\t| { type: \"start\"; partial: AssistantMessage }\n\t| { type: \"text_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| { type: \"text_end\"; contentIndex: number; content: string; partial: AssistantMessage }\n\t| { type: \"thinking_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| { type: \"thinking_end\"; contentIndex: number; content: string; partial: AssistantMessage }\n\t| { type: \"toolcall_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| {\n\t\t\ttype: \"toolcall_end\";\n\t\t\tcontentIndex: number;\n\t\t\ttoolCall: ToolCall;\n\t\t\tpartial: AssistantMessage;\n\t\t\tmalformedArguments?: boolean;\n\t }\n\t| { type: \"server_tool_use\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"done\"; reason: Extract<StopReason, \"stop\" | \"length\" | \"toolUse\">; message: AssistantMessage }\n\t| { type: \"error\"; reason: Extract<StopReason, \"aborted\" | \"error\">; error: AssistantMessage };\n\n/**\n * Compatibility settings for OpenAI-compatible completions APIs.\n * Use this to override URL-based auto-detection for custom providers.\n */\nexport interface OpenAICompletionsCompat {\n\t/** Whether the provider supports the `store` field. Default: auto-detected from URL. */\n\tsupportsStore?: boolean;\n\t/** Whether the provider supports the `developer` role (vs `system`). Default: auto-detected from URL. */\n\tsupportsDeveloperRole?: boolean;\n\t/** Whether the provider supports `reasoning_effort`. Default: auto-detected from URL. */\n\tsupportsReasoningEffort?: boolean;\n\t/** Whether the provider supports `stream_options: { include_usage: true }` for token usage in streaming responses. Default: true. */\n\tsupportsUsageInStreaming?: boolean;\n\t/** Which field to use for max tokens. Default: auto-detected from URL. */\n\tmaxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n\t/** Whether tool results require the `name` field. Default: auto-detected from URL. */\n\trequiresToolResultName?: boolean;\n\t/** Whether a user message after tool results requires an assistant message in between. Default: auto-detected from URL. */\n\trequiresAssistantAfterToolResult?: boolean;\n\t/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */\n\trequiresThinkingAsText?: boolean;\n\t/** Whether all replayed assistant messages must include an empty reasoning_content field when reasoning is enabled. Default: auto-detected from URL. */\n\trequiresReasoningContentOnAssistantMessages?: boolean;\n\t/** Format for reasoning/thinking parameter. \"openai\" uses reasoning_effort, \"openrouter\" uses reasoning: { effort }, \"deepseek\" uses thinking: { type } plus reasoning_effort, \"together\" uses reasoning: { enabled } plus reasoning_effort when supported, \"zai\" uses top-level enable_thinking: boolean, \"qwen\" uses top-level enable_thinking: boolean, and \"qwen-chat-template\" uses chat_template_kwargs.enable_thinking. Default: \"openai\". */\n\tthinkingFormat?: \"openai\" | \"openrouter\" | \"deepseek\" | \"together\" | \"zai\" | \"qwen\" | \"qwen-chat-template\";\n\t/** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */\n\topenRouterRouting?: OpenRouterRouting;\n\t/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */\n\tvercelGatewayRouting?: VercelGatewayRouting;\n\t/** Whether z.ai supports top-level `tool_stream: true` for streaming tool call deltas. Default: false. */\n\tzaiToolStream?: boolean;\n\t/** Whether the provider supports the `strict` field in tool definitions. Default: true. */\n\tsupportsStrictMode?: boolean;\n\t/** Cache control convention for prompt caching. \"anthropic\" applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user/assistant text content. */\n\tcacheControlFormat?: \"anthropic\";\n\t/** Whether to send known session-affinity headers (`session_id`, `x-client-request-id`, `x-session-affinity`) from `options.sessionId` when caching is enabled. Default: false. */\n\tsendSessionAffinityHeaders?: boolean;\n\t/** Whether the provider supports long prompt cache retention (`prompt_cache_retention: \"24h\"` or Anthropic-style `cache_control.ttl: \"1h\"`, depending on format). Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n}\n\n/** Compatibility settings for OpenAI Responses APIs. */\nexport interface OpenAIResponsesCompat {\n\t/** Whether to send the OpenAI `session_id` cache-affinity header from `options.sessionId` when caching is enabled. Default: true. */\n\tsendSessionIdHeader?: boolean;\n\t/** Whether the provider supports `prompt_cache_retention: \"24h\"`. Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n}\n\n/** Compatibility settings for Anthropic Messages-compatible APIs. */\nexport interface AnthropicMessagesCompat {\n\t/**\n\t * Whether the provider accepts per-tool `eager_input_streaming`.\n\t * When false, the Anthropic provider omits `tools[].eager_input_streaming`\n\t * and sends the legacy `fine-grained-tool-streaming-2025-05-14` beta header\n\t * for tool-enabled requests.\n\t * Default: true.\n\t */\n\tsupportsEagerToolInputStreaming?: boolean;\n\t/** Whether the provider supports Anthropic long cache retention (`cache_control.ttl: \"1h\"`). Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n\t/**\n\t * Whether to send the `x-session-affinity` header from `options.sessionId`\n\t * when caching is enabled. Required for providers like Fireworks that use\n\t * session affinity for prompt cache routing (requests to the same replica\n\t * maximize cache hits).\n\t * Default: false.\n\t */\n\tsendSessionAffinityHeaders?: boolean;\n\t/**\n\t * Whether the provider supports Anthropic-style `cache_control` markers on\n\t * tool definitions. When false, `cache_control` is omitted from tool params.\n\t * Some Anthropic-compatible providers (e.g., Fireworks) do not support this\n\t * field on tools and may reject or ignore it.\n\t * Default: true.\n\t */\n\tsupportsCacheControlOnTools?: boolean;\n\t/**\n\t * Whether to force adaptive thinking (`thinking.type: \"adaptive\"` plus\n\t * `output_config.effort`) regardless of the model id. Built-in models that\n\t * require adaptive thinking set this in generated metadata. Custom\n\t * Anthropic-compatible providers can set this to `true` for any model whose\n\t * upstream requires the adaptive format. Set to `false` to\n\t * opt out on overridden built-in models.\n\t * Default: false.\n\t */\n\tforceAdaptiveThinking?: boolean;\n}\n\n/**\n * OpenRouter provider routing preferences.\n * Controls which upstream providers OpenRouter routes requests to.\n * Sent as the `provider` field in the OpenRouter API request body.\n * @see https://openrouter.ai/docs/guides/routing/provider-selection\n */\nexport interface OpenRouterRouting {\n\t/** Whether to allow backup providers to serve requests. Default: true. */\n\tallow_fallbacks?: boolean;\n\t/** Whether to filter providers to only those that support all parameters in the request. Default: false. */\n\trequire_parameters?: boolean;\n\t/** Data collection setting. \"allow\" (default): allow providers that may store/train on data. \"deny\": only use providers that don't collect user data. */\n\tdata_collection?: \"deny\" | \"allow\";\n\t/** Whether to restrict routing to only ZDR (Zero Data Retention) endpoints. */\n\tzdr?: boolean;\n\t/** Whether to restrict routing to only models that allow text distillation. */\n\tenforce_distillable_text?: boolean;\n\t/** An ordered list of provider names/slugs to try in sequence, falling back to the next if unavailable. */\n\torder?: string[];\n\t/** List of provider names/slugs to exclusively allow for this request. */\n\tonly?: string[];\n\t/** List of provider names/slugs to skip for this request. */\n\tignore?: string[];\n\t/** A list of quantization levels to filter providers by (e.g., [\"fp16\", \"bf16\", \"fp8\", \"fp6\", \"int8\", \"int4\", \"fp4\", \"fp32\"]). */\n\tquantizations?: string[];\n\t/** Sorting strategy. Can be a string (e.g., \"price\", \"throughput\", \"latency\") or an object with `by` and `partition`. */\n\tsort?:\n\t\t| string\n\t\t| {\n\t\t\t\t/** The sorting metric: \"price\", \"throughput\", \"latency\". */\n\t\t\t\tby?: string;\n\t\t\t\t/** Partitioning strategy: \"model\" (default) or \"none\". */\n\t\t\t\tpartition?: string | null;\n\t\t };\n\t/** Maximum price per million tokens (USD). */\n\tmax_price?: {\n\t\t/** Price per million prompt tokens. */\n\t\tprompt?: number | string;\n\t\t/** Price per million completion tokens. */\n\t\tcompletion?: number | string;\n\t\t/** Price per image. */\n\t\timage?: number | string;\n\t\t/** Price per audio unit. */\n\t\taudio?: number | string;\n\t\t/** Price per request. */\n\t\trequest?: number | string;\n\t};\n\t/** Preferred minimum throughput (tokens/second). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */\n\tpreferred_min_throughput?:\n\t\t| number\n\t\t| {\n\t\t\t\t/** Minimum tokens/second at the 50th percentile. */\n\t\t\t\tp50?: number;\n\t\t\t\t/** Minimum tokens/second at the 75th percentile. */\n\t\t\t\tp75?: number;\n\t\t\t\t/** Minimum tokens/second at the 90th percentile. */\n\t\t\t\tp90?: number;\n\t\t\t\t/** Minimum tokens/second at the 99th percentile. */\n\t\t\t\tp99?: number;\n\t\t };\n\t/** Preferred maximum latency (seconds). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */\n\tpreferred_max_latency?:\n\t\t| number\n\t\t| {\n\t\t\t\t/** Maximum latency in seconds at the 50th percentile. */\n\t\t\t\tp50?: number;\n\t\t\t\t/** Maximum latency in seconds at the 75th percentile. */\n\t\t\t\tp75?: number;\n\t\t\t\t/** Maximum latency in seconds at the 90th percentile. */\n\t\t\t\tp90?: number;\n\t\t\t\t/** Maximum latency in seconds at the 99th percentile. */\n\t\t\t\tp99?: number;\n\t\t };\n}\n\n/**\n * Vercel AI Gateway routing preferences.\n * Controls which upstream providers the gateway routes requests to.\n * @see https://vercel.com/docs/ai-gateway/models-and-providers/provider-options\n */\nexport interface VercelGatewayRouting {\n\t/** List of provider slugs to exclusively use for this request (e.g., [\"bedrock\", \"anthropic\"]). */\n\tonly?: string[];\n\t/** List of provider slugs to try in order (e.g., [\"anthropic\", \"openai\"]). */\n\torder?: string[];\n}\n\n// Model interface for the unified model system\nexport interface Model<TApi extends Api> {\n\tid: string;\n\tname: string;\n\tapi: TApi;\n\tprovider: Provider;\n\tbaseUrl: string;\n\treasoning: boolean;\n\t/**\n\t * Maps pi thinking levels to provider/model-specific values.\n\t * Missing keys use provider defaults. null marks a level as unsupported.\n\t */\n\tthinkingLevelMap?: ThinkingLevelMap;\n\tinput: (\"text\" | \"image\")[];\n\tcost: {\n\t\tinput: number; // $/million tokens\n\t\toutput: number; // $/million tokens\n\t\tcacheRead: number; // $/million tokens\n\t\tcacheWrite: number; // $/million tokens\n\t};\n\tcontextWindow: number;\n\tmaxTokens: number;\n\theaders?: Record<string, string>;\n\t/** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */\n\tcompat?: TApi extends \"openai-completions\"\n\t\t? OpenAICompletionsCompat\n\t\t: TApi extends \"openai-responses\"\n\t\t\t? OpenAIResponsesCompat\n\t\t\t: TApi extends \"anthropic-messages\"\n\t\t\t\t? AnthropicMessagesCompat\n\t\t\t\t: never;\n\t/** Provider-specific options passed through to stream handlers. */\n\tproviderOptions?: Record<string, unknown>;\n}\n\nexport interface ImagesModel<TApi extends ImagesApi>\n\textends Omit<Model<Api>, \"api\" | \"provider\" | \"reasoning\" | \"contextWindow\" | \"maxTokens\" | \"compat\"> {\n\tapi: TApi;\n\tprovider: ImagesProvider;\n\toutput: (\"text\" | \"image\")[];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AssistantMessageDiagnostic } from \"./utils/diagnostics.js\";\nimport type { AssistantMessageEventStream } from \"./utils/event-stream.js\";\n\nexport type { AssistantMessageEventStream } from \"./utils/event-stream.js\";\n\nexport type KnownApi =\n\t| \"openai-completions\"\n\t| \"mistral-conversations\"\n\t| \"openai-responses\"\n\t| \"azure-openai-responses\"\n\t| \"openai-codex-responses\"\n\t| \"anthropic-messages\"\n\t| \"bedrock-converse-stream\"\n\t| \"google-generative-ai\"\n\t| \"google-vertex\";\n\nexport type Api = KnownApi | (string & {});\n\nexport type KnownImagesApi = \"openrouter-images\";\n\nexport type ImagesApi = KnownImagesApi | (string & {});\n\nexport type KnownProvider =\n\t| \"amazon-bedrock\"\n\t| \"anthropic\"\n\t| \"google\"\n\t| \"google-vertex\"\n\t| \"openai\"\n\t| \"azure-openai-responses\"\n\t| \"openai-codex\"\n\t| \"deepseek\"\n\t| \"github-copilot\"\n\t| \"xai\"\n\t| \"groq\"\n\t| \"cerebras\"\n\t| \"openrouter\"\n\t| \"vercel-ai-gateway\"\n\t| \"zai\"\n\t| \"mistral\"\n\t| \"minimax\"\n\t| \"minimax-cn\"\n\t| \"moonshotai\"\n\t| \"moonshotai-cn\"\n\t| \"huggingface\"\n\t| \"fireworks\"\n\t| \"together\"\n\t| \"opencode\"\n\t| \"opencode-go\"\n\t| \"kimi-coding\"\n\t| \"cloudflare-workers-ai\"\n\t| \"cloudflare-ai-gateway\"\n\t| \"xiaomi\"\n\t| \"xiaomi-token-plan-cn\"\n\t| \"xiaomi-token-plan-ams\"\n\t| \"xiaomi-token-plan-sgp\";\nexport type Provider = KnownProvider | string;\n\nexport type KnownImagesProvider = \"openrouter\";\n\nexport type ImagesProvider = KnownImagesProvider | string;\n\nexport type ThinkingLevel = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\nexport type ModelThinkingLevel = \"off\" | ThinkingLevel;\nexport type ThinkingLevelMap = Partial<Record<ModelThinkingLevel, string | null>>;\n\n/** Token budgets for each thinking level (token-based providers only) */\nexport interface ThinkingBudgets {\n\tminimal?: number;\n\tlow?: number;\n\tmedium?: number;\n\thigh?: number;\n}\n\n// Base options all providers share\nexport type CacheRetention = \"none\" | \"short\" | \"long\";\n\nexport type Transport = \"sse\" | \"websocket\" | \"websocket-cached\" | \"auto\";\n\nexport interface ProviderResponse {\n\tstatus: number;\n\theaders: Record<string, string>;\n}\n\nexport interface StreamOptions {\n\ttemperature?: number;\n\tmaxTokens?: number;\n\tsignal?: AbortSignal;\n\tapiKey?: string;\n\t/**\n\t * Preferred transport for providers that support multiple transports.\n\t * Providers that do not support this option ignore it.\n\t */\n\ttransport?: Transport;\n\t/**\n\t * Prompt cache retention preference. Providers map this to their supported values.\n\t * Default: \"short\".\n\t */\n\tcacheRetention?: CacheRetention;\n\t/**\n\t * Optional session identifier for providers that support session-based caching.\n\t * Providers can use this to enable prompt caching, request routing, or other\n\t * session-aware features. Ignored by providers that don't support it.\n\t */\n\tsessionId?: string;\n\t/**\n\t * Optional callback for inspecting or replacing provider payloads before sending.\n\t * Return undefined to keep the payload unchanged.\n\t */\n\tonPayload?: (payload: unknown, model: Model<Api>) => unknown | undefined | Promise<unknown | undefined>;\n\t/**\n\t * Optional callback invoked after an HTTP response is received and before\n\t * its body stream is consumed.\n\t */\n\tonResponse?: (response: ProviderResponse, model: Model<Api>) => void | Promise<void>;\n\t/**\n\t * Optional custom HTTP headers to include in API requests.\n\t * Merged with provider defaults; can override default headers.\n\t * Not supported by all providers (e.g., AWS Bedrock uses SDK auth).\n\t */\n\theaders?: Record<string, string>;\n\t/**\n\t * HTTP request timeout in milliseconds for providers/SDKs that support it.\n\t * For example, OpenAI and Anthropic SDK clients default to 10 minutes.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum retry attempts for providers/SDKs that support client-side retries.\n\t * For example, OpenAI and Anthropic SDK clients default to 2.\n\t */\n\tmaxRetries?: number;\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately\n\t * with an error containing the requested delay, allowing higher-level retry logic\n\t * to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n\t/**\n\t * Optional metadata to include in API requests.\n\t * Providers extract the fields they understand and ignore the rest.\n\t * For example, Anthropic uses `user_id` for abuse tracking and rate limiting.\n\t */\n\tmetadata?: Record<string, unknown>;\n}\n\nexport type ProviderStreamOptions = StreamOptions & Record<string, unknown>;\n\nexport interface ImagesOptions {\n\tsignal?: AbortSignal;\n\tapiKey?: string;\n\t/**\n\t * Optional callback for inspecting or replacing provider payloads before sending.\n\t * Return undefined to keep the payload unchanged.\n\t */\n\tonPayload?: (payload: unknown, model: ImagesModel<ImagesApi>) => unknown | undefined | Promise<unknown | undefined>;\n\t/**\n\t * Optional callback invoked after an HTTP response is received.\n\t */\n\tonResponse?: (response: ProviderResponse, model: ImagesModel<ImagesApi>) => void | Promise<void>;\n\t/**\n\t * Optional custom HTTP headers to include in API requests.\n\t * Merged with provider defaults; can override default headers.\n\t */\n\theaders?: Record<string, string>;\n\t/**\n\t * HTTP request timeout in milliseconds for providers/SDKs that support it.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum retry attempts for providers/SDKs that support client-side retries.\n\t */\n\tmaxRetries?: number;\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately\n\t * with an error containing the requested delay, allowing higher-level retry logic\n\t * to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n\t/**\n\t * Optional metadata to include in API requests.\n\t * Providers extract the fields they understand and ignore the rest.\n\t */\n\tmetadata?: Record<string, unknown>;\n}\n\nexport type ProviderImagesOptions = ImagesOptions & Record<string, unknown>;\n\n// Unified options with reasoning passed to streamSimple() and completeSimple()\nexport interface SimpleStreamOptions extends StreamOptions {\n\t/** Workspace root for providers that spawn local processes. */\n\tcwd?: string;\n\treasoning?: ThinkingLevel;\n\t/** Custom token budgets for thinking levels (token-based providers only) */\n\tthinkingBudgets?: ThinkingBudgets;\n}\n\n// Generic StreamFunction with typed options.\n//\n// Contract:\n// - Must return an AssistantMessageEventStream.\n// - Once invoked, request/model/runtime failures should be encoded in the\n// returned stream, not thrown.\n// - Error termination must produce an AssistantMessage with stopReason\n// \"error\" or \"aborted\" and errorMessage, emitted via the stream protocol.\nexport type StreamFunction<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> = (\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: TOptions,\n) => AssistantMessageEventStream;\n\nexport type ImagesFunction<TApi extends ImagesApi = ImagesApi, TOptions extends ImagesOptions = ImagesOptions> = (\n\tmodel: ImagesModel<TApi>,\n\tcontext: ImagesContext,\n\toptions?: TOptions,\n) => Promise<AssistantImages>;\n\nexport interface TextSignatureV1 {\n\tv: 1;\n\tid: string;\n\tphase?: \"commentary\" | \"final_answer\";\n}\n\nexport interface TextContent {\n\ttype: \"text\";\n\ttext: string;\n\ttextSignature?: string; // e.g., for OpenAI responses, message metadata (legacy id string or TextSignatureV1 JSON)\n}\n\nexport interface ThinkingContent {\n\ttype: \"thinking\";\n\tthinking: string;\n\tthinkingSignature?: string; // e.g., for OpenAI responses, the reasoning item ID\n\t/** When true, the thinking content was redacted by safety filters. The opaque\n\t * encrypted payload is stored in `thinkingSignature` so it can be passed back\n\t * to the API for multi-turn continuity. */\n\tredacted?: boolean;\n}\n\nexport interface ImageContent {\n\ttype: \"image\";\n\tdata: string; // base64 encoded image data\n\tmimeType: string; // e.g., \"image/jpeg\", \"image/png\"\n}\n\nexport interface ToolCall {\n\ttype: \"toolCall\";\n\tid: string;\n\tname: string;\n\targuments: Record<string, any>;\n\tthoughtSignature?: string; // Google-specific: opaque signature for reusing thought context\n\t/** Result from an externally executed tool (e.g. Claude Code SDK). Skips local dispatch. */\n\texternalResult?: {\n\t\tcontent?: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: Record<string, unknown>;\n\t\tisError?: boolean;\n\t};\n}\n\n/** GSD compat: server-side tool invocation block (e.g. web search). */\nexport interface ServerToolUse {\n\ttype: \"serverToolUse\";\n\tid: string;\n\tname: string;\n\tinput: unknown;\n\tcaller?: unknown;\n\texternalResult?: {\n\t\tcontent?: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: Record<string, unknown>;\n\t\tisError?: boolean;\n\t};\n}\n\n/** GSD compat: server-side tool result block paired with serverToolUse. */\nexport interface WebSearchResult {\n\ttype: \"webSearchResult\";\n\ttoolUseId: string;\n\tcontent: unknown;\n\tcaller?: unknown;\n}\n\n/** GSD compat alias for {@link ServerToolUse}. */\nexport type ServerToolUseContent = ServerToolUse;\n\n/** GSD compat alias for {@link WebSearchResult}. */\nexport type WebSearchResultContent = WebSearchResult;\n\nexport interface Usage {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotalTokens: number;\n\tcost: {\n\t\tinput: number;\n\t\toutput: number;\n\t\tcacheRead: number;\n\t\tcacheWrite: number;\n\t\ttotal: number;\n\t};\n}\n\nexport type StopReason = \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\";\n\nexport interface UserMessage {\n\trole: \"user\";\n\tcontent: string | (TextContent | ImageContent)[];\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport interface AssistantMessage {\n\trole: \"assistant\";\n\tcontent: (TextContent | ThinkingContent | ToolCall | ServerToolUse | WebSearchResult)[];\n\tapi: Api;\n\tprovider: Provider;\n\tmodel: string;\n\tresponseModel?: string; // Concrete `chunk.model` when different from the requested `model` (e.g. OpenRouter `auto` -> `anthropic/...`)\n\tresponseId?: string; // Provider-specific response/message identifier when the upstream API exposes one\n\tdiagnostics?: AssistantMessageDiagnostic[]; // Redacted provider/runtime diagnostics for failures and recoveries.\n\tusage: Usage;\n\tstopReason: StopReason;\n\terrorMessage?: string;\n\t/** Server-requested retry delay in milliseconds (from Retry-After or rate limit headers). */\n\tretryAfterMs?: number;\n\t/** Provider inference performance metrics (e.g. tokens/sec from local models). */\n\tinferenceMetrics?: InferenceMetrics;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\n/** Inference performance metrics reported by providers that support it (e.g. Ollama). */\nexport interface InferenceMetrics {\n\t/** Tokens generated per second during eval phase. */\n\ttokensPerSecond: number;\n\t/** Wall-clock duration of the full request in milliseconds. */\n\ttotalDurationMs: number;\n\t/** Duration of the eval (generation) phase in milliseconds. */\n\tevalDurationMs: number;\n\t/** Duration of the prompt eval phase in milliseconds. */\n\tpromptEvalDurationMs: number;\n}\n\nexport interface ToolResultMessage<TDetails = any> {\n\trole: \"toolResult\";\n\ttoolCallId: string;\n\ttoolName: string;\n\tcontent: (TextContent | ImageContent)[]; // Supports text and images\n\tdetails?: TDetails;\n\tisError: boolean;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nexport type Message = UserMessage | AssistantMessage | ToolResultMessage;\n\nexport type ImagesInputContent = TextContent | ImageContent;\nexport type ImagesOutputContent = TextContent | ImageContent;\n\nexport interface ImagesContext {\n\tinput: ImagesInputContent[];\n}\n\nexport type ImagesStopReason = \"stop\" | \"error\" | \"aborted\";\n\nexport interface AssistantImages {\n\tapi: ImagesApi;\n\tprovider: ImagesProvider;\n\tmodel: string;\n\toutput: ImagesOutputContent[];\n\tresponseId?: string;\n\tusage?: Usage;\n\tstopReason: ImagesStopReason;\n\terrorMessage?: string;\n\ttimestamp: number; // Unix timestamp in milliseconds\n}\n\nimport type { TSchema } from \"typebox\";\n\nexport interface Tool<TParameters extends TSchema = TSchema> {\n\tname: string;\n\tdescription: string;\n\tparameters: TParameters;\n}\n\nexport interface Context {\n\tsystemPrompt?: string;\n\tmessages: Message[];\n\ttools?: Tool[];\n}\n\n/**\n * Event protocol for AssistantMessageEventStream.\n *\n * Streams should emit `start` before partial updates, then terminate with either:\n * - `done` carrying the final successful AssistantMessage, or\n * - `error` carrying the final AssistantMessage with stopReason \"error\" or \"aborted\"\n * and errorMessage.\n */\nexport type AssistantMessageEvent =\n\t| { type: \"start\"; partial: AssistantMessage }\n\t| { type: \"text_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| { type: \"text_end\"; contentIndex: number; content: string; partial: AssistantMessage }\n\t| { type: \"thinking_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| { type: \"thinking_end\"; contentIndex: number; content: string; partial: AssistantMessage }\n\t| { type: \"toolcall_start\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string; partial: AssistantMessage }\n\t| {\n\t\t\ttype: \"toolcall_end\";\n\t\t\tcontentIndex: number;\n\t\t\ttoolCall: ToolCall;\n\t\t\tpartial: AssistantMessage;\n\t\t\tmalformedArguments?: boolean;\n\t }\n\t| { type: \"server_tool_use\"; contentIndex: number; partial: AssistantMessage }\n\t| { type: \"done\"; reason: Extract<StopReason, \"stop\" | \"length\" | \"toolUse\">; message: AssistantMessage }\n\t| { type: \"error\"; reason: Extract<StopReason, \"aborted\" | \"error\">; error: AssistantMessage };\n\n/**\n * Compatibility settings for OpenAI-compatible completions APIs.\n * Use this to override URL-based auto-detection for custom providers.\n */\nexport interface OpenAICompletionsCompat {\n\t/** Whether the provider supports the `store` field. Default: auto-detected from URL. */\n\tsupportsStore?: boolean;\n\t/** Whether the provider supports the `developer` role (vs `system`). Default: auto-detected from URL. */\n\tsupportsDeveloperRole?: boolean;\n\t/** Whether the provider supports `reasoning_effort`. Default: auto-detected from URL. */\n\tsupportsReasoningEffort?: boolean;\n\t/** Whether the provider supports `stream_options: { include_usage: true }` for token usage in streaming responses. Default: true. */\n\tsupportsUsageInStreaming?: boolean;\n\t/** Which field to use for max tokens. Default: auto-detected from URL. */\n\tmaxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n\t/** Whether tool results require the `name` field. Default: auto-detected from URL. */\n\trequiresToolResultName?: boolean;\n\t/** Whether a user message after tool results requires an assistant message in between. Default: auto-detected from URL. */\n\trequiresAssistantAfterToolResult?: boolean;\n\t/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */\n\trequiresThinkingAsText?: boolean;\n\t/** Whether all replayed assistant messages must include an empty reasoning_content field when reasoning is enabled. Default: auto-detected from URL. */\n\trequiresReasoningContentOnAssistantMessages?: boolean;\n\t/** Format for reasoning/thinking parameter. \"openai\" uses reasoning_effort, \"openrouter\" uses reasoning: { effort }, \"deepseek\" uses thinking: { type } plus reasoning_effort, \"together\" uses reasoning: { enabled } plus reasoning_effort when supported, \"zai\" uses top-level enable_thinking: boolean, \"qwen\" uses top-level enable_thinking: boolean, and \"qwen-chat-template\" uses chat_template_kwargs.enable_thinking. Default: \"openai\". */\n\tthinkingFormat?: \"openai\" | \"openrouter\" | \"deepseek\" | \"together\" | \"zai\" | \"qwen\" | \"qwen-chat-template\";\n\t/** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */\n\topenRouterRouting?: OpenRouterRouting;\n\t/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */\n\tvercelGatewayRouting?: VercelGatewayRouting;\n\t/** Whether z.ai supports top-level `tool_stream: true` for streaming tool call deltas. Default: false. */\n\tzaiToolStream?: boolean;\n\t/** Whether the provider supports the `strict` field in tool definitions. Default: true. */\n\tsupportsStrictMode?: boolean;\n\t/** Cache control convention for prompt caching. \"anthropic\" applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user/assistant text content. */\n\tcacheControlFormat?: \"anthropic\";\n\t/** Whether to send known session-affinity headers (`session_id`, `x-client-request-id`, `x-session-affinity`) from `options.sessionId` when caching is enabled. Default: false. */\n\tsendSessionAffinityHeaders?: boolean;\n\t/** Whether the provider supports long prompt cache retention (`prompt_cache_retention: \"24h\"` or Anthropic-style `cache_control.ttl: \"1h\"`, depending on format). Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n}\n\n/** Compatibility settings for OpenAI Responses APIs. */\nexport interface OpenAIResponsesCompat {\n\t/** Whether to send the OpenAI `session_id` cache-affinity header from `options.sessionId` when caching is enabled. Default: true. */\n\tsendSessionIdHeader?: boolean;\n\t/** Whether the provider supports `prompt_cache_retention: \"24h\"`. Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n}\n\n/** Compatibility settings for Anthropic Messages-compatible APIs. */\nexport interface AnthropicMessagesCompat {\n\t/**\n\t * Whether the provider accepts per-tool `eager_input_streaming`.\n\t * When false, the Anthropic provider omits `tools[].eager_input_streaming`\n\t * and sends the legacy `fine-grained-tool-streaming-2025-05-14` beta header\n\t * for tool-enabled requests.\n\t * Default: true.\n\t */\n\tsupportsEagerToolInputStreaming?: boolean;\n\t/** Whether the provider supports Anthropic long cache retention (`cache_control.ttl: \"1h\"`). Default: true. */\n\tsupportsLongCacheRetention?: boolean;\n\t/**\n\t * Whether to send the `x-session-affinity` header from `options.sessionId`\n\t * when caching is enabled. Required for providers like Fireworks that use\n\t * session affinity for prompt cache routing (requests to the same replica\n\t * maximize cache hits).\n\t * Default: false.\n\t */\n\tsendSessionAffinityHeaders?: boolean;\n\t/**\n\t * Whether the provider supports Anthropic-style `cache_control` markers on\n\t * tool definitions. When false, `cache_control` is omitted from tool params.\n\t * Some Anthropic-compatible providers (e.g., Fireworks) do not support this\n\t * field on tools and may reject or ignore it.\n\t * Default: true.\n\t */\n\tsupportsCacheControlOnTools?: boolean;\n\t/**\n\t * Whether to force adaptive thinking (`thinking.type: \"adaptive\"` plus\n\t * `output_config.effort`) regardless of the model id. Built-in models that\n\t * require adaptive thinking set this in generated metadata. Custom\n\t * Anthropic-compatible providers can set this to `true` for any model whose\n\t * upstream requires the adaptive format. Set to `false` to\n\t * opt out on overridden built-in models.\n\t * Default: false.\n\t */\n\tforceAdaptiveThinking?: boolean;\n}\n\n/**\n * OpenRouter provider routing preferences.\n * Controls which upstream providers OpenRouter routes requests to.\n * Sent as the `provider` field in the OpenRouter API request body.\n * @see https://openrouter.ai/docs/guides/routing/provider-selection\n */\nexport interface OpenRouterRouting {\n\t/** Whether to allow backup providers to serve requests. Default: true. */\n\tallow_fallbacks?: boolean;\n\t/** Whether to filter providers to only those that support all parameters in the request. Default: false. */\n\trequire_parameters?: boolean;\n\t/** Data collection setting. \"allow\" (default): allow providers that may store/train on data. \"deny\": only use providers that don't collect user data. */\n\tdata_collection?: \"deny\" | \"allow\";\n\t/** Whether to restrict routing to only ZDR (Zero Data Retention) endpoints. */\n\tzdr?: boolean;\n\t/** Whether to restrict routing to only models that allow text distillation. */\n\tenforce_distillable_text?: boolean;\n\t/** An ordered list of provider names/slugs to try in sequence, falling back to the next if unavailable. */\n\torder?: string[];\n\t/** List of provider names/slugs to exclusively allow for this request. */\n\tonly?: string[];\n\t/** List of provider names/slugs to skip for this request. */\n\tignore?: string[];\n\t/** A list of quantization levels to filter providers by (e.g., [\"fp16\", \"bf16\", \"fp8\", \"fp6\", \"int8\", \"int4\", \"fp4\", \"fp32\"]). */\n\tquantizations?: string[];\n\t/** Sorting strategy. Can be a string (e.g., \"price\", \"throughput\", \"latency\") or an object with `by` and `partition`. */\n\tsort?:\n\t\t| string\n\t\t| {\n\t\t\t\t/** The sorting metric: \"price\", \"throughput\", \"latency\". */\n\t\t\t\tby?: string;\n\t\t\t\t/** Partitioning strategy: \"model\" (default) or \"none\". */\n\t\t\t\tpartition?: string | null;\n\t\t };\n\t/** Maximum price per million tokens (USD). */\n\tmax_price?: {\n\t\t/** Price per million prompt tokens. */\n\t\tprompt?: number | string;\n\t\t/** Price per million completion tokens. */\n\t\tcompletion?: number | string;\n\t\t/** Price per image. */\n\t\timage?: number | string;\n\t\t/** Price per audio unit. */\n\t\taudio?: number | string;\n\t\t/** Price per request. */\n\t\trequest?: number | string;\n\t};\n\t/** Preferred minimum throughput (tokens/second). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */\n\tpreferred_min_throughput?:\n\t\t| number\n\t\t| {\n\t\t\t\t/** Minimum tokens/second at the 50th percentile. */\n\t\t\t\tp50?: number;\n\t\t\t\t/** Minimum tokens/second at the 75th percentile. */\n\t\t\t\tp75?: number;\n\t\t\t\t/** Minimum tokens/second at the 90th percentile. */\n\t\t\t\tp90?: number;\n\t\t\t\t/** Minimum tokens/second at the 99th percentile. */\n\t\t\t\tp99?: number;\n\t\t };\n\t/** Preferred maximum latency (seconds). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */\n\tpreferred_max_latency?:\n\t\t| number\n\t\t| {\n\t\t\t\t/** Maximum latency in seconds at the 50th percentile. */\n\t\t\t\tp50?: number;\n\t\t\t\t/** Maximum latency in seconds at the 75th percentile. */\n\t\t\t\tp75?: number;\n\t\t\t\t/** Maximum latency in seconds at the 90th percentile. */\n\t\t\t\tp90?: number;\n\t\t\t\t/** Maximum latency in seconds at the 99th percentile. */\n\t\t\t\tp99?: number;\n\t\t };\n}\n\n/**\n * Vercel AI Gateway routing preferences.\n * Controls which upstream providers the gateway routes requests to.\n * @see https://vercel.com/docs/ai-gateway/models-and-providers/provider-options\n */\nexport interface VercelGatewayRouting {\n\t/** List of provider slugs to exclusively use for this request (e.g., [\"bedrock\", \"anthropic\"]). */\n\tonly?: string[];\n\t/** List of provider slugs to try in order (e.g., [\"anthropic\", \"openai\"]). */\n\torder?: string[];\n}\n\n// Model interface for the unified model system\nexport interface Model<TApi extends Api> {\n\tid: string;\n\tname: string;\n\tapi: TApi;\n\tprovider: Provider;\n\tbaseUrl: string;\n\treasoning: boolean;\n\t/**\n\t * Maps pi thinking levels to provider/model-specific values.\n\t * Missing keys use provider defaults. null marks a level as unsupported.\n\t */\n\tthinkingLevelMap?: ThinkingLevelMap;\n\tinput: (\"text\" | \"image\")[];\n\tcost: {\n\t\tinput: number; // $/million tokens\n\t\toutput: number; // $/million tokens\n\t\tcacheRead: number; // $/million tokens\n\t\tcacheWrite: number; // $/million tokens\n\t};\n\tcontextWindow: number;\n\tmaxTokens: number;\n\theaders?: Record<string, string>;\n\t/** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */\n\tcompat?: TApi extends \"openai-completions\"\n\t\t? OpenAICompletionsCompat\n\t\t: TApi extends \"openai-responses\"\n\t\t\t? OpenAIResponsesCompat\n\t\t\t: TApi extends \"anthropic-messages\"\n\t\t\t\t? AnthropicMessagesCompat\n\t\t\t\t: never;\n\t/** Provider-specific options passed through to stream handlers. */\n\tproviderOptions?: Record<string, unknown>;\n}\n\nexport interface ImagesModel<TApi extends ImagesApi>\n\textends Omit<Model<Api>, \"api\" | \"provider\" | \"reasoning\" | \"contextWindow\" | \"maxTokens\" | \"compat\"> {\n\tapi: TApi;\n\tprovider: ImagesProvider;\n\toutput: (\"text\" | \"image\")[];\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/pi-ai",
|
|
3
|
-
"version": "1.0.2-dev.
|
|
3
|
+
"version": "1.0.2-dev.2c204d3",
|
|
4
4
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -57,9 +57,10 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"bin": {
|
|
60
|
-
"pi-ai": "./
|
|
60
|
+
"pi-ai": "./bin/pi-ai.js"
|
|
61
61
|
},
|
|
62
62
|
"files": [
|
|
63
|
+
"bin",
|
|
63
64
|
"dist",
|
|
64
65
|
"README.md"
|
|
65
66
|
],
|
|
@@ -13,8 +13,8 @@ export interface ReadToolDetails {
|
|
|
13
13
|
}
|
|
14
14
|
/** Max read output lines shown in the TUI when tool cards are collapsed (errors only). */
|
|
15
15
|
export declare const READ_TUI_COLLAPSED_MAX_LINES = 10;
|
|
16
|
-
/**
|
|
17
|
-
export declare const READ_TUI_EXPANDED_MAX_LINES
|
|
16
|
+
/** Max read output lines shown in the TUI when tool cards are expanded. */
|
|
17
|
+
export declare const READ_TUI_EXPANDED_MAX_LINES = 50;
|
|
18
18
|
export declare function getReadTuiMaxDisplayLines(expanded: boolean): number;
|
|
19
19
|
/**
|
|
20
20
|
* Pluggable operations for the read tool.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKpD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAO5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAItF,OAAO,EAAoD,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEtH,QAAA,MAAM,UAAU;;;;EAId,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AASD,0FAA0F;AAC1F,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKpD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAO5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAItF,OAAO,EAAoD,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEtH,QAAA,MAAM,UAAU;;;;EAId,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AASD,0FAA0F;AAC1F,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,2EAA2E;AAC3E,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAEnE;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,+CAA+C;IAC/C,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,sEAAsE;IACtE,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACnF;AAQD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AAiJD,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,CAAC,CAwJhE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG"}
|
|
@@ -21,8 +21,8 @@ const readSchema = Type.Object({
|
|
|
21
21
|
const COMPACT_RESOURCE_FILE_NAMES = new Set(["AGENTS.md", "AGENTS.MD", "CLAUDE.md", "CLAUDE.MD"]);
|
|
22
22
|
/** Max read output lines shown in the TUI when tool cards are collapsed (errors only). */
|
|
23
23
|
export const READ_TUI_COLLAPSED_MAX_LINES = 10;
|
|
24
|
-
/**
|
|
25
|
-
export const READ_TUI_EXPANDED_MAX_LINES =
|
|
24
|
+
/** Max read output lines shown in the TUI when tool cards are expanded. */
|
|
25
|
+
export const READ_TUI_EXPANDED_MAX_LINES = 50;
|
|
26
26
|
export function getReadTuiMaxDisplayLines(expanded) {
|
|
27
27
|
return expanded ? READ_TUI_EXPANDED_MAX_LINES : READ_TUI_COLLAPSED_MAX_LINES;
|
|
28
28
|
}
|
|
@@ -121,7 +121,9 @@ function formatReadResult(args, result, options, theme, showImages, _cwd, isErro
|
|
|
121
121
|
const remaining = lines.length - maxLines;
|
|
122
122
|
let text = `\n${displayLines.map((line) => (lang ? replaceTabs(line) : theme.fg("toolOutput", replaceTabs(line)))).join("\n")}`;
|
|
123
123
|
if (remaining > 0) {
|
|
124
|
-
text +=
|
|
124
|
+
text += options.expanded
|
|
125
|
+
? theme.fg("muted", `\n... (${remaining} more lines hidden from display)`)
|
|
126
|
+
: `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
125
127
|
}
|
|
126
128
|
const truncation = result.details?.truncation;
|
|
127
129
|
if (truncation?.truncated) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename, dirname, isAbsolute, relative, resolve as resolvePath, sep } from \"node:path\";\nimport type { AgentTool } from \"@gsd/pi-agent-core\";\nimport type { Api, ImageContent, Model, TextContent } from \"@gsd/pi-ai\";\nimport { Text } from \"@gsd/pi-tui\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { getReadmePath } from \"../../config.js\";\nimport { keyHint, keyText } from \"../tool-ui/keybinding-hints.js\";\nimport { getLanguageFromPath, highlightCode, type Theme } from \"../../theme/theme.js\";\nimport { formatDimensionNote, resizeImage } from \"../../utils/image-resize.js\";\nimport { detectSupportedImageMimeTypeFromFile } from \"../../utils/mime.js\";\nimport { formatPathRelativeToCwdOrAbsolute } from \"../../utils/paths.js\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.js\";\nimport { resolveReadPathAsync, resolveToCwd } from \"./path-utils.js\";\nimport { getTextOutput, invalidArgText, replaceTabs, shortenPath, str } from \"./render-utils.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\nconst readSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n\toffset: Type.Optional(Type.Number({ description: \"Line number to start reading from (1-indexed)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n});\n\nexport type ReadToolInput = Static<typeof readSchema>;\n\nexport interface ReadToolDetails {\n\ttruncation?: TruncationResult;\n}\n\ninterface CompactReadClassification {\n\tkind: \"docs\" | \"resource\" | \"skill\";\n\tlabel: string;\n}\n\nconst COMPACT_RESOURCE_FILE_NAMES = new Set([\"AGENTS.md\", \"AGENTS.MD\", \"CLAUDE.md\", \"CLAUDE.MD\"]);\n\n/** Max read output lines shown in the TUI when tool cards are collapsed (errors only). */\nexport const READ_TUI_COLLAPSED_MAX_LINES = 10;\n/** Expanded read output is intentionally uncapped in the TUI. */\nexport const READ_TUI_EXPANDED_MAX_LINES = Number.POSITIVE_INFINITY;\n\nexport function getReadTuiMaxDisplayLines(expanded: boolean): number {\n\treturn expanded ? READ_TUI_EXPANDED_MAX_LINES : READ_TUI_COLLAPSED_MAX_LINES;\n}\n\n/**\n * Pluggable operations for the read tool.\n * Override these to delegate file reading to remote systems (for example SSH).\n */\nexport interface ReadOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Check if file is readable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/** Detect image MIME type, return null or undefined for non-images */\n\tdetectImageMimeType?: (absolutePath: string) => Promise<string | null | undefined>;\n}\n\nconst defaultReadOperations: ReadOperations = {\n\treadFile: (path) => fsReadFile(path),\n\taccess: (path) => fsAccess(path, constants.R_OK),\n\tdetectImageMimeType: detectSupportedImageMimeTypeFromFile,\n};\n\nexport interface ReadToolOptions {\n\t/** Whether to auto-resize images to 2000x2000 max. Default: true */\n\tautoResizeImages?: boolean;\n\t/** Custom operations for file reading. Default: local filesystem */\n\toperations?: ReadOperations;\n}\n\ntype ReadRenderArgs = { path?: string; file_path?: string; offset?: number; limit?: number };\n\nfunction formatReadLineRange(args: ReadRenderArgs | undefined, theme: Theme): string {\n\tif (args?.offset === undefined && args?.limit === undefined) return \"\";\n\tconst startLine = args.offset ?? 1;\n\tconst endLine = args.limit !== undefined ? startLine + args.limit - 1 : \"\";\n\treturn theme.fg(\"warning\", `:${startLine}${endLine ? `-${endLine}` : \"\"}`);\n}\n\nfunction formatReadCall(args: ReadRenderArgs | undefined, theme: Theme): string {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst path = rawPath !== null ? shortenPath(rawPath) : null;\n\tconst invalidArg = invalidArgText(theme);\n\tconst pathDisplay = path === null ? invalidArg : path ? theme.fg(\"accent\", path) : theme.fg(\"toolOutput\", \"...\");\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"read\"))} ${pathDisplay}${formatReadLineRange(args, theme)}`;\n}\n\nfunction trimTrailingEmptyLines(lines: string[]): string[] {\n\tlet end = lines.length;\n\twhile (end > 0 && lines[end - 1] === \"\") {\n\t\tend--;\n\t}\n\treturn lines.slice(0, end);\n}\n\nfunction getNonVisionImageNote(model: Model<Api> | undefined): string | undefined {\n\tif (!model || model.input.includes(\"image\")) {\n\t\treturn undefined;\n\t}\n\treturn \"[Current model does not support images. The image will be omitted from this request.]\";\n}\n\nfunction toPosixPath(filePath: string): string {\n\treturn filePath.split(sep).join(\"/\");\n}\n\nfunction getPiDocsClassification(absolutePath: string): CompactReadClassification | undefined {\n\tconst packageRoot = dirname(getReadmePath());\n\tconst relativePath = relative(resolvePath(packageRoot), resolvePath(absolutePath));\n\tif (\n\t\trelativePath === \"\" ||\n\t\trelativePath === \"..\" ||\n\t\trelativePath.startsWith(`..${sep}`) ||\n\t\tisAbsolute(relativePath)\n\t) {\n\t\treturn undefined;\n\t}\n\n\tconst label = toPosixPath(relativePath);\n\tif (label === \"README.md\" || label.startsWith(\"docs/\") || label.startsWith(\"examples/\")) {\n\t\treturn { kind: \"docs\", label };\n\t}\n\treturn undefined;\n}\n\nfunction getCompactReadClassification(\n\targs: ReadRenderArgs | undefined,\n\tcwd: string,\n): CompactReadClassification | undefined {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tif (!rawPath) return undefined;\n\n\tconst absolutePath = resolveToCwd(rawPath, cwd);\n\tconst fileName = basename(absolutePath);\n\tif (fileName === \"SKILL.md\") {\n\t\treturn { kind: \"skill\", label: basename(dirname(absolutePath)) || fileName };\n\t}\n\n\tconst docsClassification = getPiDocsClassification(absolutePath);\n\tif (docsClassification) return docsClassification;\n\n\tif (COMPACT_RESOURCE_FILE_NAMES.has(fileName)) {\n\t\treturn { kind: \"resource\", label: formatPathRelativeToCwdOrAbsolute(absolutePath, cwd) };\n\t}\n\n\treturn undefined;\n}\n\nfunction formatCompactReadCall(\n\tclassification: CompactReadClassification,\n\targs: ReadRenderArgs | undefined,\n\ttheme: Theme,\n): string {\n\tconst expandHint = theme.fg(\"dim\", ` (${keyText(\"app.tools.expand\")} to expand)`);\n\tif (classification.kind === \"skill\") {\n\t\treturn (\n\t\t\ttheme.fg(\"customMessageLabel\", `\\x1b[1m[skill]\\x1b[22m `) +\n\t\t\ttheme.fg(\"customMessageText\", classification.label) +\n\t\t\tformatReadLineRange(args, theme) +\n\t\t\texpandHint\n\t\t);\n\t}\n\n\treturn (\n\t\ttheme.fg(\"toolTitle\", theme.bold(`read ${classification.kind}`)) +\n\t\t\" \" +\n\t\ttheme.fg(\"accent\", classification.label) +\n\t\tformatReadLineRange(args, theme) +\n\t\texpandHint\n\t);\n}\n\nfunction formatReadResult(\n\targs: ReadRenderArgs | undefined,\n\tresult: { content: (TextContent | ImageContent)[]; details?: ReadToolDetails },\n\toptions: ToolRenderResultOptions,\n\ttheme: Theme,\n\tshowImages: boolean,\n\t_cwd: string,\n\tisError: boolean,\n): string {\n\tif (!options.expanded && !isError) {\n\t\treturn \"\";\n\t}\n\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst output = getTextOutput(result, showImages);\n\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\tconst renderedLines = lang ? highlightCode(replaceTabs(output), lang) : output.split(\"\\n\");\n\tconst lines = trimTrailingEmptyLines(renderedLines);\n\tconst maxLines = getReadTuiMaxDisplayLines(options.expanded);\n\tconst displayLines = lines.slice(0, maxLines);\n\tconst remaining = lines.length - maxLines;\n\tlet text = `\\n${displayLines.map((line) => (lang ? replaceTabs(line) : theme.fg(\"toolOutput\", replaceTabs(line)))).join(\"\\n\")}`;\n\tif (remaining > 0) {\n\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t}\n\n\tconst truncation = result.details?.truncation;\n\tif (truncation?.truncated) {\n\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`)}`;\n\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines ?? DEFAULT_MAX_LINES} line limit)]`)}`;\n\t\t} else {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`)}`;\n\t\t}\n\t}\n\treturn text;\n}\n\nexport function createReadToolDefinition(\n\tcwd: string,\n\toptions?: ReadToolOptions,\n): ToolDefinition<typeof readSchema, ReadToolDetails | undefined> {\n\tconst autoResizeImages = options?.autoResizeImages ?? true;\n\tconst ops = options?.operations ?? defaultReadOperations;\n\treturn {\n\t\tname: \"read\",\n\t\tlabel: \"read\",\n\t\tdescription: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,\n\t\tpromptSnippet: \"Read file contents\",\n\t\tpromptGuidelines: [\"Use read to examine files instead of cat or sed.\"],\n\t\tparameters: readSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, offset, limit }: { path: string; offset?: number; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?,\n\t\t) {\n\t\t\treturn new Promise<{ content: (TextContent | ImageContent)[]; details: ReadToolDetails | undefined }>(\n\t\t\t\t(resolve, reject) => {\n\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tlet aborted = false;\n\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t};\n\t\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t\t(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst absolutePath = await resolveReadPathAsync(path, cwd);\n\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\t// Check if file exists and is readable.\n\t\t\t\t\t\t\tawait ops.access(absolutePath);\n\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\tconst mimeType = ops.detectImageMimeType ? await ops.detectImageMimeType(absolutePath) : undefined;\n\t\t\t\t\t\t\tlet content: (TextContent | ImageContent)[];\n\t\t\t\t\t\t\tlet details: ReadToolDetails | undefined;\n\t\t\t\t\t\t\tconst nonVisionImageNote = getNonVisionImageNote(ctx?.model);\n\t\t\t\t\t\t\tif (mimeType) {\n\t\t\t\t\t\t\t\t// Read image as binary.\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tif (autoResizeImages) {\n\t\t\t\t\t\t\t\t\t// Resize image if needed before sending it back to the model.\n\t\t\t\t\t\t\t\t\tconst resized = await resizeImage(buffer, mimeType);\n\t\t\t\t\t\t\t\t\tif (!resized) {\n\t\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${mimeType}]\\n[Image omitted: could not be resized below the inline image size limit.]`;\n\t\t\t\t\t\t\t\t\t\tif (nonVisionImageNote) textNote += `\\n${nonVisionImageNote}`;\n\t\t\t\t\t\t\t\t\t\tcontent = [{ type: \"text\", text: textNote }];\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst dimensionNote = formatDimensionNote(resized);\n\t\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${resized.mimeType}]`;\n\t\t\t\t\t\t\t\t\t\tif (dimensionNote) textNote += `\\n${dimensionNote}`;\n\t\t\t\t\t\t\t\t\t\tif (nonVisionImageNote) textNote += `\\n${nonVisionImageNote}`;\n\t\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: resized.data, mimeType: resized.mimeType },\n\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${mimeType}]`;\n\t\t\t\t\t\t\t\t\tif (nonVisionImageNote) textNote += `\\n${nonVisionImageNote}`;\n\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: buffer.toString(\"base64\"), mimeType },\n\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Read text content.\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tconst textContent = buffer.toString(\"utf-8\");\n\t\t\t\t\t\t\t\tconst allLines = textContent.split(\"\\n\");\n\t\t\t\t\t\t\t\tconst totalFileLines = allLines.length;\n\t\t\t\t\t\t\t\t// Apply offset if specified. Convert from 1-indexed input to 0-indexed array access.\n\t\t\t\t\t\t\t\tconst requestedStartLine = offset ? Math.max(0, offset - 1) : 0;\n\t\t\t\t\t\t\t\tconst startLine =\n\t\t\t\t\t\t\t\t\tallLines.length > 0 ? Math.min(requestedStartLine, allLines.length - 1) : requestedStartLine;\n\t\t\t\t\t\t\t\tconst startLineDisplay = startLine + 1;\n\t\t\t\t\t\t\t\tconst offsetWasClamped = offset !== undefined && requestedStartLine !== startLine;\n\t\t\t\t\t\t\t\tlet selectedContent: string;\n\t\t\t\t\t\t\t\tlet userLimitedLines: number | undefined;\n\t\t\t\t\t\t\t\t// If limit is specified by the user, honor it first. Otherwise truncateHead decides.\n\t\t\t\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\t\t\t\tconst endLine = Math.min(startLine + limit, allLines.length);\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine, endLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t\tuserLimitedLines = endLine - startLine;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Apply truncation, respecting both line and byte limits.\n\t\t\t\t\t\t\t\tconst truncation = truncateHead(selectedContent);\n\t\t\t\t\t\t\t\tlet outputText: string;\n\t\t\t\t\t\t\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\t\t\t\t\t\t\t// First line alone exceeds the byte limit. Point the model at a bash fallback.\n\t\t\t\t\t\t\t\t\tconst firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], \"utf-8\"));\n\t\t\t\t\t\t\t\t\toutputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (truncation.truncated) {\n\t\t\t\t\t\t\t\t\t// Truncation occurred. Build an actionable continuation notice.\n\t\t\t\t\t\t\t\t\tconst endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n\t\t\t\t\t\t\t\t\tconst nextOffset = endLineDisplay + 1;\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (userLimitedLines !== undefined && startLine + userLimitedLines < allLines.length) {\n\t\t\t\t\t\t\t\t\t// User-specified limit stopped early, but the file still has more content.\n\t\t\t\t\t\t\t\t\tconst remaining = allLines.length - (startLine + userLimitedLines);\n\t\t\t\t\t\t\t\t\tconst nextOffset = startLine + userLimitedLines + 1;\n\t\t\t\t\t\t\t\t\toutputText = `${truncation.content}\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// No truncation and no remaining user-limited content.\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (offsetWasClamped) {\n\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Requested offset ${offset} was beyond the end of the file (${totalFileLines} lines total), so it was clamped to line ${startLineDisplay}.]`;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcontent = [{ type: \"text\", text: outputText }];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\tresolve({ content, details });\n\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\tif (!aborted) reject(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t})();\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\tconst classification = !context.expanded ? getCompactReadClassification(args, context.cwd) : undefined;\n\t\t\ttext.setText(\n\t\t\t\tclassification ? formatCompactReadCall(classification, args, theme) : formatReadCall(args, theme),\n\t\t\t);\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(\n\t\t\t\tformatReadResult(context.args, result, options, theme, context.showImages, context.cwd, context.isError),\n\t\t\t);\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createReadTool(cwd: string, options?: ReadToolOptions): AgentTool<typeof readSchema> {\n\treturn wrapToolDefinition(createReadToolDefinition(cwd, options));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename, dirname, isAbsolute, relative, resolve as resolvePath, sep } from \"node:path\";\nimport type { AgentTool } from \"@gsd/pi-agent-core\";\nimport type { Api, ImageContent, Model, TextContent } from \"@gsd/pi-ai\";\nimport { Text } from \"@gsd/pi-tui\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { getReadmePath } from \"../../config.js\";\nimport { keyHint, keyText } from \"../tool-ui/keybinding-hints.js\";\nimport { getLanguageFromPath, highlightCode, type Theme } from \"../../theme/theme.js\";\nimport { formatDimensionNote, resizeImage } from \"../../utils/image-resize.js\";\nimport { detectSupportedImageMimeTypeFromFile } from \"../../utils/mime.js\";\nimport { formatPathRelativeToCwdOrAbsolute } from \"../../utils/paths.js\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.js\";\nimport { resolveReadPathAsync, resolveToCwd } from \"./path-utils.js\";\nimport { getTextOutput, invalidArgText, replaceTabs, shortenPath, str } from \"./render-utils.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\nconst readSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n\toffset: Type.Optional(Type.Number({ description: \"Line number to start reading from (1-indexed)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n});\n\nexport type ReadToolInput = Static<typeof readSchema>;\n\nexport interface ReadToolDetails {\n\ttruncation?: TruncationResult;\n}\n\ninterface CompactReadClassification {\n\tkind: \"docs\" | \"resource\" | \"skill\";\n\tlabel: string;\n}\n\nconst COMPACT_RESOURCE_FILE_NAMES = new Set([\"AGENTS.md\", \"AGENTS.MD\", \"CLAUDE.md\", \"CLAUDE.MD\"]);\n\n/** Max read output lines shown in the TUI when tool cards are collapsed (errors only). */\nexport const READ_TUI_COLLAPSED_MAX_LINES = 10;\n/** Max read output lines shown in the TUI when tool cards are expanded. */\nexport const READ_TUI_EXPANDED_MAX_LINES = 50;\n\nexport function getReadTuiMaxDisplayLines(expanded: boolean): number {\n\treturn expanded ? READ_TUI_EXPANDED_MAX_LINES : READ_TUI_COLLAPSED_MAX_LINES;\n}\n\n/**\n * Pluggable operations for the read tool.\n * Override these to delegate file reading to remote systems (for example SSH).\n */\nexport interface ReadOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Check if file is readable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/** Detect image MIME type, return null or undefined for non-images */\n\tdetectImageMimeType?: (absolutePath: string) => Promise<string | null | undefined>;\n}\n\nconst defaultReadOperations: ReadOperations = {\n\treadFile: (path) => fsReadFile(path),\n\taccess: (path) => fsAccess(path, constants.R_OK),\n\tdetectImageMimeType: detectSupportedImageMimeTypeFromFile,\n};\n\nexport interface ReadToolOptions {\n\t/** Whether to auto-resize images to 2000x2000 max. Default: true */\n\tautoResizeImages?: boolean;\n\t/** Custom operations for file reading. Default: local filesystem */\n\toperations?: ReadOperations;\n}\n\ntype ReadRenderArgs = { path?: string; file_path?: string; offset?: number; limit?: number };\n\nfunction formatReadLineRange(args: ReadRenderArgs | undefined, theme: Theme): string {\n\tif (args?.offset === undefined && args?.limit === undefined) return \"\";\n\tconst startLine = args.offset ?? 1;\n\tconst endLine = args.limit !== undefined ? startLine + args.limit - 1 : \"\";\n\treturn theme.fg(\"warning\", `:${startLine}${endLine ? `-${endLine}` : \"\"}`);\n}\n\nfunction formatReadCall(args: ReadRenderArgs | undefined, theme: Theme): string {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst path = rawPath !== null ? shortenPath(rawPath) : null;\n\tconst invalidArg = invalidArgText(theme);\n\tconst pathDisplay = path === null ? invalidArg : path ? theme.fg(\"accent\", path) : theme.fg(\"toolOutput\", \"...\");\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"read\"))} ${pathDisplay}${formatReadLineRange(args, theme)}`;\n}\n\nfunction trimTrailingEmptyLines(lines: string[]): string[] {\n\tlet end = lines.length;\n\twhile (end > 0 && lines[end - 1] === \"\") {\n\t\tend--;\n\t}\n\treturn lines.slice(0, end);\n}\n\nfunction getNonVisionImageNote(model: Model<Api> | undefined): string | undefined {\n\tif (!model || model.input.includes(\"image\")) {\n\t\treturn undefined;\n\t}\n\treturn \"[Current model does not support images. The image will be omitted from this request.]\";\n}\n\nfunction toPosixPath(filePath: string): string {\n\treturn filePath.split(sep).join(\"/\");\n}\n\nfunction getPiDocsClassification(absolutePath: string): CompactReadClassification | undefined {\n\tconst packageRoot = dirname(getReadmePath());\n\tconst relativePath = relative(resolvePath(packageRoot), resolvePath(absolutePath));\n\tif (\n\t\trelativePath === \"\" ||\n\t\trelativePath === \"..\" ||\n\t\trelativePath.startsWith(`..${sep}`) ||\n\t\tisAbsolute(relativePath)\n\t) {\n\t\treturn undefined;\n\t}\n\n\tconst label = toPosixPath(relativePath);\n\tif (label === \"README.md\" || label.startsWith(\"docs/\") || label.startsWith(\"examples/\")) {\n\t\treturn { kind: \"docs\", label };\n\t}\n\treturn undefined;\n}\n\nfunction getCompactReadClassification(\n\targs: ReadRenderArgs | undefined,\n\tcwd: string,\n): CompactReadClassification | undefined {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tif (!rawPath) return undefined;\n\n\tconst absolutePath = resolveToCwd(rawPath, cwd);\n\tconst fileName = basename(absolutePath);\n\tif (fileName === \"SKILL.md\") {\n\t\treturn { kind: \"skill\", label: basename(dirname(absolutePath)) || fileName };\n\t}\n\n\tconst docsClassification = getPiDocsClassification(absolutePath);\n\tif (docsClassification) return docsClassification;\n\n\tif (COMPACT_RESOURCE_FILE_NAMES.has(fileName)) {\n\t\treturn { kind: \"resource\", label: formatPathRelativeToCwdOrAbsolute(absolutePath, cwd) };\n\t}\n\n\treturn undefined;\n}\n\nfunction formatCompactReadCall(\n\tclassification: CompactReadClassification,\n\targs: ReadRenderArgs | undefined,\n\ttheme: Theme,\n): string {\n\tconst expandHint = theme.fg(\"dim\", ` (${keyText(\"app.tools.expand\")} to expand)`);\n\tif (classification.kind === \"skill\") {\n\t\treturn (\n\t\t\ttheme.fg(\"customMessageLabel\", `\\x1b[1m[skill]\\x1b[22m `) +\n\t\t\ttheme.fg(\"customMessageText\", classification.label) +\n\t\t\tformatReadLineRange(args, theme) +\n\t\t\texpandHint\n\t\t);\n\t}\n\n\treturn (\n\t\ttheme.fg(\"toolTitle\", theme.bold(`read ${classification.kind}`)) +\n\t\t\" \" +\n\t\ttheme.fg(\"accent\", classification.label) +\n\t\tformatReadLineRange(args, theme) +\n\t\texpandHint\n\t);\n}\n\nfunction formatReadResult(\n\targs: ReadRenderArgs | undefined,\n\tresult: { content: (TextContent | ImageContent)[]; details?: ReadToolDetails },\n\toptions: ToolRenderResultOptions,\n\ttheme: Theme,\n\tshowImages: boolean,\n\t_cwd: string,\n\tisError: boolean,\n): string {\n\tif (!options.expanded && !isError) {\n\t\treturn \"\";\n\t}\n\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst output = getTextOutput(result, showImages);\n\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\tconst renderedLines = lang ? highlightCode(replaceTabs(output), lang) : output.split(\"\\n\");\n\tconst lines = trimTrailingEmptyLines(renderedLines);\n\tconst maxLines = getReadTuiMaxDisplayLines(options.expanded);\n\tconst displayLines = lines.slice(0, maxLines);\n\tconst remaining = lines.length - maxLines;\n\tlet text = `\\n${displayLines.map((line) => (lang ? replaceTabs(line) : theme.fg(\"toolOutput\", replaceTabs(line)))).join(\"\\n\")}`;\n\tif (remaining > 0) {\n\t\ttext += options.expanded\n\t\t\t? theme.fg(\"muted\", `\\n... (${remaining} more lines hidden from display)`)\n\t\t\t: `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t}\n\n\tconst truncation = result.details?.truncation;\n\tif (truncation?.truncated) {\n\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`)}`;\n\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines ?? DEFAULT_MAX_LINES} line limit)]`)}`;\n\t\t} else {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`)}`;\n\t\t}\n\t}\n\treturn text;\n}\n\nexport function createReadToolDefinition(\n\tcwd: string,\n\toptions?: ReadToolOptions,\n): ToolDefinition<typeof readSchema, ReadToolDetails | undefined> {\n\tconst autoResizeImages = options?.autoResizeImages ?? true;\n\tconst ops = options?.operations ?? defaultReadOperations;\n\treturn {\n\t\tname: \"read\",\n\t\tlabel: \"read\",\n\t\tdescription: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,\n\t\tpromptSnippet: \"Read file contents\",\n\t\tpromptGuidelines: [\"Use read to examine files instead of cat or sed.\"],\n\t\tparameters: readSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, offset, limit }: { path: string; offset?: number; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?,\n\t\t) {\n\t\t\treturn new Promise<{ content: (TextContent | ImageContent)[]; details: ReadToolDetails | undefined }>(\n\t\t\t\t(resolve, reject) => {\n\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tlet aborted = false;\n\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t};\n\t\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t\t(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst absolutePath = await resolveReadPathAsync(path, cwd);\n\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\t// Check if file exists and is readable.\n\t\t\t\t\t\t\tawait ops.access(absolutePath);\n\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\tconst mimeType = ops.detectImageMimeType ? await ops.detectImageMimeType(absolutePath) : undefined;\n\t\t\t\t\t\t\tlet content: (TextContent | ImageContent)[];\n\t\t\t\t\t\t\tlet details: ReadToolDetails | undefined;\n\t\t\t\t\t\t\tconst nonVisionImageNote = getNonVisionImageNote(ctx?.model);\n\t\t\t\t\t\t\tif (mimeType) {\n\t\t\t\t\t\t\t\t// Read image as binary.\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tif (autoResizeImages) {\n\t\t\t\t\t\t\t\t\t// Resize image if needed before sending it back to the model.\n\t\t\t\t\t\t\t\t\tconst resized = await resizeImage(buffer, mimeType);\n\t\t\t\t\t\t\t\t\tif (!resized) {\n\t\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${mimeType}]\\n[Image omitted: could not be resized below the inline image size limit.]`;\n\t\t\t\t\t\t\t\t\t\tif (nonVisionImageNote) textNote += `\\n${nonVisionImageNote}`;\n\t\t\t\t\t\t\t\t\t\tcontent = [{ type: \"text\", text: textNote }];\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst dimensionNote = formatDimensionNote(resized);\n\t\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${resized.mimeType}]`;\n\t\t\t\t\t\t\t\t\t\tif (dimensionNote) textNote += `\\n${dimensionNote}`;\n\t\t\t\t\t\t\t\t\t\tif (nonVisionImageNote) textNote += `\\n${nonVisionImageNote}`;\n\t\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: resized.data, mimeType: resized.mimeType },\n\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${mimeType}]`;\n\t\t\t\t\t\t\t\t\tif (nonVisionImageNote) textNote += `\\n${nonVisionImageNote}`;\n\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: buffer.toString(\"base64\"), mimeType },\n\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Read text content.\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tconst textContent = buffer.toString(\"utf-8\");\n\t\t\t\t\t\t\t\tconst allLines = textContent.split(\"\\n\");\n\t\t\t\t\t\t\t\tconst totalFileLines = allLines.length;\n\t\t\t\t\t\t\t\t// Apply offset if specified. Convert from 1-indexed input to 0-indexed array access.\n\t\t\t\t\t\t\t\tconst requestedStartLine = offset ? Math.max(0, offset - 1) : 0;\n\t\t\t\t\t\t\t\tconst startLine =\n\t\t\t\t\t\t\t\t\tallLines.length > 0 ? Math.min(requestedStartLine, allLines.length - 1) : requestedStartLine;\n\t\t\t\t\t\t\t\tconst startLineDisplay = startLine + 1;\n\t\t\t\t\t\t\t\tconst offsetWasClamped = offset !== undefined && requestedStartLine !== startLine;\n\t\t\t\t\t\t\t\tlet selectedContent: string;\n\t\t\t\t\t\t\t\tlet userLimitedLines: number | undefined;\n\t\t\t\t\t\t\t\t// If limit is specified by the user, honor it first. Otherwise truncateHead decides.\n\t\t\t\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\t\t\t\tconst endLine = Math.min(startLine + limit, allLines.length);\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine, endLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t\tuserLimitedLines = endLine - startLine;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Apply truncation, respecting both line and byte limits.\n\t\t\t\t\t\t\t\tconst truncation = truncateHead(selectedContent);\n\t\t\t\t\t\t\t\tlet outputText: string;\n\t\t\t\t\t\t\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\t\t\t\t\t\t\t// First line alone exceeds the byte limit. Point the model at a bash fallback.\n\t\t\t\t\t\t\t\t\tconst firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], \"utf-8\"));\n\t\t\t\t\t\t\t\t\toutputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (truncation.truncated) {\n\t\t\t\t\t\t\t\t\t// Truncation occurred. Build an actionable continuation notice.\n\t\t\t\t\t\t\t\t\tconst endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n\t\t\t\t\t\t\t\t\tconst nextOffset = endLineDisplay + 1;\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (userLimitedLines !== undefined && startLine + userLimitedLines < allLines.length) {\n\t\t\t\t\t\t\t\t\t// User-specified limit stopped early, but the file still has more content.\n\t\t\t\t\t\t\t\t\tconst remaining = allLines.length - (startLine + userLimitedLines);\n\t\t\t\t\t\t\t\t\tconst nextOffset = startLine + userLimitedLines + 1;\n\t\t\t\t\t\t\t\t\toutputText = `${truncation.content}\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// No truncation and no remaining user-limited content.\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (offsetWasClamped) {\n\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Requested offset ${offset} was beyond the end of the file (${totalFileLines} lines total), so it was clamped to line ${startLineDisplay}.]`;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcontent = [{ type: \"text\", text: outputText }];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\tresolve({ content, details });\n\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\tif (!aborted) reject(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t})();\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\tconst classification = !context.expanded ? getCompactReadClassification(args, context.cwd) : undefined;\n\t\t\ttext.setText(\n\t\t\t\tclassification ? formatCompactReadCall(classification, args, theme) : formatReadCall(args, theme),\n\t\t\t);\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(\n\t\t\t\tformatReadResult(context.args, result, options, theme, context.showImages, context.cwd, context.isError),\n\t\t\t);\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createReadTool(cwd: string, options?: ReadToolOptions): AgentTool<typeof readSchema> {\n\treturn wrapToolDefinition(createReadToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/pi-coding-agent",
|
|
3
|
-
"version": "1.0.2-dev.
|
|
3
|
+
"version": "1.0.2-dev.2c204d3",
|
|
4
4
|
"description": "Coding agent CLI (vendored from earendil-works/pi)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"copy-assets": "node scripts/copy-assets.cjs"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@opengsd/contracts": "^1.0.2-dev.
|
|
36
|
+
"@opengsd/contracts": "^1.0.2-dev.2c204d3",
|
|
37
37
|
"@mariozechner/jiti": "^2.6.2",
|
|
38
38
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
39
39
|
"chalk": "5.6.2",
|
|
@@ -51,13 +51,13 @@
|
|
|
51
51
|
"sql.js": "^1.14.1",
|
|
52
52
|
"strip-ansi": "^7.1.0",
|
|
53
53
|
"typebox": "1.1.38",
|
|
54
|
-
"undici": "
|
|
54
|
+
"undici": "7.26.0",
|
|
55
55
|
"yaml": "2.9.0",
|
|
56
|
-
"@gsd/agent-core": "^1.0.2-dev.
|
|
57
|
-
"@gsd/native": "^1.0.2-dev.
|
|
58
|
-
"@gsd/pi-agent-core": "^1.0.2-dev.
|
|
59
|
-
"@gsd/pi-ai": "^1.0.2-dev.
|
|
60
|
-
"@gsd/pi-tui": "^1.0.2-dev.
|
|
56
|
+
"@gsd/agent-core": "^1.0.2-dev.2c204d3",
|
|
57
|
+
"@gsd/native": "^1.0.2-dev.2c204d3",
|
|
58
|
+
"@gsd/pi-agent-core": "^1.0.2-dev.2c204d3",
|
|
59
|
+
"@gsd/pi-ai": "^1.0.2-dev.2c204d3",
|
|
60
|
+
"@gsd/pi-tui": "^1.0.2-dev.2c204d3",
|
|
61
61
|
"@sinclair/typebox": "^0.34.41"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengsd/rpc-client",
|
|
3
|
-
"version": "1.0.2-dev.
|
|
3
|
+
"version": "1.0.2-dev.2c204d3",
|
|
4
4
|
"description": "Standalone RPC client SDK for GSD — zero internal dependencies",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"gsd": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"test": "node --test dist/rpc-client.test.js"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@opengsd/contracts": "^1.0.2-dev.
|
|
37
|
+
"@opengsd/contracts": "^1.0.2-dev.2c204d3"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=22.0.0"
|
package/pkg/package.json
CHANGED
package/scripts/install/deps.js
CHANGED
|
@@ -164,6 +164,16 @@ function execCommand(command, opts = {}) {
|
|
|
164
164
|
* to materialize the real packages without re-running lifecycle scripts.
|
|
165
165
|
*/
|
|
166
166
|
export async function repairPackageDependencies(packageRoot, { ui, quiet = false } = {}) {
|
|
167
|
+
if (
|
|
168
|
+
process.env.GSD_SKIP_DEP_REPAIR === '1' ||
|
|
169
|
+
process.env.GSD_SKIP_DEP_REPAIR === 'true'
|
|
170
|
+
) {
|
|
171
|
+
if (!quiet) {
|
|
172
|
+
ui?.skip?.('Dependencies', 'skipped by GSD_SKIP_DEP_REPAIR')
|
|
173
|
+
}
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
167
177
|
const pkgJson = join(packageRoot, 'package.json')
|
|
168
178
|
if (!existsSync(pkgJson)) return
|
|
169
179
|
|
|
@@ -5,11 +5,20 @@
|
|
|
5
5
|
import { createRequire } from 'module'
|
|
6
6
|
import { dirname, join } from 'path'
|
|
7
7
|
import { fileURLToPath } from 'url'
|
|
8
|
+
import { detectPackageManager } from './npm-global.js'
|
|
8
9
|
|
|
9
10
|
const require = createRequire(import.meta.url)
|
|
10
11
|
const { GSD_PI_BRAND } = require(join(dirname(fileURLToPath(import.meta.url)), '..', 'lib', 'logo.cjs'))
|
|
11
12
|
|
|
12
13
|
export function parseInstalledVersion(npmListJson) {
|
|
14
|
+
if (Array.isArray(npmListJson)) {
|
|
15
|
+
for (const entry of npmListJson) {
|
|
16
|
+
const found = parseInstalledVersion(entry)
|
|
17
|
+
if (found) return found
|
|
18
|
+
}
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
if (!npmListJson || typeof npmListJson !== 'object') return null
|
|
14
23
|
|
|
15
24
|
const direct = npmListJson.dependencies?.['@opengsd/gsd-pi']?.version
|
|
@@ -30,6 +39,10 @@ export function parseInstalledVersion(npmListJson) {
|
|
|
30
39
|
return walk(npmListJson)
|
|
31
40
|
}
|
|
32
41
|
|
|
42
|
+
function getPackageManagerBin(packageManager) {
|
|
43
|
+
return process.platform === 'win32' ? `${packageManager}.cmd` : packageManager
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
/**
|
|
34
47
|
* Decide install action for non-interactive or pre-prompt routing.
|
|
35
48
|
*/
|
|
@@ -39,11 +52,12 @@ export function compareActions({ installed, yesMode }) {
|
|
|
39
52
|
return 'prompt'
|
|
40
53
|
}
|
|
41
54
|
|
|
42
|
-
export async function detectInstalledVersion() {
|
|
55
|
+
export async function detectInstalledVersion(options = {}) {
|
|
43
56
|
const { execFileSync } = await import('child_process')
|
|
44
|
-
const
|
|
57
|
+
const packageManager = options.packageManager ?? detectPackageManager()
|
|
58
|
+
const bin = getPackageManagerBin(packageManager)
|
|
45
59
|
try {
|
|
46
|
-
const raw = execFileSync(
|
|
60
|
+
const raw = execFileSync(bin, ['list', '-g', '@opengsd/gsd-pi', '--json'], {
|
|
47
61
|
encoding: 'utf-8',
|
|
48
62
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
49
63
|
timeout: 30_000,
|