@opengsd/gsd-pi 1.0.2-dev.5961fbf → 1.0.2-dev.5f7864c
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/onboarding.js +22 -3
- package/dist/resource-loader.d.ts +2 -0
- package/dist/resource-loader.js +18 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/get-secrets-from-user.js +16 -16
- package/dist/resources/extensions/google-cli/index.js +30 -0
- package/dist/resources/extensions/google-cli/models.js +55 -0
- package/dist/resources/extensions/google-cli/package.json +11 -0
- package/dist/resources/extensions/google-cli/readiness.js +12 -0
- package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
- 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/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/commands-usage.js +105 -1
- package/dist/resources/extensions/gsd/config-overlay.js +20 -14
- package/dist/resources/extensions/gsd/context-overlay.js +22 -16
- package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
- package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/guided-flow.js +1 -1
- package/dist/resources/extensions/gsd/key-manager.js +45 -13
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- 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/tui/render-kit.js +51 -0
- package/dist/resources/extensions/gsd/vision-ask.js +22 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/extensions/shared/confirm-ui.js +9 -6
- package/dist/resources/extensions/shared/dialog-frame.js +42 -0
- package/dist/resources/extensions/shared/interview-ui.js +42 -30
- package/dist/resources/extensions/shared/next-action-ui.js +6 -6
- 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 +6 -6
- 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/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 +6 -6
- package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
- 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/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- 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/dialog-container.d.ts +12 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.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-selectors-auth.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- 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 +3 -3
- 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/dist/models.generated.d.ts +57 -17
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +64 -28
- 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 +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- 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/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/get-secrets-from-user.ts +17 -16
- package/src/resources/extensions/google-cli/index.ts +34 -0
- package/src/resources/extensions/google-cli/models.ts +57 -0
- package/src/resources/extensions/google-cli/package.json +11 -0
- package/src/resources/extensions/google-cli/readiness.ts +15 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
- 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/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/commands-usage.ts +110 -5
- package/src/resources/extensions/gsd/config-overlay.ts +19 -16
- package/src/resources/extensions/gsd/context-overlay.ts +24 -19
- package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
- package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/guided-flow.ts +1 -1
- package/src/resources/extensions/gsd/key-manager.ts +57 -14
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- 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/collect-from-manifest.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
- 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/tui-border-assertions.ts +28 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -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/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/tui/render-kit.ts +82 -0
- package/src/resources/extensions/gsd/vision-ask.ts +28 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/extensions/shared/confirm-ui.ts +8 -12
- package/src/resources/extensions/shared/dialog-frame.ts +71 -0
- package/src/resources/extensions/shared/interview-ui.ts +43 -42
- package/src/resources/extensions/shared/next-action-ui.ts +6 -6
- package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
- package/src/resources/shared/package-manager-detection.ts +39 -0
- /package/dist/web/standalone/.next/static/{spUYLkQXoHJyxYOMH9VQy → IjxvcC7sl_MHNKXsUZrAy}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{spUYLkQXoHJyxYOMH9VQy → IjxvcC7sl_MHNKXsUZrAy}/_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-coding-agent",
|
|
3
|
-
"version": "1.0.2-dev.
|
|
3
|
+
"version": "1.0.2-dev.5f7864c",
|
|
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.5f7864c",
|
|
37
37
|
"@mariozechner/jiti": "^2.6.2",
|
|
38
38
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
39
39
|
"chalk": "5.6.2",
|
|
@@ -53,11 +53,11 @@
|
|
|
53
53
|
"typebox": "1.1.38",
|
|
54
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.5f7864c",
|
|
57
|
+
"@gsd/native": "^1.0.2-dev.5f7864c",
|
|
58
|
+
"@gsd/pi-agent-core": "^1.0.2-dev.5f7864c",
|
|
59
|
+
"@gsd/pi-ai": "^1.0.2-dev.5f7864c",
|
|
60
|
+
"@gsd/pi-tui": "^1.0.2-dev.5f7864c",
|
|
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.5f7864c",
|
|
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.5f7864c"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=22.0.0"
|
package/pkg/package.json
CHANGED
|
@@ -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,
|
|
@@ -1,14 +1,61 @@
|
|
|
1
1
|
import { execFileSync, spawn } from 'child_process'
|
|
2
|
-
import {
|
|
2
|
+
import { homedir } from 'os'
|
|
3
|
+
import { join, resolve as resolvePath, sep } from 'path'
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
const PACKAGE_MANAGERS = new Set(['npm', 'pnpm'])
|
|
6
|
+
|
|
7
|
+
function normalizePackageManager(value) {
|
|
8
|
+
return PACKAGE_MANAGERS.has(value) ? value : 'npm'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function hasPnpmPath(value = '') {
|
|
12
|
+
const normalized = value.replace(/\\/g, '/').toLowerCase()
|
|
13
|
+
return (
|
|
14
|
+
normalized.includes('/.pnpm/') ||
|
|
15
|
+
normalized.endsWith('/pnpm') ||
|
|
16
|
+
normalized.endsWith('/pnpm.cjs') ||
|
|
17
|
+
normalized.endsWith('/pnpm.js')
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function pathStartsWith(pathValue = '', dir) {
|
|
22
|
+
if (!pathValue) return false
|
|
23
|
+
const resolvedPath = resolvePath(pathValue)
|
|
24
|
+
const resolvedDir = resolvePath(dir)
|
|
25
|
+
return resolvedPath === resolvedDir || resolvedPath.startsWith(resolvedDir + sep)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function hasPnpmBinPath(env, argv1) {
|
|
29
|
+
const pnpmBinDirs = []
|
|
30
|
+
if (env.PNPM_HOME) pnpmBinDirs.push(env.PNPM_HOME)
|
|
31
|
+
pnpmBinDirs.push(join(homedir(), 'Library', 'pnpm'))
|
|
32
|
+
pnpmBinDirs.push(join(homedir(), '.local', 'share', 'pnpm'))
|
|
33
|
+
|
|
34
|
+
return pnpmBinDirs.some((dir) => pathStartsWith(argv1, dir) || pathStartsWith(env.npm_execpath, dir))
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function detectPackageManager(env = process.env, argv1 = process.argv[1]) {
|
|
38
|
+
const userAgent = env.npm_config_user_agent || ''
|
|
39
|
+
if (userAgent.startsWith('pnpm/')) return 'pnpm'
|
|
40
|
+
// Installer runs under npm during npm install; keep that context authoritative.
|
|
41
|
+
if (userAgent.startsWith('npm/')) return 'npm'
|
|
42
|
+
|
|
43
|
+
if (hasPnpmPath(env.npm_execpath || '')) return 'pnpm'
|
|
44
|
+
if (hasPnpmPath(argv1 || '')) return 'pnpm'
|
|
45
|
+
if (hasPnpmBinPath(env, argv1)) return 'pnpm'
|
|
46
|
+
|
|
47
|
+
return 'npm'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getPackageManagerBin(packageManager) {
|
|
51
|
+
const bin = normalizePackageManager(packageManager)
|
|
52
|
+
return process.platform === 'win32' ? `${bin}.cmd` : bin
|
|
6
53
|
}
|
|
7
54
|
|
|
8
|
-
const
|
|
55
|
+
const PM_OUTPUT_LIMIT = 64 * 1024
|
|
9
56
|
|
|
10
|
-
function
|
|
11
|
-
return execFileSync(
|
|
57
|
+
function runPackageManager(packageManager, args) {
|
|
58
|
+
return execFileSync(getPackageManagerBin(packageManager), args, {
|
|
12
59
|
encoding: 'utf-8',
|
|
13
60
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
14
61
|
timeout: 120_000,
|
|
@@ -16,30 +63,30 @@ function runNpm(args) {
|
|
|
16
63
|
}).trim()
|
|
17
64
|
}
|
|
18
65
|
|
|
19
|
-
function
|
|
66
|
+
function formatPackageManagerFailure(packageManager, result) {
|
|
20
67
|
const output = `${result.stderr}\n${result.stdout}`.trim()
|
|
21
68
|
const meaningful = output
|
|
22
69
|
.split('\n')
|
|
23
|
-
.filter((line) =>
|
|
70
|
+
.filter((line) => line.trim() && !/^(?:npm\s+warn|warn)\b/i.test(line.trim()))
|
|
24
71
|
.slice(-3)
|
|
25
72
|
.join('; ')
|
|
26
|
-
return meaningful || result.error?.message ||
|
|
73
|
+
return meaningful || result.error?.message || `${packageManager} install failed`
|
|
27
74
|
}
|
|
28
75
|
|
|
29
76
|
function appendLimited(value, chunk) {
|
|
30
|
-
if (value.length >=
|
|
31
|
-
return value + chunk.slice(0,
|
|
77
|
+
if (value.length >= PM_OUTPUT_LIMIT) return value
|
|
78
|
+
return value + chunk.slice(0, PM_OUTPUT_LIMIT - value.length)
|
|
32
79
|
}
|
|
33
80
|
|
|
34
|
-
function
|
|
81
|
+
function runPackageManagerAsync(packageManager, args, {
|
|
35
82
|
captureStdout = false,
|
|
36
83
|
cwd,
|
|
37
84
|
timeout = 300_000,
|
|
38
85
|
} = {}) {
|
|
39
|
-
const
|
|
86
|
+
const bin = getPackageManagerBin(packageManager)
|
|
40
87
|
|
|
41
88
|
return new Promise((resolve) => {
|
|
42
|
-
const child = spawn(
|
|
89
|
+
const child = spawn(bin, args, {
|
|
43
90
|
cwd,
|
|
44
91
|
shell: process.platform === 'win32',
|
|
45
92
|
stdio: ['ignore', captureStdout ? 'pipe' : 'ignore', 'pipe'],
|
|
@@ -85,7 +132,7 @@ function runNpmAsync(args, {
|
|
|
85
132
|
ok: false,
|
|
86
133
|
stdout,
|
|
87
134
|
stderr,
|
|
88
|
-
error: new Error(
|
|
135
|
+
error: new Error(`${packageManager} ${args.join(' ')} timed out after ${timeout}ms`),
|
|
89
136
|
})
|
|
90
137
|
return
|
|
91
138
|
}
|
|
@@ -100,20 +147,35 @@ function runNpmAsync(args, {
|
|
|
100
147
|
ok: false,
|
|
101
148
|
stdout,
|
|
102
149
|
stderr,
|
|
103
|
-
error: new Error(
|
|
150
|
+
error: new Error(`${packageManager} ${args.join(' ')} failed with ${reason}`),
|
|
104
151
|
})
|
|
105
152
|
})
|
|
106
153
|
})
|
|
107
154
|
}
|
|
108
155
|
|
|
109
|
-
export function getGlobalPaths() {
|
|
110
|
-
const
|
|
111
|
-
|
|
156
|
+
export function getGlobalPaths(options = {}) {
|
|
157
|
+
const packageManager = normalizePackageManager(options.packageManager ?? detectPackageManager())
|
|
158
|
+
|
|
159
|
+
if (packageManager === 'pnpm') {
|
|
160
|
+
const binDir = runPackageManager(packageManager, ['bin', '-g'])
|
|
161
|
+
const root = runPackageManager(packageManager, ['root', '-g'])
|
|
162
|
+
return {
|
|
163
|
+
prefix: binDir,
|
|
164
|
+
root,
|
|
165
|
+
binDir,
|
|
166
|
+
packageRoot: join(root, '@opengsd', 'gsd-pi'),
|
|
167
|
+
packageManager,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const prefix = runPackageManager(packageManager, ['prefix', '-g'])
|
|
172
|
+
const root = runPackageManager(packageManager, ['root', '-g'])
|
|
112
173
|
return {
|
|
113
174
|
prefix,
|
|
114
175
|
root,
|
|
115
176
|
binDir: process.platform === 'win32' ? prefix : join(prefix, 'bin'),
|
|
116
177
|
packageRoot: join(root, '@opengsd', 'gsd-pi'),
|
|
178
|
+
packageManager,
|
|
117
179
|
}
|
|
118
180
|
}
|
|
119
181
|
|
|
@@ -121,33 +183,41 @@ export function getLocalPackageRoot(cwd = process.cwd()) {
|
|
|
121
183
|
return join(cwd, 'node_modules', '@opengsd', 'gsd-pi')
|
|
122
184
|
}
|
|
123
185
|
|
|
124
|
-
export async function installGlobalPackage(version) {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
'--ignore-scripts',
|
|
129
|
-
|
|
130
|
-
|
|
186
|
+
export async function installGlobalPackage(version, options = {}) {
|
|
187
|
+
const packageManager = normalizePackageManager(options.packageManager ?? detectPackageManager())
|
|
188
|
+
const packageSpec = `@opengsd/gsd-pi@${version}`
|
|
189
|
+
const installArgs = packageManager === 'pnpm'
|
|
190
|
+
? ['add', '-g', '--ignore-scripts', packageSpec]
|
|
191
|
+
: ['install', '-g', '--ignore-scripts', packageSpec]
|
|
192
|
+
|
|
193
|
+
const result = await runPackageManagerAsync(packageManager, installArgs)
|
|
131
194
|
if (!result.ok) {
|
|
132
|
-
throw new Error(
|
|
195
|
+
throw new Error(formatPackageManagerFailure(packageManager, result))
|
|
133
196
|
}
|
|
134
|
-
const rootResult = await
|
|
197
|
+
const rootResult = await runPackageManagerAsync(packageManager, ['root', '-g'], {
|
|
135
198
|
captureStdout: true,
|
|
136
199
|
timeout: 120_000,
|
|
137
200
|
})
|
|
138
201
|
if (!rootResult.ok) {
|
|
139
|
-
throw new Error(
|
|
202
|
+
throw new Error(formatPackageManagerFailure(packageManager, rootResult))
|
|
140
203
|
}
|
|
141
204
|
return join(rootResult.stdout.trim(), '@opengsd', 'gsd-pi')
|
|
142
205
|
}
|
|
143
206
|
|
|
144
|
-
export async function installLocalPackage(version, cwd = process.cwd()) {
|
|
145
|
-
const
|
|
146
|
-
|
|
207
|
+
export async function installLocalPackage(version, cwd = process.cwd(), options = {}) {
|
|
208
|
+
const packageManager = normalizePackageManager(options.packageManager ?? detectPackageManager())
|
|
209
|
+
const packageSpec = `@opengsd/gsd-pi@${version}`
|
|
210
|
+
const installArgs = packageManager === 'pnpm'
|
|
211
|
+
? ['add', '--ignore-scripts', packageSpec]
|
|
212
|
+
: ['install', '--ignore-scripts', packageSpec]
|
|
213
|
+
|
|
214
|
+
const result = await runPackageManagerAsync(
|
|
215
|
+
packageManager,
|
|
216
|
+
installArgs,
|
|
147
217
|
{ cwd },
|
|
148
218
|
)
|
|
149
219
|
if (!result.ok) {
|
|
150
|
-
throw new Error(
|
|
220
|
+
throw new Error(formatPackageManagerFailure(packageManager, result))
|
|
151
221
|
}
|
|
152
222
|
return getLocalPackageRoot(cwd)
|
|
153
223
|
}
|
package/scripts/install.js
CHANGED
|
@@ -71,6 +71,7 @@ if (HAS_HELP) {
|
|
|
71
71
|
|
|
72
72
|
${colors.yellow}Usage:${colors.reset}
|
|
73
73
|
npx @opengsd/gsd-pi@latest Install GSD-Pi globally (recommended)
|
|
74
|
+
pnpm dlx @opengsd/gsd-pi@latest Install GSD-Pi globally with pnpm
|
|
74
75
|
npx @opengsd/gsd-pi@latest --local Install to current project (advanced)
|
|
75
76
|
|
|
76
77
|
${colors.yellow}Options:${colors.reset}
|
|
@@ -132,6 +132,19 @@ function formatLibraryList(libs: C7Library[], query: string): string {
|
|
|
132
132
|
return lines.join("\n");
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
function getFirstTextContent(result: { content?: unknown }): string | undefined {
|
|
136
|
+
const content = result.content;
|
|
137
|
+
if (!Array.isArray(content)) return undefined;
|
|
138
|
+
const textBlock = content.find(
|
|
139
|
+
(block: unknown) =>
|
|
140
|
+
typeof block === "object" &&
|
|
141
|
+
block !== null &&
|
|
142
|
+
(block as { type?: unknown }).type === "text" &&
|
|
143
|
+
typeof (block as { text?: unknown }).text === "string",
|
|
144
|
+
) as { text: string } | undefined;
|
|
145
|
+
return textBlock?.text.trim() || undefined;
|
|
146
|
+
}
|
|
147
|
+
|
|
135
148
|
// ─── Tool details types ───────────────────────────────────────────────────────
|
|
136
149
|
|
|
137
150
|
interface ResolveDetails {
|
|
@@ -234,7 +247,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
234
247
|
const d = result.details as ResolveDetails | undefined;
|
|
235
248
|
if (isPartial) return new Text(theme.fg("warning", "Searching Context7..."), 0, 0);
|
|
236
249
|
if ((result as any).isError || d?.error) {
|
|
237
|
-
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
250
|
+
return new Text(theme.fg("error", `Error: ${d?.error ?? getFirstTextContent(result) ?? "unknown"}`), 0, 0);
|
|
238
251
|
}
|
|
239
252
|
let text = theme.fg("success", `${d?.resultCount ?? 0} ${d?.resultCount === 1 ? "library" : "libraries"} found`);
|
|
240
253
|
if (d?.cached) text += theme.fg("dim", " (cached)");
|
|
@@ -389,7 +402,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
389
402
|
|
|
390
403
|
if (isPartial) return new Text(theme.fg("warning", "Fetching documentation..."), 0, 0);
|
|
391
404
|
if ((result as any).isError || d?.error) {
|
|
392
|
-
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
405
|
+
return new Text(theme.fg("error", `Error: ${d?.error ?? getFirstTextContent(result) ?? "unknown"}`), 0, 0);
|
|
393
406
|
}
|
|
394
407
|
|
|
395
408
|
let text = theme.fg("success", `${(d?.charCount ?? 0).toLocaleString()} chars`);
|
|
@@ -13,6 +13,7 @@ import { resolve } from "node:path";
|
|
|
13
13
|
import type { ExtensionAPI, Theme } from "@gsd/pi-coding-agent";
|
|
14
14
|
import { Editor, type EditorTheme, Key, matchesKey, Text, truncateToWidth, wrapTextWithAnsi } from "@gsd/pi-tui";
|
|
15
15
|
import { Type } from "@sinclair/typebox";
|
|
16
|
+
import { renderSharedDialogFrame } from "./shared/dialog-frame.js";
|
|
16
17
|
import { makeUI } from "./shared/tui.js";
|
|
17
18
|
import { maskEditorLine, type ProgressStatus } from "./shared/mod.js";
|
|
18
19
|
import { parseSecretsManifest, formatSecretsManifest } from "./gsd/files.js";
|
|
@@ -43,6 +44,10 @@ function maskPreview(value: string): string {
|
|
|
43
44
|
return `${value.slice(0, 4)}${"*".repeat(Math.max(4, value.length - 8))}${value.slice(-4)}`;
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
function dialogContentWidth(width: number): number {
|
|
48
|
+
return width < 4 ? Math.max(1, width) : Math.max(1, width - 4);
|
|
49
|
+
}
|
|
50
|
+
|
|
46
51
|
function shellEscapeSingle(value: string): string {
|
|
47
52
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
48
53
|
}
|
|
@@ -168,10 +173,10 @@ async function collectOneSecret(
|
|
|
168
173
|
|
|
169
174
|
function render(width: number): string[] {
|
|
170
175
|
if (cachedLines) return cachedLines;
|
|
176
|
+
const contentWidth = dialogContentWidth(width);
|
|
171
177
|
const lines: string[] = [];
|
|
172
|
-
const add = (s: string) => lines.push(truncateToWidth(s,
|
|
178
|
+
const add = (s: string) => lines.push(truncateToWidth(s, contentWidth));
|
|
173
179
|
|
|
174
|
-
add(theme.fg("accent", "─".repeat(width)));
|
|
175
180
|
add(theme.fg("dim", ` Page ${pageIndex + 1}/${totalPages} · Secure Env Setup`));
|
|
176
181
|
lines.push("");
|
|
177
182
|
|
|
@@ -187,7 +192,7 @@ async function collectOneSecret(
|
|
|
187
192
|
for (let g = 0; g < guidance.length; g++) {
|
|
188
193
|
const prefix = ` ${g + 1}. `;
|
|
189
194
|
const step = guidance[g] as string;
|
|
190
|
-
const wrappedLines = wrapTextWithAnsi(step,
|
|
195
|
+
const wrappedLines = wrapTextWithAnsi(step, Math.max(1, contentWidth - 4));
|
|
191
196
|
for (let w = 0; w < wrappedLines.length; w++) {
|
|
192
197
|
const indent = w === 0 ? prefix : " ".repeat(prefix.length);
|
|
193
198
|
lines.push(theme.fg("dim", `${indent}${wrappedLines[w]}`));
|
|
@@ -205,16 +210,15 @@ async function collectOneSecret(
|
|
|
205
210
|
|
|
206
211
|
// Editor
|
|
207
212
|
add(theme.fg("muted", " Enter value:"));
|
|
208
|
-
for (const line of editor.render(
|
|
213
|
+
for (const line of editor.render(Math.max(1, contentWidth - 2))) {
|
|
209
214
|
add(theme.fg("text", maskEditorLine(line)));
|
|
210
215
|
}
|
|
211
216
|
|
|
212
217
|
lines.push("");
|
|
213
|
-
|
|
214
|
-
add(theme.fg("accent", "─".repeat(width)));
|
|
218
|
+
const footer = theme.fg("dim", " enter to confirm | ctrl+s or esc to skip | esc cancels");
|
|
215
219
|
|
|
216
|
-
cachedLines = lines;
|
|
217
|
-
return
|
|
220
|
+
cachedLines = renderSharedDialogFrame(theme, "Secure Env Setup", lines, width, { footer });
|
|
221
|
+
return cachedLines;
|
|
218
222
|
}
|
|
219
223
|
|
|
220
224
|
return {
|
|
@@ -286,13 +290,11 @@ export async function showSecretsSummary(
|
|
|
286
290
|
function render(width: number): string[] {
|
|
287
291
|
if (cachedLines) return cachedLines;
|
|
288
292
|
|
|
289
|
-
const
|
|
293
|
+
const contentWidth = dialogContentWidth(width);
|
|
294
|
+
const ui = makeUI(theme, contentWidth);
|
|
290
295
|
const lines: string[] = [];
|
|
291
296
|
const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
|
|
292
297
|
|
|
293
|
-
push(ui.bar());
|
|
294
|
-
push(ui.blank());
|
|
295
|
-
push(ui.header(" Secrets Summary"));
|
|
296
298
|
push(ui.blank());
|
|
297
299
|
|
|
298
300
|
for (const entry of entries) {
|
|
@@ -314,11 +316,10 @@ export async function showSecretsSummary(
|
|
|
314
316
|
}
|
|
315
317
|
|
|
316
318
|
push(ui.blank());
|
|
317
|
-
|
|
318
|
-
push(ui.bar());
|
|
319
|
+
const footer = ui.hints(["any key to continue"])[0] ?? "";
|
|
319
320
|
|
|
320
|
-
cachedLines = lines;
|
|
321
|
-
return
|
|
321
|
+
cachedLines = renderSharedDialogFrame(theme, "Secrets Summary", lines, width, { footer });
|
|
322
|
+
return cachedLines;
|
|
322
323
|
}
|
|
323
324
|
|
|
324
325
|
return {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google local CLI providers.
|
|
3
|
+
*
|
|
4
|
+
* These deliberately use authMode "externalCli": GSD never owns the browser
|
|
5
|
+
* OAuth flow or cached tokens. Users authenticate with the official CLI, then
|
|
6
|
+
* /login activates the provider once the local binary is available.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
10
|
+
import { GOOGLE_ANTIGRAVITY_MODELS, GOOGLE_GEMINI_CLI_MODELS } from "./models.js";
|
|
11
|
+
import { isAntigravityCliReady, isGeminiCliReady } from "./readiness.js";
|
|
12
|
+
import { streamViaGoogleCli } from "./stream-adapter.js";
|
|
13
|
+
|
|
14
|
+
export default function googleCli(pi: ExtensionAPI) {
|
|
15
|
+
pi.registerProvider("google-gemini-cli", {
|
|
16
|
+
name: "Google Gemini CLI",
|
|
17
|
+
authMode: "externalCli",
|
|
18
|
+
api: "google-gemini-cli",
|
|
19
|
+
baseUrl: "local://google-gemini-cli",
|
|
20
|
+
isReady: isGeminiCliReady,
|
|
21
|
+
streamSimple: streamViaGoogleCli,
|
|
22
|
+
models: GOOGLE_GEMINI_CLI_MODELS,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
pi.registerProvider("google-antigravity", {
|
|
26
|
+
name: "Google Antigravity",
|
|
27
|
+
authMode: "externalCli",
|
|
28
|
+
api: "google-antigravity",
|
|
29
|
+
baseUrl: "local://google-antigravity",
|
|
30
|
+
isReady: isAntigravityCliReady,
|
|
31
|
+
streamSimple: streamViaGoogleCli,
|
|
32
|
+
models: GOOGLE_ANTIGRAVITY_MODELS,
|
|
33
|
+
});
|
|
34
|
+
}
|