@code-yeongyu/senpi 2026.9.21-2 → 2026.9.22
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/CHANGELOG.md +21 -0
- package/dist/bundle/chunks/{anthropic-messages-C3ZY2ANT.js → anthropic-messages-2P7APOOQ.js} +1 -1
- package/dist/bundle/chunks/{app-server-command-HSX5RFAP.js → app-server-command-DLBXJ5K5.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-7TAGS2VU.js → azure-openai-responses-3AH7MJWF.js} +1 -1
- package/dist/bundle/chunks/{chunk-3SLCHXZO.js → chunk-4AXZDO3E.js} +2 -2
- package/dist/bundle/chunks/{chunk-Z3KQB2R3.js → chunk-7ICH7UFW.js} +12 -12
- package/dist/bundle/chunks/{chunk-KNM6SRPE.js → chunk-AAVNXTGQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-IDTLJYJ5.js → chunk-AY37SZJZ.js} +4 -4
- package/dist/bundle/chunks/{chunk-XHMOFY4T.js → chunk-BUPX33Q4.js} +3 -3
- package/dist/bundle/chunks/{chunk-GLKVDRNP.js → chunk-CWCY7LXK.js} +1 -1
- package/dist/bundle/chunks/{chunk-POMPEGWQ.js → chunk-F3DXL5MX.js} +1 -1
- package/dist/bundle/chunks/{chunk-GVI2HP7N.js → chunk-I2HIIJPI.js} +1 -1
- package/dist/bundle/chunks/{chunk-T6XA2IZR.js → chunk-JR4X6ECO.js} +1 -1
- package/dist/bundle/chunks/{chunk-M2XAY6I7.js → chunk-M2HSO7MH.js} +1 -1
- package/dist/bundle/chunks/{chunk-MIVOQT3Q.js → chunk-N5AQJAQ2.js} +1 -1
- package/dist/bundle/chunks/{chunk-UYVPLEOL.js → chunk-NK2RNX25.js} +1 -1
- package/dist/bundle/chunks/chunk-NMB4C6ZZ.js +2 -0
- package/dist/bundle/chunks/{chunk-B7W62BM7.js → chunk-P4OHEJ7P.js} +1 -1
- package/dist/bundle/chunks/{chunk-I425CMTO.js → chunk-VBNHBSBD.js} +1 -1
- package/dist/bundle/chunks/{chunk-B2IM56LB.js → chunk-VYIJQQ5I.js} +1 -1
- package/dist/bundle/chunks/chunk-XRHUMMIW.js +8 -0
- package/dist/bundle/chunks/{chunk-47GF6XYZ.js → chunk-YT2ZSZOY.js} +1 -1
- package/dist/bundle/chunks/{chunk-OSDJ2SYO.js → chunk-ZCBX2K34.js} +1 -1
- package/dist/bundle/chunks/{chunk-D5CL7PPD.js → chunk-ZMVXBX33.js} +2 -2
- package/dist/bundle/chunks/{cli-main-GQTEEZ2V.js → cli-main-D2VPNIQ3.js} +1 -1
- package/dist/bundle/chunks/{google-generative-ai-JWIH75VF.js → google-generative-ai-Y2IYMUVC.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-IRGAY5XR.js → google-vertex-TKBBMPHV.js} +1 -1
- package/dist/bundle/chunks/{host-command-KOEKIHIZ.js → host-command-IFIIOX5S.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle-3OJZA4QQ.js +3 -0
- package/dist/bundle/chunks/host-lifecycle.js +3 -3
- package/dist/bundle/chunks/{interactive-host-runtime-2KTFEW7O.js → interactive-host-runtime-V7PBDIOJ.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-I3ILWXQB.js → interactive-mode-RFMMGQCT.js} +1 -1
- package/dist/bundle/chunks/kimi-coding.js +2 -2
- package/dist/bundle/chunks/{mistral-conversations-VOBYATVJ.js → mistral-conversations-ZYDVFRYF.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-S5FWCIWE.js → multi-session-host-45YMCQIH.js} +8 -7
- package/dist/bundle/chunks/openai-codex-responses-MEIUNROM.js +10 -0
- package/dist/bundle/chunks/{openai-completions-YK6QTYOH.js → openai-completions-4V76L5ZJ.js} +1 -1
- package/dist/bundle/chunks/openai-responses-YR7WRBG3.js +2 -0
- package/dist/bundle/chunks/{package-manager-cli-HOL6CAI6.js → package-manager-cli-7DQKRSI5.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-YPZP3VJS.js +2 -0
- package/dist/bundle/chunks/{rpc-mode-L3DSGTVM.js → rpc-mode-4GWZCJKI.js} +1 -1
- package/dist/bundle/chunks/{session-picker-L3FYEQBL.js → session-picker-ZKRYWZGC.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +38 -37
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +6 -4
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +9 -7
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/credential-pool/classify.d.ts.map +1 -1
- package/dist/core/credential-pool/classify.js +12 -0
- package/dist/core/credential-pool/classify.js.map +1 -1
- package/dist/core/credential-pool/failover.d.ts +37 -5
- package/dist/core/credential-pool/failover.d.ts.map +1 -1
- package/dist/core/credential-pool/failover.js +60 -24
- package/dist/core/credential-pool/failover.js.map +1 -1
- package/dist/core/credential-pool/rotation-events.d.ts +5 -0
- package/dist/core/credential-pool/rotation-events.d.ts.map +1 -0
- package/dist/core/credential-pool/rotation-events.js +25 -0
- package/dist/core/credential-pool/rotation-events.js.map +1 -0
- package/dist/core/credential-pool/rotation-stream.d.ts +4 -3
- package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -1
- package/dist/core/credential-pool/rotation-stream.js +8 -11
- package/dist/core/credential-pool/rotation-stream.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/schema.d.ts +2 -25
- package/dist/core/extensions/builtin/ask-user/schema.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/schema.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +2 -7
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +2 -8
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/naming.d.ts +0 -1
- package/dist/core/extensions/builtin/mcp/expose/naming.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/naming.js +0 -3
- package/dist/core/extensions/builtin/mcp/expose/naming.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/register.d.ts +1 -2
- package/dist/core/extensions/builtin/mcp/expose/register.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/register.js +0 -21
- package/dist/core/extensions/builtin/mcp/expose/register.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.d.ts +2 -2
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.js +2 -2
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +29 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +30 -3
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.js +8 -7
- package/dist/modes/interactive/components/assistant-render-descriptors.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +7 -5
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/handoff-activity.d.ts +4 -0
- package/dist/modes/rpc/handoff-activity.d.ts.map +1 -0
- package/dist/modes/rpc/handoff-activity.js +6 -0
- package/dist/modes/rpc/handoff-activity.js.map +1 -0
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
- package/dist/modes/rpc/host-ensure.js +60 -17
- package/dist/modes/rpc/host-ensure.js.map +1 -1
- package/dist/modes/rpc/host-lifecycle.d.ts +3 -0
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +25 -5
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.d.ts +1 -0
- package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +40 -7
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +13 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts +10 -4
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +90 -18
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +5 -3
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +21 -2
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-worker-client.d.ts +1 -0
- package/dist/modes/rpc/session-worker-client.d.ts.map +1 -1
- package/dist/modes/rpc/session-worker-client.js +3 -0
- package/dist/modes/rpc/session-worker-client.js.map +1 -1
- package/dist/modes/rpc/session-worker-protocol.d.ts +3 -1
- package/dist/modes/rpc/session-worker-protocol.d.ts.map +1 -1
- package/dist/modes/rpc/session-worker-protocol.js.map +1 -1
- package/dist/modes/rpc/session-worker.js +7 -1
- package/dist/modes/rpc/session-worker.js.map +1 -1
- package/docs/providers.md +9 -1
- package/docs/rpc.md +58 -8
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +15 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +51 -13
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/agent-bridge.ts +53 -9
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/reserved-dispatch.ts +1 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/config/settings.ts +18 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/eval-status.ts +9 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +3 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/AGENTS.md +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/prelude.jl +10 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +18 -6
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-contract.ts +2 -6
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/prelude.ts +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/run-queue.ts +17 -7
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +6 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel-contract.ts +2 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel.ts +37 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +11 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/prelude.rb +6 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-contract.ts +2 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-kernel.ts +14 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-queue.ts +18 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt-template.ts +3 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +4 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/timeouts/idle-timeout.ts +9 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/AGENTS.md +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-execution.ts +19 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-runtime.ts +11 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-contract.ts +6 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +72 -20
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-snapshot.ts +28 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-state.ts +5 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-status.ts +5 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-eval-result.ts +76 -25
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-execution-event.ts +4 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-kernel-reset-refused-error.ts +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-request.ts +2 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool-options.ts +3 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +58 -37
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/managed-cell.ts +15 -8
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +20 -6
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/run-eval-cell.ts +89 -25
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/terminal-snapshot-store.ts +4 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +51 -10
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/README.md +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +14 -56
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +18 -27
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/websocket-transport-failure.d.ts +40 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/websocket-transport-failure.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/websocket-transport-failure.js +102 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/websocket-transport-failure.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts +4 -3
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +28 -14
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-region.d.ts +44 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-region.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-region.js +120 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-region.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.d.ts +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.js +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +21 -15
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding-auth.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding-auth.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding-auth.js +43 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding-auth.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.d.ts +19 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.js +63 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/chunk-5J5R5AMP.js +0 -8
- package/dist/bundle/chunks/chunk-I3F6VZZF.js +0 -2
- package/dist/bundle/chunks/host-lifecycle-DGZJTBDJ.js +0 -3
- package/dist/bundle/chunks/openai-codex-responses-L2PO2D6F.js +0 -10
- package/dist/bundle/chunks/openai-responses-YDUBVF4S.js +0 -2
- package/dist/bundle/chunks/rotation-stream-Y4YU6HV4.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-compat.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/schema-compat.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { type TSchema, Type } from \"typebox\";\nimport { buildMcpToolName, buildMcpToolNames, type McpToolNameEntry } from \"./naming.ts\";\nimport { collectAllPages, type McpListPage, type McpPaginationResult } from \"./pagination.ts\";\n\nexport type { McpListPage, McpPaginationResult, McpToolNameEntry };\nexport { buildMcpToolName, buildMcpToolNames, collectAllPages };\n\ninterface SchemaConversionResult {\n\tschema: TSchema;\n\twarnings: string[];\n}\n\ninterface OutputSchemaRetryResult {\n\tschema: Record<string, unknown>;\n\twarnings: string[];\n}\n\nexport type McpContentBlock =\n\t| { type: \"text\"; text?: unknown }\n\t| { type: \"image\"; data?: unknown; mimeType?: unknown }\n\t| { type: \"audio\"; data?: unknown; mimeType?: unknown }\n\t| { type: \"resource\"; resource?: unknown }\n\t| { type: \"resource_link\"; uri?: unknown; name?: unknown; description?: unknown; mimeType?: unknown }\n\t| Record<string, unknown>;\n\nexport type McpMappedContentBlock =\n\t| TextContent\n\t| ImageContent\n\t| { type: \"audio\"; data: string; mimeType: string }\n\t| { type: \"resource\"; resource: unknown }\n\t| { type: \"resource_link\"; uri: string; name?: string; description?: string; mimeType?: string };\n\nexport interface McpToolResultLike {\n\tcontent?: McpContentBlock[];\n\tstructuredContent?: unknown;\n\tisError?: boolean;\n}\n\nexport type McpMappedToolResult =\n\t| { ok: true; content: McpMappedContentBlock[] }\n\t| { ok: false; error: { message: string; content: McpMappedContentBlock[] } };\n\nconst PERMISSIVE_OBJECT_SCHEMA = { type: \"object\", properties: {} } as const;\n\nexport function convertJsonSchemaToTypeBox(schema: unknown): SchemaConversionResult {\n\tconst warnings: string[] = [];\n\tconst resolved = resolveRefs(stripTopLevelSchemaKeys(schema), schema, new Set<string>(), warnings);\n\tif (warnings.length > 0) {\n\t\treturn { schema: Type.Unsafe<unknown>({ ...PERMISSIVE_OBJECT_SCHEMA }), warnings };\n\t}\n\tif (!isRecord(resolved)) {\n\t\treturn {\n\t\t\tschema: Type.Unsafe<unknown>({ ...PERMISSIVE_OBJECT_SCHEMA }),\n\t\t\twarnings: [\"MCP schema is not an object; using permissive object schema.\"],\n\t\t};\n\t}\n\treturn { schema: Type.Unsafe<unknown>(resolved), warnings };\n}\n\nexport function prepareOutputSchemaRetry(schema: unknown): OutputSchemaRetryResult {\n\tconst warnings: string[] = [];\n\tconst record: Record<string, unknown> = isRecord(schema) ? { ...schema } : { ...PERMISSIVE_OBJECT_SCHEMA };\n\tif (hasOwn(record, \"$schema\")) {\n\t\tdelete record.$schema;\n\t\twarnings.push(\"Stripped top-level $schema from MCP outputSchema retry.\");\n\t}\n\tif (hasOwn(record, \"additionalProperties\")) {\n\t\tdelete record.additionalProperties;\n\t\twarnings.push(\"Stripped top-level additionalProperties from MCP outputSchema retry.\");\n\t}\n\treturn { schema: record, warnings };\n}\n\nexport function mapMcpToolResult(result: McpToolResultLike): McpMappedToolResult {\n\tconst content = mapMcpContent(result);\n\tif (result.isError === true) {\n\t\treturn { ok: false, error: { message: contentToErrorMessage(content), content } };\n\t}\n\treturn { ok: true, content };\n}\n\nfunction mapMcpContent(result: McpToolResultLike): McpMappedContentBlock[] {\n\tconst content: McpMappedContentBlock[] = [];\n\tfor (const block of result.content ?? []) {\n\t\tcontent.push(mapContentBlock(block));\n\t}\n\tif (result.structuredContent !== undefined) {\n\t\tcontent.push({ type: \"text\", text: stringifyJson(result.structuredContent) });\n\t}\n\tif (content.length === 0) {\n\t\tcontent.push({ type: \"text\", text: \"(empty result)\" });\n\t}\n\treturn content;\n}\n\nfunction mapContentBlock(block: McpContentBlock): McpMappedContentBlock {\n\tif (block.type === \"text\") {\n\t\treturn { type: \"text\", text: typeof block.text === \"string\" ? block.text : stringifyJson(block.text) };\n\t}\n\tif (block.type === \"image\" && typeof block.data === \"string\" && typeof block.mimeType === \"string\") {\n\t\treturn { type: \"image\", data: block.data, mimeType: block.mimeType };\n\t}\n\tif (block.type === \"audio\" && typeof block.data === \"string\" && typeof block.mimeType === \"string\") {\n\t\treturn { type: \"audio\", data: block.data, mimeType: block.mimeType };\n\t}\n\tif (block.type === \"resource\" && hasOwn(block, \"resource\")) {\n\t\treturn { type: \"resource\", resource: block.resource };\n\t}\n\tif (block.type === \"resource_link\" && typeof block.uri === \"string\") {\n\t\treturn {\n\t\t\ttype: \"resource_link\",\n\t\t\turi: block.uri,\n\t\t\t...(typeof block.name === \"string\" ? { name: block.name } : {}),\n\t\t\t...(typeof block.description === \"string\" ? { description: block.description } : {}),\n\t\t\t...(typeof block.mimeType === \"string\" ? { mimeType: block.mimeType } : {}),\n\t\t};\n\t}\n\treturn { type: \"text\", text: stringifyJson(block) };\n}\n\nfunction contentToErrorMessage(content: readonly McpMappedContentBlock[]): string {\n\tconst firstText = content.find((block): block is TextContent => block.type === \"text\");\n\treturn firstText?.text.trim() || \"MCP tool returned an error result.\";\n}\n\nfunction stripTopLevelSchemaKeys(schema: unknown): unknown {\n\tif (!isRecord(schema)) return schema;\n\tconst result = { ...schema };\n\tdelete result.$schema;\n\tdelete result.additionalProperties;\n\treturn result;\n}\n\nfunction resolveRefs(value: unknown, root: unknown, seenRefs: Set<string>, warnings: string[]): unknown {\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => resolveRefs(entry, root, seenRefs, warnings));\n\t}\n\tif (!isRecord(value)) return value;\n\n\tif (typeof value.$ref === \"string\") {\n\t\tconst ref = value.$ref;\n\t\tconst resolved = resolveLocalRef(root, ref);\n\t\tif (resolved === undefined || seenRefs.has(ref)) {\n\t\t\twarnings.push(`MCP schema contains unresolvable $ref '${ref}'; using permissive object schema.`);\n\t\t\treturn { ...PERMISSIVE_OBJECT_SCHEMA };\n\t\t}\n\t\tconst nextSeenRefs = new Set(seenRefs);\n\t\tnextSeenRefs.add(ref);\n\t\treturn resolveRefs(resolved, root, nextSeenRefs, warnings);\n\t}\n\n\tconst result: Record<string, unknown> = {};\n\tfor (const [key, child] of Object.entries(value)) {\n\t\tif (key === \"type\" && child === null) continue;\n\t\tresult[key] = resolveRefs(child, root, seenRefs, warnings);\n\t}\n\treturn result;\n}\n\nfunction resolveLocalRef(root: unknown, ref: string): unknown {\n\tif (!ref.startsWith(\"#/\")) return undefined;\n\tlet current: unknown = root;\n\tfor (const part of ref\n\t\t.slice(2)\n\t\t.split(\"/\")\n\t\t.map((segment) => segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\"))) {\n\t\tif (!isRecord(current) || !(part in current)) return undefined;\n\t\tcurrent = current[part];\n\t}\n\treturn current;\n}\n\nfunction stringifyJson(value: unknown): string {\n\tconst text = JSON.stringify(value);\n\treturn text ?? String(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction hasOwn(value: Record<string, unknown>, key: string): boolean {\n\treturn Object.getOwnPropertyDescriptor(value, key) !== undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"schema-compat.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/schema-compat.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { type TSchema, Type } from \"typebox\";\nimport { buildMcpToolNames, type McpToolNameEntry } from \"./naming.ts\";\nimport { collectAllPages, type McpListPage, type McpPaginationResult } from \"./pagination.ts\";\n\nexport type { McpListPage, McpPaginationResult, McpToolNameEntry };\nexport { buildMcpToolNames, collectAllPages };\n\ninterface SchemaConversionResult {\n\tschema: TSchema;\n\twarnings: string[];\n}\n\ninterface OutputSchemaRetryResult {\n\tschema: Record<string, unknown>;\n\twarnings: string[];\n}\n\nexport type McpContentBlock =\n\t| { type: \"text\"; text?: unknown }\n\t| { type: \"image\"; data?: unknown; mimeType?: unknown }\n\t| { type: \"audio\"; data?: unknown; mimeType?: unknown }\n\t| { type: \"resource\"; resource?: unknown }\n\t| { type: \"resource_link\"; uri?: unknown; name?: unknown; description?: unknown; mimeType?: unknown }\n\t| Record<string, unknown>;\n\nexport type McpMappedContentBlock =\n\t| TextContent\n\t| ImageContent\n\t| { type: \"audio\"; data: string; mimeType: string }\n\t| { type: \"resource\"; resource: unknown }\n\t| { type: \"resource_link\"; uri: string; name?: string; description?: string; mimeType?: string };\n\nexport interface McpToolResultLike {\n\tcontent?: McpContentBlock[];\n\tstructuredContent?: unknown;\n\tisError?: boolean;\n}\n\nexport type McpMappedToolResult =\n\t| { ok: true; content: McpMappedContentBlock[] }\n\t| { ok: false; error: { message: string; content: McpMappedContentBlock[] } };\n\nconst PERMISSIVE_OBJECT_SCHEMA = { type: \"object\", properties: {} } as const;\n\nexport function convertJsonSchemaToTypeBox(schema: unknown): SchemaConversionResult {\n\tconst warnings: string[] = [];\n\tconst resolved = resolveRefs(stripTopLevelSchemaKeys(schema), schema, new Set<string>(), warnings);\n\tif (warnings.length > 0) {\n\t\treturn { schema: Type.Unsafe<unknown>({ ...PERMISSIVE_OBJECT_SCHEMA }), warnings };\n\t}\n\tif (!isRecord(resolved)) {\n\t\treturn {\n\t\t\tschema: Type.Unsafe<unknown>({ ...PERMISSIVE_OBJECT_SCHEMA }),\n\t\t\twarnings: [\"MCP schema is not an object; using permissive object schema.\"],\n\t\t};\n\t}\n\treturn { schema: Type.Unsafe<unknown>(resolved), warnings };\n}\n\nexport function prepareOutputSchemaRetry(schema: unknown): OutputSchemaRetryResult {\n\tconst warnings: string[] = [];\n\tconst record: Record<string, unknown> = isRecord(schema) ? { ...schema } : { ...PERMISSIVE_OBJECT_SCHEMA };\n\tif (hasOwn(record, \"$schema\")) {\n\t\tdelete record.$schema;\n\t\twarnings.push(\"Stripped top-level $schema from MCP outputSchema retry.\");\n\t}\n\tif (hasOwn(record, \"additionalProperties\")) {\n\t\tdelete record.additionalProperties;\n\t\twarnings.push(\"Stripped top-level additionalProperties from MCP outputSchema retry.\");\n\t}\n\treturn { schema: record, warnings };\n}\n\nexport function mapMcpToolResult(result: McpToolResultLike): McpMappedToolResult {\n\tconst content = mapMcpContent(result);\n\tif (result.isError === true) {\n\t\treturn { ok: false, error: { message: contentToErrorMessage(content), content } };\n\t}\n\treturn { ok: true, content };\n}\n\nfunction mapMcpContent(result: McpToolResultLike): McpMappedContentBlock[] {\n\tconst content: McpMappedContentBlock[] = [];\n\tfor (const block of result.content ?? []) {\n\t\tcontent.push(mapContentBlock(block));\n\t}\n\tif (result.structuredContent !== undefined) {\n\t\tcontent.push({ type: \"text\", text: stringifyJson(result.structuredContent) });\n\t}\n\tif (content.length === 0) {\n\t\tcontent.push({ type: \"text\", text: \"(empty result)\" });\n\t}\n\treturn content;\n}\n\nfunction mapContentBlock(block: McpContentBlock): McpMappedContentBlock {\n\tif (block.type === \"text\") {\n\t\treturn { type: \"text\", text: typeof block.text === \"string\" ? block.text : stringifyJson(block.text) };\n\t}\n\tif (block.type === \"image\" && typeof block.data === \"string\" && typeof block.mimeType === \"string\") {\n\t\treturn { type: \"image\", data: block.data, mimeType: block.mimeType };\n\t}\n\tif (block.type === \"audio\" && typeof block.data === \"string\" && typeof block.mimeType === \"string\") {\n\t\treturn { type: \"audio\", data: block.data, mimeType: block.mimeType };\n\t}\n\tif (block.type === \"resource\" && hasOwn(block, \"resource\")) {\n\t\treturn { type: \"resource\", resource: block.resource };\n\t}\n\tif (block.type === \"resource_link\" && typeof block.uri === \"string\") {\n\t\treturn {\n\t\t\ttype: \"resource_link\",\n\t\t\turi: block.uri,\n\t\t\t...(typeof block.name === \"string\" ? { name: block.name } : {}),\n\t\t\t...(typeof block.description === \"string\" ? { description: block.description } : {}),\n\t\t\t...(typeof block.mimeType === \"string\" ? { mimeType: block.mimeType } : {}),\n\t\t};\n\t}\n\treturn { type: \"text\", text: stringifyJson(block) };\n}\n\nfunction contentToErrorMessage(content: readonly McpMappedContentBlock[]): string {\n\tconst firstText = content.find((block): block is TextContent => block.type === \"text\");\n\treturn firstText?.text.trim() || \"MCP tool returned an error result.\";\n}\n\nfunction stripTopLevelSchemaKeys(schema: unknown): unknown {\n\tif (!isRecord(schema)) return schema;\n\tconst result = { ...schema };\n\tdelete result.$schema;\n\tdelete result.additionalProperties;\n\treturn result;\n}\n\nfunction resolveRefs(value: unknown, root: unknown, seenRefs: Set<string>, warnings: string[]): unknown {\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => resolveRefs(entry, root, seenRefs, warnings));\n\t}\n\tif (!isRecord(value)) return value;\n\n\tif (typeof value.$ref === \"string\") {\n\t\tconst ref = value.$ref;\n\t\tconst resolved = resolveLocalRef(root, ref);\n\t\tif (resolved === undefined || seenRefs.has(ref)) {\n\t\t\twarnings.push(`MCP schema contains unresolvable $ref '${ref}'; using permissive object schema.`);\n\t\t\treturn { ...PERMISSIVE_OBJECT_SCHEMA };\n\t\t}\n\t\tconst nextSeenRefs = new Set(seenRefs);\n\t\tnextSeenRefs.add(ref);\n\t\treturn resolveRefs(resolved, root, nextSeenRefs, warnings);\n\t}\n\n\tconst result: Record<string, unknown> = {};\n\tfor (const [key, child] of Object.entries(value)) {\n\t\tif (key === \"type\" && child === null) continue;\n\t\tresult[key] = resolveRefs(child, root, seenRefs, warnings);\n\t}\n\treturn result;\n}\n\nfunction resolveLocalRef(root: unknown, ref: string): unknown {\n\tif (!ref.startsWith(\"#/\")) return undefined;\n\tlet current: unknown = root;\n\tfor (const part of ref\n\t\t.slice(2)\n\t\t.split(\"/\")\n\t\t.map((segment) => segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\"))) {\n\t\tif (!isRecord(current) || !(part in current)) return undefined;\n\t\tcurrent = current[part];\n\t}\n\treturn current;\n}\n\nfunction stringifyJson(value: unknown): string {\n\tconst text = JSON.stringify(value);\n\treturn text ?? String(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction hasOwn(value: Record<string, unknown>, key: string): boolean {\n\treturn Object.getOwnPropertyDescriptor(value, key) !== undefined;\n}\n"]}
|
|
@@ -15,6 +15,35 @@ export declare const HTTP_IDLE_TIMEOUT_CHOICES: readonly [{
|
|
|
15
15
|
readonly label: "disabled";
|
|
16
16
|
readonly timeoutMs: 0;
|
|
17
17
|
}];
|
|
18
|
+
/** Facts the global-install decision reads; injected so the decision is testable per runtime. */
|
|
19
|
+
export interface UndiciGlobalsInstallInput {
|
|
20
|
+
/** `process.versions`; a `bun` entry means this process IS Bun. */
|
|
21
|
+
readonly versions: Readonly<Record<string, string | undefined>>;
|
|
22
|
+
/** `globalThis.fetch` at the time of the call. */
|
|
23
|
+
readonly currentFetch: unknown;
|
|
24
|
+
/** `globalThis.fetch` captured when this module loaded. */
|
|
25
|
+
readonly originalFetch: unknown;
|
|
26
|
+
/** `globalThis.fetch` left behind by the previous install, if any. */
|
|
27
|
+
readonly installedFetch: unknown;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Whether `configureHttpDispatcher` may replace the global `fetch` (and the
|
|
31
|
+
* WebSocket/Headers/Request/Response constructors) with the bundled Undici
|
|
32
|
+
* implementation.
|
|
33
|
+
*
|
|
34
|
+
* Bun keeps its native fetch: the distributed CLI inlines npm undici, and its
|
|
35
|
+
* fetch running on Bun 1.3.x answers with the response headers but never
|
|
36
|
+
* delivers a streamed body, so every SSE model response stalls after the
|
|
37
|
+
* headers (#1890). Bun's own fetch honors HTTP_PROXY / HTTPS_PROXY / NO_PROXY,
|
|
38
|
+
* which `applyHttpProxySettings` sets, and stream stalls stay bounded by the
|
|
39
|
+
* agent-level idle and stream-start guards derived from the same
|
|
40
|
+
* `httpIdleTimeoutMs` setting.
|
|
41
|
+
*
|
|
42
|
+
* Node installs the globals so fetch and the dispatcher share one undici
|
|
43
|
+
* implementation (see the call site); a caller that deliberately replaced
|
|
44
|
+
* `fetch` after module load keeps its override.
|
|
45
|
+
*/
|
|
46
|
+
export declare function shouldInstallUndiciGlobals(input: UndiciGlobalsInstallInput): boolean;
|
|
18
47
|
export declare function parseHttpIdleTimeoutMs(value: unknown): number | undefined;
|
|
19
48
|
export declare function formatHttpIdleTimeoutMs(timeoutMs: number): string;
|
|
20
49
|
export declare function applyHttpProxySettings(httpProxy: string | undefined): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAIpD,eAAO,MAAM,yBAAyB;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,KAAM;;aAClC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,KAAM;;aACjC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,MAAO;;aAClC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,MAAO;;aAClC,KAAK,EAAE,UAAU;aAAE,SAAS,EAAE,CAAC;EACxB,CAAC;
|
|
1
|
+
{"version":3,"file":"http-dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAIpD,eAAO,MAAM,yBAAyB;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,KAAM;;aAClC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,KAAM;;aACjC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,MAAO;;aAClC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,MAAO;;aAClC,KAAK,EAAE,UAAU;aAAE,SAAS,EAAE,CAAC;EACxB,CAAC;AAMX,iGAAiG;AACjG,MAAM,WAAW,yBAAyB;IACzC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAChE,kDAAkD;IAClD,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,2DAA2D;IAC3D,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,sEAAsE;IACtE,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAKpF;AAMD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAgBzE;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAa1E;AA+BD,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAqC,GAAG,IAAI,CA0C9F"}
|
|
@@ -13,6 +13,30 @@ export const HTTP_IDLE_TIMEOUT_CHOICES = [
|
|
|
13
13
|
const originalGlobalFetch = globalThis.fetch;
|
|
14
14
|
let installedGlobalFetch;
|
|
15
15
|
let multiSessionDispatcherTimeoutMs;
|
|
16
|
+
/**
|
|
17
|
+
* Whether `configureHttpDispatcher` may replace the global `fetch` (and the
|
|
18
|
+
* WebSocket/Headers/Request/Response constructors) with the bundled Undici
|
|
19
|
+
* implementation.
|
|
20
|
+
*
|
|
21
|
+
* Bun keeps its native fetch: the distributed CLI inlines npm undici, and its
|
|
22
|
+
* fetch running on Bun 1.3.x answers with the response headers but never
|
|
23
|
+
* delivers a streamed body, so every SSE model response stalls after the
|
|
24
|
+
* headers (#1890). Bun's own fetch honors HTTP_PROXY / HTTPS_PROXY / NO_PROXY,
|
|
25
|
+
* which `applyHttpProxySettings` sets, and stream stalls stay bounded by the
|
|
26
|
+
* agent-level idle and stream-start guards derived from the same
|
|
27
|
+
* `httpIdleTimeoutMs` setting.
|
|
28
|
+
*
|
|
29
|
+
* Node installs the globals so fetch and the dispatcher share one undici
|
|
30
|
+
* implementation (see the call site); a caller that deliberately replaced
|
|
31
|
+
* `fetch` after module load keeps its override.
|
|
32
|
+
*/
|
|
33
|
+
export function shouldInstallUndiciGlobals(input) {
|
|
34
|
+
if (input.versions.bun !== undefined)
|
|
35
|
+
return false;
|
|
36
|
+
return input.installedFetch === undefined
|
|
37
|
+
? input.currentFetch === input.originalFetch
|
|
38
|
+
: input.currentFetch === input.installedFetch;
|
|
39
|
+
}
|
|
16
40
|
function isMultiSessionRpcProcess() {
|
|
17
41
|
return process.argv.includes("--multi-session");
|
|
18
42
|
}
|
|
@@ -103,9 +127,12 @@ export function configureHttpDispatcher(timeoutMs = DEFAULT_HTTP_IDLE_TIMEOUT_MS
|
|
|
103
127
|
// bundled fetch can otherwise consume compressed responses through npm undici's
|
|
104
128
|
// dispatcher without decompressing them, causing response.json() failures.
|
|
105
129
|
// If a caller replaced fetch after module load, preserve that deliberate override.
|
|
106
|
-
const shouldInstallGlobals =
|
|
107
|
-
|
|
108
|
-
: globalThis.fetch
|
|
130
|
+
const shouldInstallGlobals = shouldInstallUndiciGlobals({
|
|
131
|
+
versions: process.versions,
|
|
132
|
+
currentFetch: globalThis.fetch,
|
|
133
|
+
originalFetch: originalGlobalFetch,
|
|
134
|
+
installedFetch: installedGlobalFetch,
|
|
135
|
+
});
|
|
109
136
|
if (shouldInstallGlobals) {
|
|
110
137
|
undici.install?.();
|
|
111
138
|
installedGlobalFetch = globalThis.fetch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-dispatcher.js","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"node:events\";\nimport * as undici from \"undici\";\n\nexport const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300_000;\n// Node's 250ms default can terminate valid connection attempts on high-latency routes.\nconst DEFAULT_AUTO_SELECT_FAMILY_ATTEMPT_TIMEOUT_MS = 2_000;\n\nexport const HTTP_IDLE_TIMEOUT_CHOICES = [\n\t{ label: \"30 sec\", timeoutMs: 30_000 },\n\t{ label: \"1 min\", timeoutMs: 60_000 },\n\t{ label: \"2 min\", timeoutMs: 120_000 },\n\t{ label: \"5 min\", timeoutMs: 300_000 },\n\t{ label: \"disabled\", timeoutMs: 0 },\n] as const;\n\nconst originalGlobalFetch = globalThis.fetch;\nlet installedGlobalFetch: typeof globalThis.fetch | undefined;\nlet multiSessionDispatcherTimeoutMs: number | undefined;\n\nfunction isMultiSessionRpcProcess(): boolean {\n\treturn process.argv.includes(\"--multi-session\");\n}\n\nexport function parseHttpIdleTimeoutMs(value: unknown): number | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst trimmed = value.trim();\n\t\tif (trimmed.toLowerCase() === \"disabled\") {\n\t\t\treturn 0;\n\t\t}\n\t\tif (trimmed.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn parseHttpIdleTimeoutMs(Number(trimmed));\n\t}\n\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n\t\treturn undefined;\n\t}\n\treturn Math.floor(value);\n}\n\nexport function formatHttpIdleTimeoutMs(timeoutMs: number): string {\n\tconst choice = HTTP_IDLE_TIMEOUT_CHOICES.find((item) => item.timeoutMs === timeoutMs);\n\tif (choice) {\n\t\treturn choice.label;\n\t}\n\treturn `${timeoutMs / 1000} sec`;\n}\n\nexport function applyHttpProxySettings(httpProxy: string | undefined): void {\n\tconst proxy = httpProxy?.trim();\n\tif (!proxy) return;\n\tif (isMultiSessionRpcProcess()) {\n\t\tconst existing = process.env.HTTP_PROXY ?? process.env.HTTPS_PROXY;\n\t\tif (existing !== undefined && existing !== proxy) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Multi-session RPC shares one process-global HTTP proxy; proxy settings must be fixed at process startup.\",\n\t\t\t);\n\t\t}\n\t}\n\tprocess.env.HTTP_PROXY ??= proxy;\n\tprocess.env.HTTPS_PROXY ??= proxy;\n}\n\nconst ignoreUndiciDispatcherError = (_error: unknown): void => {};\n\n// Undici can emit an internal Client \"error\" while terminating a mid-stream\n// fetch body. The body stream still rejects through reader.read(); this listener\n// only prevents EventEmitter's unhandled \"error\" special case from crashing pi.\nfunction withUndiciErrorListener<T extends undici.Dispatcher>(dispatcher: T): T {\n\tif (dispatcher instanceof EventEmitter) {\n\t\tEventEmitter.prototype.on.call(dispatcher, \"error\", ignoreUndiciDispatcherError);\n\t}\n\treturn dispatcher;\n}\n\nfunction createUndiciClient(origin: string | URL, options: object): undici.Dispatcher {\n\treturn withUndiciErrorListener(new undici.Client(origin, options as undici.Client.Options));\n}\n\nfunction createUndiciOriginDispatcher(origin: string | URL, options: object): undici.Dispatcher {\n\tconst dispatcherOptions = options as undici.Pool.Options;\n\tif (dispatcherOptions.connections === 1) {\n\t\treturn createUndiciClient(origin, dispatcherOptions);\n\t}\n\treturn withUndiciErrorListener(\n\t\tnew undici.Pool(origin, {\n\t\t\t...dispatcherOptions,\n\t\t\tfactory: createUndiciClient,\n\t\t}),\n\t);\n}\n\nexport function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TIMEOUT_MS): void {\n\tconst normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);\n\tif (normalizedTimeoutMs === undefined) {\n\t\tthrow new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);\n\t}\n\tif (isMultiSessionRpcProcess()) {\n\t\tif (multiSessionDispatcherTimeoutMs !== undefined && multiSessionDispatcherTimeoutMs !== normalizedTimeoutMs) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Multi-session RPC shares one process-global Undici dispatcher; HTTP idle timeout must be fixed at process startup.\",\n\t\t\t);\n\t\t}\n\t\tmultiSessionDispatcherTimeoutMs = normalizedTimeoutMs;\n\t}\n\tconst dispatcher = withUndiciErrorListener(\n\t\tnew undici.EnvHttpProxyAgent({\n\t\t\tallowH2: false,\n\t\t\t// Keep HTTP origins on CONNECT tunnels as they were before Undici 8.7.\n\t\t\tproxyTunnel: true,\n\t\t\tbodyTimeout: normalizedTimeoutMs,\n\t\t\tconnect: {\n\t\t\t\tautoSelectFamilyAttemptTimeout: DEFAULT_AUTO_SELECT_FAMILY_ATTEMPT_TIMEOUT_MS,\n\t\t\t},\n\t\t\theadersTimeout: normalizedTimeoutMs,\n\t\t\tclientFactory: createUndiciClient,\n\t\t\tfactory: createUndiciOriginDispatcher,\n\t\t}),\n\t);\n\tundici.setGlobalDispatcher(dispatcher);\n\t// Keep fetch and the dispatcher on the same undici implementation. Node 26.0's\n\t// bundled fetch can otherwise consume compressed responses through npm undici's\n\t// dispatcher without decompressing them, causing response.json() failures.\n\t// If a caller replaced fetch after module load, preserve that deliberate override.\n\tconst shouldInstallGlobals =\n\t\tinstalledGlobalFetch === undefined\n\t\t\t? globalThis.fetch === originalGlobalFetch\n\t\t\t: globalThis.fetch === installedGlobalFetch;\n\tif (shouldInstallGlobals) {\n\t\tundici.install?.();\n\t\tinstalledGlobalFetch = globalThis.fetch;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"http-dispatcher.js","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"node:events\";\nimport * as undici from \"undici\";\n\nexport const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300_000;\n// Node's 250ms default can terminate valid connection attempts on high-latency routes.\nconst DEFAULT_AUTO_SELECT_FAMILY_ATTEMPT_TIMEOUT_MS = 2_000;\n\nexport const HTTP_IDLE_TIMEOUT_CHOICES = [\n\t{ label: \"30 sec\", timeoutMs: 30_000 },\n\t{ label: \"1 min\", timeoutMs: 60_000 },\n\t{ label: \"2 min\", timeoutMs: 120_000 },\n\t{ label: \"5 min\", timeoutMs: 300_000 },\n\t{ label: \"disabled\", timeoutMs: 0 },\n] as const;\n\nconst originalGlobalFetch = globalThis.fetch;\nlet installedGlobalFetch: typeof globalThis.fetch | undefined;\nlet multiSessionDispatcherTimeoutMs: number | undefined;\n\n/** Facts the global-install decision reads; injected so the decision is testable per runtime. */\nexport interface UndiciGlobalsInstallInput {\n\t/** `process.versions`; a `bun` entry means this process IS Bun. */\n\treadonly versions: Readonly<Record<string, string | undefined>>;\n\t/** `globalThis.fetch` at the time of the call. */\n\treadonly currentFetch: unknown;\n\t/** `globalThis.fetch` captured when this module loaded. */\n\treadonly originalFetch: unknown;\n\t/** `globalThis.fetch` left behind by the previous install, if any. */\n\treadonly installedFetch: unknown;\n}\n\n/**\n * Whether `configureHttpDispatcher` may replace the global `fetch` (and the\n * WebSocket/Headers/Request/Response constructors) with the bundled Undici\n * implementation.\n *\n * Bun keeps its native fetch: the distributed CLI inlines npm undici, and its\n * fetch running on Bun 1.3.x answers with the response headers but never\n * delivers a streamed body, so every SSE model response stalls after the\n * headers (#1890). Bun's own fetch honors HTTP_PROXY / HTTPS_PROXY / NO_PROXY,\n * which `applyHttpProxySettings` sets, and stream stalls stay bounded by the\n * agent-level idle and stream-start guards derived from the same\n * `httpIdleTimeoutMs` setting.\n *\n * Node installs the globals so fetch and the dispatcher share one undici\n * implementation (see the call site); a caller that deliberately replaced\n * `fetch` after module load keeps its override.\n */\nexport function shouldInstallUndiciGlobals(input: UndiciGlobalsInstallInput): boolean {\n\tif (input.versions.bun !== undefined) return false;\n\treturn input.installedFetch === undefined\n\t\t? input.currentFetch === input.originalFetch\n\t\t: input.currentFetch === input.installedFetch;\n}\n\nfunction isMultiSessionRpcProcess(): boolean {\n\treturn process.argv.includes(\"--multi-session\");\n}\n\nexport function parseHttpIdleTimeoutMs(value: unknown): number | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst trimmed = value.trim();\n\t\tif (trimmed.toLowerCase() === \"disabled\") {\n\t\t\treturn 0;\n\t\t}\n\t\tif (trimmed.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn parseHttpIdleTimeoutMs(Number(trimmed));\n\t}\n\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n\t\treturn undefined;\n\t}\n\treturn Math.floor(value);\n}\n\nexport function formatHttpIdleTimeoutMs(timeoutMs: number): string {\n\tconst choice = HTTP_IDLE_TIMEOUT_CHOICES.find((item) => item.timeoutMs === timeoutMs);\n\tif (choice) {\n\t\treturn choice.label;\n\t}\n\treturn `${timeoutMs / 1000} sec`;\n}\n\nexport function applyHttpProxySettings(httpProxy: string | undefined): void {\n\tconst proxy = httpProxy?.trim();\n\tif (!proxy) return;\n\tif (isMultiSessionRpcProcess()) {\n\t\tconst existing = process.env.HTTP_PROXY ?? process.env.HTTPS_PROXY;\n\t\tif (existing !== undefined && existing !== proxy) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Multi-session RPC shares one process-global HTTP proxy; proxy settings must be fixed at process startup.\",\n\t\t\t);\n\t\t}\n\t}\n\tprocess.env.HTTP_PROXY ??= proxy;\n\tprocess.env.HTTPS_PROXY ??= proxy;\n}\n\nconst ignoreUndiciDispatcherError = (_error: unknown): void => {};\n\n// Undici can emit an internal Client \"error\" while terminating a mid-stream\n// fetch body. The body stream still rejects through reader.read(); this listener\n// only prevents EventEmitter's unhandled \"error\" special case from crashing pi.\nfunction withUndiciErrorListener<T extends undici.Dispatcher>(dispatcher: T): T {\n\tif (dispatcher instanceof EventEmitter) {\n\t\tEventEmitter.prototype.on.call(dispatcher, \"error\", ignoreUndiciDispatcherError);\n\t}\n\treturn dispatcher;\n}\n\nfunction createUndiciClient(origin: string | URL, options: object): undici.Dispatcher {\n\treturn withUndiciErrorListener(new undici.Client(origin, options as undici.Client.Options));\n}\n\nfunction createUndiciOriginDispatcher(origin: string | URL, options: object): undici.Dispatcher {\n\tconst dispatcherOptions = options as undici.Pool.Options;\n\tif (dispatcherOptions.connections === 1) {\n\t\treturn createUndiciClient(origin, dispatcherOptions);\n\t}\n\treturn withUndiciErrorListener(\n\t\tnew undici.Pool(origin, {\n\t\t\t...dispatcherOptions,\n\t\t\tfactory: createUndiciClient,\n\t\t}),\n\t);\n}\n\nexport function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TIMEOUT_MS): void {\n\tconst normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);\n\tif (normalizedTimeoutMs === undefined) {\n\t\tthrow new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);\n\t}\n\tif (isMultiSessionRpcProcess()) {\n\t\tif (multiSessionDispatcherTimeoutMs !== undefined && multiSessionDispatcherTimeoutMs !== normalizedTimeoutMs) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Multi-session RPC shares one process-global Undici dispatcher; HTTP idle timeout must be fixed at process startup.\",\n\t\t\t);\n\t\t}\n\t\tmultiSessionDispatcherTimeoutMs = normalizedTimeoutMs;\n\t}\n\tconst dispatcher = withUndiciErrorListener(\n\t\tnew undici.EnvHttpProxyAgent({\n\t\t\tallowH2: false,\n\t\t\t// Keep HTTP origins on CONNECT tunnels as they were before Undici 8.7.\n\t\t\tproxyTunnel: true,\n\t\t\tbodyTimeout: normalizedTimeoutMs,\n\t\t\tconnect: {\n\t\t\t\tautoSelectFamilyAttemptTimeout: DEFAULT_AUTO_SELECT_FAMILY_ATTEMPT_TIMEOUT_MS,\n\t\t\t},\n\t\t\theadersTimeout: normalizedTimeoutMs,\n\t\t\tclientFactory: createUndiciClient,\n\t\t\tfactory: createUndiciOriginDispatcher,\n\t\t}),\n\t);\n\tundici.setGlobalDispatcher(dispatcher);\n\t// Keep fetch and the dispatcher on the same undici implementation. Node 26.0's\n\t// bundled fetch can otherwise consume compressed responses through npm undici's\n\t// dispatcher without decompressing them, causing response.json() failures.\n\t// If a caller replaced fetch after module load, preserve that deliberate override.\n\tconst shouldInstallGlobals = shouldInstallUndiciGlobals({\n\t\tversions: process.versions,\n\t\tcurrentFetch: globalThis.fetch,\n\t\toriginalFetch: originalGlobalFetch,\n\t\tinstalledFetch: installedGlobalFetch,\n\t});\n\tif (shouldInstallGlobals) {\n\t\tundici.install?.();\n\t\tinstalledGlobalFetch = globalThis.fetch;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-render-descriptors.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-render-descriptors.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"assistant-render-descriptors.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-render-descriptors.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,gBAAgB,EAIrB,MAAM,uBAAuB,CAAC;AAK/B,KAAK,sBAAsB,GAAG,SAAS,GAAG,aAAa,CAAC;AACxD,KAAK,kBAAkB,GAAG,gBAAgB,GAAG,yBAAyB,GAAG,sBAAsB,GAAG,YAAY,CAAC;AAC/G,KAAK,6BAA6B,GAAG,QAAQ,GAAG,sBAAsB,GAAG,kBAAkB,CAAC;AAE5F,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+FAA+F;IAC/F,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,KAAK,gCAAgC,GAAG;IACvC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,mFAAmF;IACnF,QAAQ,CAAC,2BAA2B,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAC/B,CAAC;AAuBF,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,gCAAgC,GACvC,SAAS,yBAAyB,EAAE,CA2HtC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { describeProviderFailureForUser, SERVER_FALLBACK_ABORTED_DIAGNOSTIC, stripTurnRetrySuppressionPrefix, } from "@earendil-works/pi-ai";
|
|
2
2
|
import { formatDuration } from "../../../utils/duration.js";
|
|
3
3
|
import { formatProviderNativeBody, formatProviderNativeSummary } from "../../provider-native-rendering.js";
|
|
4
4
|
import { theme } from "../theme/theme.js";
|
|
@@ -116,7 +116,7 @@ export function createAssistantRenderDescriptors(message, options) {
|
|
|
116
116
|
if (options.providerErrorOwned)
|
|
117
117
|
break;
|
|
118
118
|
const abortMessage = message.errorMessage && message.errorMessage !== "Request was aborted"
|
|
119
|
-
? message.errorMessage
|
|
119
|
+
? stripTurnRetrySuppressionPrefix(message.errorMessage)
|
|
120
120
|
: "Operation aborted";
|
|
121
121
|
addError(abortMessage);
|
|
122
122
|
break;
|
|
@@ -128,11 +128,12 @@ export function createAssistantRenderDescriptors(message, options) {
|
|
|
128
128
|
break;
|
|
129
129
|
if (message.diagnostics?.some((entry) => entry.type === SERVER_FALLBACK_ABORTED_DIAGNOSTIC))
|
|
130
130
|
break;
|
|
131
|
-
// A provider-stream stall carries the
|
|
132
|
-
// engine can
|
|
133
|
-
// without the recovery advice a retry still in
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
// A provider-stream stall or transport drop carries the classifier's own
|
|
132
|
+
// wording so the retry engine can read it; the transcript gets the
|
|
133
|
+
// plain-language version, without the recovery advice a retry still in
|
|
134
|
+
// flight would contradict, and never the internal replay marker.
|
|
135
|
+
const described = describeProviderFailureForUser(message.errorMessage);
|
|
136
|
+
addError(described ?? `Error: ${stripTurnRetrySuppressionPrefix(message.errorMessage ?? "") || "Unknown error"}`);
|
|
136
137
|
break;
|
|
137
138
|
}
|
|
138
139
|
case "pending":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-render-descriptors.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-render-descriptors.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AssistantMessage,\n\tdescribeProviderStallForUser,\n\tSERVER_FALLBACK_ABORTED_DIAGNOSTIC,\n} from \"@earendil-works/pi-ai\";\nimport { formatDuration } from \"../../../utils/duration.ts\";\nimport { formatProviderNativeBody, formatProviderNativeSummary } from \"../../provider-native-rendering.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\ntype MarkdownDescriptorKind = \"text-md\" | \"thinking-md\";\ntype TextDescriptorKind = \"thinking-label\" | \"provider-native-summary\" | \"provider-native-body\" | \"error-text\";\ntype AssistantRenderDescriptorKind = \"spacer\" | MarkdownDescriptorKind | TextDescriptorKind;\n\nexport type AssistantRenderDescriptor = {\n\treadonly kind: AssistantRenderDescriptorKind;\n\treadonly text: string;\n\t/** Index of the thinking run this label/body belongs to; set only for thinking descriptors. */\n\treadonly thinkingRun?: number;\n};\n\ntype AssistantRenderDescriptorOptions = {\n\treadonly expanded: boolean;\n\treadonly providerErrorOwned?: boolean;\n\treadonly hiddenThinkingLabel: string;\n\treadonly hideThinkingBlock: boolean;\n\t/** Per-run click overrides of `hideThinkingBlock`, keyed by thinking run index. */\n\treadonly thinkingVisibilityOverrides?: ReadonlyMap<number, boolean>;\n\treadonly hasToolCalls: boolean;\n};\n\nconst SPACER_DESCRIPTOR = { kind: \"spacer\", text: \"\" } as const satisfies AssistantRenderDescriptor;\n\nfunction assertNever(value: never): never {\n\tthrow new TypeError(`Unexpected assistant render variant: ${String(value)}`);\n}\n\nfunction isVisibleContent(content: AssistantMessage[\"content\"][number], providerNativeVisible: boolean): boolean {\n\tswitch (content.type) {\n\t\tcase \"text\":\n\t\t\treturn Boolean(content.text.trim());\n\t\tcase \"thinking\":\n\t\t\treturn Boolean(content.thinking.trim());\n\t\tcase \"providerNative\":\n\t\t\treturn providerNativeVisible;\n\t\tcase \"toolCall\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn assertNever(content);\n\t}\n}\n\nexport function createAssistantRenderDescriptors(\n\tmessage: AssistantMessage,\n\toptions: AssistantRenderDescriptorOptions,\n): readonly AssistantRenderDescriptor[] {\n\tconst descriptors: AssistantRenderDescriptor[] = [];\n\tif (message.content.some((content) => isVisibleContent(content, true))) descriptors.push(SPACER_DESCRIPTOR);\n\tlet thinkingRunIndex = 0;\n\tfor (let i = 0; i < message.content.length; i++) {\n\t\tconst content = message.content[i];\n\t\tswitch (content.type) {\n\t\t\tcase \"text\": {\n\t\t\t\tconst text = content.text.trim();\n\t\t\t\tif (text) descriptors.push({ kind: \"text-md\", text });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"thinking\": {\n\t\t\t\tconst thinkingBlocks: string[] = [];\n\t\t\t\tlet hasTiming = false;\n\t\t\t\tlet isDone = true;\n\t\t\t\tlet minStart = Number.POSITIVE_INFINITY;\n\t\t\t\tlet maxEnd = Number.NEGATIVE_INFINITY;\n\t\t\t\tfor (; i < message.content.length; i++) {\n\t\t\t\t\tconst thinkingContent = message.content[i];\n\t\t\t\t\tif (thinkingContent.type !== \"thinking\") break;\n\t\t\t\t\tconst startedAt = thinkingContent.startedAt;\n\t\t\t\t\tif (startedAt !== undefined) {\n\t\t\t\t\t\thasTiming = true;\n\t\t\t\t\t\tminStart = Math.min(minStart, startedAt);\n\t\t\t\t\t\tconst endedAt = thinkingContent.endedAt;\n\t\t\t\t\t\tif (endedAt === undefined) {\n\t\t\t\t\t\t\tisDone = false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmaxEnd = Math.max(maxEnd, endedAt);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst thinking = thinkingContent.thinking.trim();\n\t\t\t\t\tif (thinking) thinkingBlocks.push(thinking);\n\t\t\t\t}\n\t\t\t\ti--;\n\t\t\t\tif (thinkingBlocks.length === 0) break;\n\t\t\t\tconst thinkingRun = thinkingRunIndex++;\n\t\t\t\tconst hidden = options.thinkingVisibilityOverrides?.get(thinkingRun) ?? options.hideThinkingBlock;\n\t\t\t\tif (!hasTiming) {\n\t\t\t\t\tconst text = hidden\n\t\t\t\t\t\t? theme.italic(theme.fg(\"thinkingText\", options.hiddenThinkingLabel))\n\t\t\t\t\t\t: thinkingBlocks.join(\"\\n\\n\");\n\t\t\t\t\tdescriptors.push({ kind: hidden ? \"thinking-label\" : \"thinking-md\", text, thinkingRun });\n\t\t\t\t} else {\n\t\t\t\t\tconst label = isDone\n\t\t\t\t\t\t? theme.italic(theme.fg(\"thinkingText\", `Thought: ${formatDuration(Math.max(0, maxEnd - minStart))}`))\n\t\t\t\t\t\t: theme.italic(theme.fg(\"thinkingText\", options.hiddenThinkingLabel));\n\t\t\t\t\tif (hidden) {\n\t\t\t\t\t\tdescriptors.push({ kind: \"thinking-label\", text: label, thinkingRun });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdescriptors.push(\n\t\t\t\t\t\t\t{ kind: \"thinking-label\", text: label, thinkingRun },\n\t\t\t\t\t\t\t{ kind: \"thinking-md\", text: thinkingBlocks.join(\"\\n\\n\"), thinkingRun },\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (message.content.slice(i + 1).some((following) => isVisibleContent(following, false)))\n\t\t\t\t\tdescriptors.push(SPACER_DESCRIPTOR);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"providerNative\":\n\t\t\t\tdescriptors.push(\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: \"provider-native-summary\",\n\t\t\t\t\t\ttext: theme.fg(\"muted\", formatProviderNativeSummary(message, content, options.expanded)),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: \"provider-native-body\",\n\t\t\t\t\t\ttext: theme.fg(\"dim\", formatProviderNativeBody(content, options.expanded)),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tif (message.content.slice(i + 1).some((following) => isVisibleContent(following, true)))\n\t\t\t\t\tdescriptors.push(SPACER_DESCRIPTOR);\n\t\t\t\tbreak;\n\t\t\tcase \"toolCall\":\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tassertNever(content);\n\t\t}\n\t}\n\tconst addError = (text: string): void => {\n\t\tdescriptors.push(SPACER_DESCRIPTOR, { kind: \"error-text\", text: theme.fg(\"error\", text) });\n\t};\n\tswitch (message.stopReason) {\n\t\tcase \"length\":\n\t\t\taddError(\n\t\t\t\t\"Error: Model stopped because it reached the maximum output token limit. The response may be incomplete.\",\n\t\t\t);\n\t\t\tbreak;\n\t\tcase \"aborted\": {\n\t\t\tif (options.hasToolCalls) break;\n\t\t\tif (options.providerErrorOwned) break;\n\t\t\tconst abortMessage =\n\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t: \"Operation aborted\";\n\t\t\taddError(abortMessage);\n\t\t\tbreak;\n\t\t}\n\t\tcase \"error\": {\n\t\t\tif (options.hasToolCalls) break;\n\t\t\tif (options.providerErrorOwned) break;\n\t\t\tif (message.diagnostics?.some((entry) => entry.type === SERVER_FALLBACK_ABORTED_DIAGNOSTIC)) break;\n\t\t\t// A provider-stream stall carries the watchdog's own wording so the retry\n\t\t\t// engine can classify it; the transcript gets the plain-language version,\n\t\t\t// without the recovery advice a retry still in flight would contradict.\n\t\t\tconst stall = describeProviderStallForUser(message.errorMessage);\n\t\t\taddError(stall ?? `Error: ${message.errorMessage || \"Unknown error\"}`);\n\t\t\tbreak;\n\t\t}\n\t\tcase \"pending\":\n\t\tcase \"stop\":\n\t\tcase \"toolUse\":\n\t\tcase \"deferred\":\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tassertNever(message.stopReason);\n\t}\n\treturn descriptors;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"assistant-render-descriptors.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-render-descriptors.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,8BAA8B,EAC9B,kCAAkC,EAClC,+BAA+B,GAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AAC3G,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAuB1C,MAAM,iBAAiB,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAA+C,CAAC;AAEpG,SAAS,WAAW,CAAC,KAAY;IAChC,MAAM,IAAI,SAAS,CAAC,wCAAwC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,gBAAgB,CAAC,OAA4C,EAAE,qBAA8B;IACrG,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,MAAM;YACV,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACrC,KAAK,UAAU;YACd,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QACzC,KAAK,gBAAgB;YACpB,OAAO,qBAAqB,CAAC;QAC9B,KAAK,UAAU;YACd,OAAO,KAAK,CAAC;QACd;YACC,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC/C,OAAyB,EACzB,OAAyC;IAEzC,MAAM,WAAW,GAAgC,EAAE,CAAC;IACpD,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAAE,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC5G,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACnC,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACtB,KAAK,MAAM,EAAE,CAAC;gBACb,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACjC,IAAI,IAAI;oBAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtD,MAAM;YACP,CAAC;YACD,KAAK,UAAU,EAAE,CAAC;gBACjB,MAAM,cAAc,GAAa,EAAE,CAAC;gBACpC,IAAI,SAAS,GAAG,KAAK,CAAC;gBACtB,IAAI,MAAM,GAAG,IAAI,CAAC;gBAClB,IAAI,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC;gBACxC,IAAI,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC;gBACtC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACxC,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;oBAC3C,IAAI,eAAe,CAAC,IAAI,KAAK,UAAU;wBAAE,MAAM;oBAC/C,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC;oBAC5C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;wBAC7B,SAAS,GAAG,IAAI,CAAC;wBACjB,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;wBACzC,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC;wBACxC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;4BAC3B,MAAM,GAAG,KAAK,CAAC;wBAChB,CAAC;6BAAM,CAAC;4BACP,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;wBACpC,CAAC;oBACF,CAAC;oBACD,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;oBACjD,IAAI,QAAQ;wBAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC7C,CAAC;gBACD,CAAC,EAAE,CAAC;gBACJ,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;oBAAE,MAAM;gBACvC,MAAM,WAAW,GAAG,gBAAgB,EAAE,CAAC;gBACvC,MAAM,MAAM,GAAG,OAAO,CAAC,2BAA2B,EAAE,GAAG,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC;gBAClG,IAAI,CAAC,SAAS,EAAE,CAAC;oBAChB,MAAM,IAAI,GAAG,MAAM;wBAClB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;wBACrE,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAC/B,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;gBAC1F,CAAC;qBAAM,CAAC;oBACP,MAAM,KAAK,GAAG,MAAM;wBACnB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,cAAc,EAAE,YAAY,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;wBACtG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC;oBACvE,IAAI,MAAM,EAAE,CAAC;wBACZ,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;oBACxE,CAAC;yBAAM,CAAC;wBACP,WAAW,CAAC,IAAI,CACf,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EACpD,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,CACvE,CAAC;oBACH,CAAC;gBACF,CAAC;gBACD,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;oBACvF,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBACrC,MAAM;YACP,CAAC;YACD,KAAK,gBAAgB;gBACpB,WAAW,CAAC,IAAI,CACf;oBACC,IAAI,EAAE,yBAAyB;oBAC/B,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;iBACxF,EACD;oBACC,IAAI,EAAE,sBAAsB;oBAC5B,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;iBAC1E,CACD,CAAC;gBACF,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;oBACtF,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBACrC,MAAM;YACP,KAAK,UAAU;gBACd,MAAM;YACP;gBACC,WAAW,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACF,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAQ,EAAE;QACvC,WAAW,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC,CAAC;IACF,QAAQ,OAAO,CAAC,UAAU,EAAE,CAAC;QAC5B,KAAK,QAAQ;YACZ,QAAQ,CACP,yGAAyG,CACzG,CAAC;YACF,MAAM;QACP,KAAK,SAAS,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,YAAY;gBAAE,MAAM;YAChC,IAAI,OAAO,CAAC,kBAAkB;gBAAE,MAAM;YACtC,MAAM,YAAY,GACjB,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,YAAY,KAAK,qBAAqB;gBACrE,CAAC,CAAC,+BAA+B,CAAC,OAAO,CAAC,YAAY,CAAC;gBACvD,CAAC,CAAC,mBAAmB,CAAC;YACxB,QAAQ,CAAC,YAAY,CAAC,CAAC;YACvB,MAAM;QACP,CAAC;QACD,KAAK,OAAO,EAAE,CAAC;YACd,IAAI,OAAO,CAAC,YAAY;gBAAE,MAAM;YAChC,IAAI,OAAO,CAAC,kBAAkB;gBAAE,MAAM;YACtC,IAAI,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,kCAAkC,CAAC;gBAAE,MAAM;YACnG,yEAAyE;YACzE,mEAAmE;YACnE,uEAAuE;YACvE,iEAAiE;YACjE,MAAM,SAAS,GAAG,8BAA8B,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YACvE,QAAQ,CACP,SAAS,IAAI,UAAU,+BAA+B,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,IAAI,eAAe,EAAE,CACvG,CAAC;YACF,MAAM;QACP,CAAC;QACD,KAAK,SAAS,CAAC;QACf,KAAK,MAAM,CAAC;QACZ,KAAK,SAAS,CAAC;QACf,KAAK,UAAU;YACd,MAAM;QACP;YACC,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,WAAW,CAAC;AACpB,CAAC","sourcesContent":["import {\n\ttype AssistantMessage,\n\tdescribeProviderFailureForUser,\n\tSERVER_FALLBACK_ABORTED_DIAGNOSTIC,\n\tstripTurnRetrySuppressionPrefix,\n} from \"@earendil-works/pi-ai\";\nimport { formatDuration } from \"../../../utils/duration.ts\";\nimport { formatProviderNativeBody, formatProviderNativeSummary } from \"../../provider-native-rendering.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\ntype MarkdownDescriptorKind = \"text-md\" | \"thinking-md\";\ntype TextDescriptorKind = \"thinking-label\" | \"provider-native-summary\" | \"provider-native-body\" | \"error-text\";\ntype AssistantRenderDescriptorKind = \"spacer\" | MarkdownDescriptorKind | TextDescriptorKind;\n\nexport type AssistantRenderDescriptor = {\n\treadonly kind: AssistantRenderDescriptorKind;\n\treadonly text: string;\n\t/** Index of the thinking run this label/body belongs to; set only for thinking descriptors. */\n\treadonly thinkingRun?: number;\n};\n\ntype AssistantRenderDescriptorOptions = {\n\treadonly expanded: boolean;\n\treadonly providerErrorOwned?: boolean;\n\treadonly hiddenThinkingLabel: string;\n\treadonly hideThinkingBlock: boolean;\n\t/** Per-run click overrides of `hideThinkingBlock`, keyed by thinking run index. */\n\treadonly thinkingVisibilityOverrides?: ReadonlyMap<number, boolean>;\n\treadonly hasToolCalls: boolean;\n};\n\nconst SPACER_DESCRIPTOR = { kind: \"spacer\", text: \"\" } as const satisfies AssistantRenderDescriptor;\n\nfunction assertNever(value: never): never {\n\tthrow new TypeError(`Unexpected assistant render variant: ${String(value)}`);\n}\n\nfunction isVisibleContent(content: AssistantMessage[\"content\"][number], providerNativeVisible: boolean): boolean {\n\tswitch (content.type) {\n\t\tcase \"text\":\n\t\t\treturn Boolean(content.text.trim());\n\t\tcase \"thinking\":\n\t\t\treturn Boolean(content.thinking.trim());\n\t\tcase \"providerNative\":\n\t\t\treturn providerNativeVisible;\n\t\tcase \"toolCall\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn assertNever(content);\n\t}\n}\n\nexport function createAssistantRenderDescriptors(\n\tmessage: AssistantMessage,\n\toptions: AssistantRenderDescriptorOptions,\n): readonly AssistantRenderDescriptor[] {\n\tconst descriptors: AssistantRenderDescriptor[] = [];\n\tif (message.content.some((content) => isVisibleContent(content, true))) descriptors.push(SPACER_DESCRIPTOR);\n\tlet thinkingRunIndex = 0;\n\tfor (let i = 0; i < message.content.length; i++) {\n\t\tconst content = message.content[i];\n\t\tswitch (content.type) {\n\t\t\tcase \"text\": {\n\t\t\t\tconst text = content.text.trim();\n\t\t\t\tif (text) descriptors.push({ kind: \"text-md\", text });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"thinking\": {\n\t\t\t\tconst thinkingBlocks: string[] = [];\n\t\t\t\tlet hasTiming = false;\n\t\t\t\tlet isDone = true;\n\t\t\t\tlet minStart = Number.POSITIVE_INFINITY;\n\t\t\t\tlet maxEnd = Number.NEGATIVE_INFINITY;\n\t\t\t\tfor (; i < message.content.length; i++) {\n\t\t\t\t\tconst thinkingContent = message.content[i];\n\t\t\t\t\tif (thinkingContent.type !== \"thinking\") break;\n\t\t\t\t\tconst startedAt = thinkingContent.startedAt;\n\t\t\t\t\tif (startedAt !== undefined) {\n\t\t\t\t\t\thasTiming = true;\n\t\t\t\t\t\tminStart = Math.min(minStart, startedAt);\n\t\t\t\t\t\tconst endedAt = thinkingContent.endedAt;\n\t\t\t\t\t\tif (endedAt === undefined) {\n\t\t\t\t\t\t\tisDone = false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmaxEnd = Math.max(maxEnd, endedAt);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst thinking = thinkingContent.thinking.trim();\n\t\t\t\t\tif (thinking) thinkingBlocks.push(thinking);\n\t\t\t\t}\n\t\t\t\ti--;\n\t\t\t\tif (thinkingBlocks.length === 0) break;\n\t\t\t\tconst thinkingRun = thinkingRunIndex++;\n\t\t\t\tconst hidden = options.thinkingVisibilityOverrides?.get(thinkingRun) ?? options.hideThinkingBlock;\n\t\t\t\tif (!hasTiming) {\n\t\t\t\t\tconst text = hidden\n\t\t\t\t\t\t? theme.italic(theme.fg(\"thinkingText\", options.hiddenThinkingLabel))\n\t\t\t\t\t\t: thinkingBlocks.join(\"\\n\\n\");\n\t\t\t\t\tdescriptors.push({ kind: hidden ? \"thinking-label\" : \"thinking-md\", text, thinkingRun });\n\t\t\t\t} else {\n\t\t\t\t\tconst label = isDone\n\t\t\t\t\t\t? theme.italic(theme.fg(\"thinkingText\", `Thought: ${formatDuration(Math.max(0, maxEnd - minStart))}`))\n\t\t\t\t\t\t: theme.italic(theme.fg(\"thinkingText\", options.hiddenThinkingLabel));\n\t\t\t\t\tif (hidden) {\n\t\t\t\t\t\tdescriptors.push({ kind: \"thinking-label\", text: label, thinkingRun });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdescriptors.push(\n\t\t\t\t\t\t\t{ kind: \"thinking-label\", text: label, thinkingRun },\n\t\t\t\t\t\t\t{ kind: \"thinking-md\", text: thinkingBlocks.join(\"\\n\\n\"), thinkingRun },\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (message.content.slice(i + 1).some((following) => isVisibleContent(following, false)))\n\t\t\t\t\tdescriptors.push(SPACER_DESCRIPTOR);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"providerNative\":\n\t\t\t\tdescriptors.push(\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: \"provider-native-summary\",\n\t\t\t\t\t\ttext: theme.fg(\"muted\", formatProviderNativeSummary(message, content, options.expanded)),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: \"provider-native-body\",\n\t\t\t\t\t\ttext: theme.fg(\"dim\", formatProviderNativeBody(content, options.expanded)),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tif (message.content.slice(i + 1).some((following) => isVisibleContent(following, true)))\n\t\t\t\t\tdescriptors.push(SPACER_DESCRIPTOR);\n\t\t\t\tbreak;\n\t\t\tcase \"toolCall\":\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tassertNever(content);\n\t\t}\n\t}\n\tconst addError = (text: string): void => {\n\t\tdescriptors.push(SPACER_DESCRIPTOR, { kind: \"error-text\", text: theme.fg(\"error\", text) });\n\t};\n\tswitch (message.stopReason) {\n\t\tcase \"length\":\n\t\t\taddError(\n\t\t\t\t\"Error: Model stopped because it reached the maximum output token limit. The response may be incomplete.\",\n\t\t\t);\n\t\t\tbreak;\n\t\tcase \"aborted\": {\n\t\t\tif (options.hasToolCalls) break;\n\t\t\tif (options.providerErrorOwned) break;\n\t\t\tconst abortMessage =\n\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t? stripTurnRetrySuppressionPrefix(message.errorMessage)\n\t\t\t\t\t: \"Operation aborted\";\n\t\t\taddError(abortMessage);\n\t\t\tbreak;\n\t\t}\n\t\tcase \"error\": {\n\t\t\tif (options.hasToolCalls) break;\n\t\t\tif (options.providerErrorOwned) break;\n\t\t\tif (message.diagnostics?.some((entry) => entry.type === SERVER_FALLBACK_ABORTED_DIAGNOSTIC)) break;\n\t\t\t// A provider-stream stall or transport drop carries the classifier's own\n\t\t\t// wording so the retry engine can read it; the transcript gets the\n\t\t\t// plain-language version, without the recovery advice a retry still in\n\t\t\t// flight would contradict, and never the internal replay marker.\n\t\t\tconst described = describeProviderFailureForUser(message.errorMessage);\n\t\t\taddError(\n\t\t\t\tdescribed ?? `Error: ${stripTurnRetrySuppressionPrefix(message.errorMessage ?? \"\") || \"Unknown error\"}`,\n\t\t\t);\n\t\t\tbreak;\n\t\t}\n\t\tcase \"pending\":\n\t\tcase \"stop\":\n\t\tcase \"toolUse\":\n\t\tcase \"deferred\":\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tassertNever(message.stopReason);\n\t}\n\treturn descriptors;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAEN,KAAK,YAAY,EAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAM5E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2K/G"}
|
package/dist/modes/print-mode.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* - `pi -p "prompt"` - text output
|
|
6
6
|
* - `senpi --mode json "prompt"` - JSON event stream
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { describeProviderFailureForUser, stripTurnRetrySuppressionPrefix, } from "@earendil-works/pi-ai";
|
|
9
9
|
import { flushRawStdout, waitForRawStdoutBackpressure, writeRawStdout } from "../core/output-guard.js";
|
|
10
10
|
import { killTrackedDetachedChildren } from "../utils/shell.js";
|
|
11
11
|
import { toJsonEvent } from "./json-event.js";
|
|
@@ -141,10 +141,12 @@ export async function runPrintMode(runtimeHost, options) {
|
|
|
141
141
|
if (lastMessage?.role === "assistant") {
|
|
142
142
|
const assistantMsg = lastMessage;
|
|
143
143
|
if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") {
|
|
144
|
-
// A provider-stream stall
|
|
145
|
-
// the
|
|
146
|
-
const
|
|
147
|
-
console.error(
|
|
144
|
+
// A provider-stream stall or transport drop keeps the classifier wording
|
|
145
|
+
// on the message; stderr gets the plain-language version instead.
|
|
146
|
+
const described = describeProviderFailureForUser(assistantMsg.errorMessage);
|
|
147
|
+
console.error(described ??
|
|
148
|
+
(stripTurnRetrySuppressionPrefix(assistantMsg.errorMessage ?? "") ||
|
|
149
|
+
`Request ${assistantMsg.stopReason}`));
|
|
148
150
|
exitCode = 1;
|
|
149
151
|
}
|
|
150
152
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `senpi --mode json \"prompt\"` - JSON event stream\n */\n\nimport { describeProviderStallForUser, type ImageContent } from \"@earendil-works/pi-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.ts\";\nimport { flushRawStdout, waitForRawStdoutBackpressure, writeRawStdout } from \"../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.ts\";\nimport { toJsonEvent } from \"./json-event.ts\";\nimport { formatProviderNativeBody, formatProviderNativeSummary } from \"./provider-native-rendering.ts\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unsubscribeBackpressure: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tmode: mode === \"json\" ? \"json\" : \"print\",\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t\texpectedLeafId: navigateOptions?.expectedLeafId,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\teditAssistantMessage: async (entryId, text, editOptions) => {\n\t\t\t\t\tconst result = await session.editAssistantMessage(entryId, text, {\n\t\t\t\t\t\tsummarize: editOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: editOptions?.customInstructions,\n\t\t\t\t\t\texpectedLeafId: editOptions?.expectedLeafId,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled, unchanged: result.unchanged, entryId: result.entryId };\n\t\t\t\t},\n\t\t\t\teditUserMessage: async (entryId, text, editOptions) => {\n\t\t\t\t\tconst result = await session.editUserMessage(entryId, text, {\n\t\t\t\t\t\tsummarize: editOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: editOptions?.customInstructions,\n\t\t\t\t\t\texpectedLeafId: editOptions?.expectedLeafId,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled, unchanged: result.unchanged, entryId: result.entryId };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (event.type === \"retry_fallback_applied\") {\n\t\t\t\tconsole.error(`Model fallback: ${event.from} -> ${event.to} (${event.reason})`);\n\t\t\t} else if (event.type === \"retry_fallback_exhausted\") {\n\t\t\t\tconsole.error(`Model fallback exhausted: ${event.chainKey} (${event.lastError})`);\n\t\t\t} else if (event.type === \"retry_fallback_reverted\") {\n\t\t\t\tconsole.error(`Model fallback reverted: ${event.from} -> ${event.to}`);\n\t\t\t}\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(toJsonEvent(event))}\\n`);\n\t\t\t}\n\t\t});\n\t\tunsubscribeBackpressure =\n\t\t\tmode === \"json\"\n\t\t\t\t? session.agent.subscribe(async () => {\n\t\t\t\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages, sessionTitlePrompt: false });\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message, { sessionTitlePrompt: false });\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst state = session.state;\n\t\t\tconst lastMessage = state.messages.findLast((message) => message.role === \"assistant\");\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\tconst assistantMsg = lastMessage;\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\t// A provider-stream stall keeps the watchdog wording on the message for\n\t\t\t\t\t// the retry classifier; stdout gets the plain-language version instead.\n\t\t\t\t\tconst stall = describeProviderStallForUser(assistantMsg.errorMessage);\n\t\t\t\t\tconsole.error(stall ?? (assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`));\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t} else if (content.type === \"providerNative\") {\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeSummary(assistantMsg, content, false)}\\n`);\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeBody(content, false)}\\n`);\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\n\t\tawait session.waitForSettledSessionWork();\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `senpi --mode json \"prompt\"` - JSON event stream\n */\n\nimport {\n\tdescribeProviderFailureForUser,\n\ttype ImageContent,\n\tstripTurnRetrySuppressionPrefix,\n} from \"@earendil-works/pi-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.ts\";\nimport { flushRawStdout, waitForRawStdoutBackpressure, writeRawStdout } from \"../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.ts\";\nimport { toJsonEvent } from \"./json-event.ts\";\nimport { formatProviderNativeBody, formatProviderNativeSummary } from \"./provider-native-rendering.ts\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unsubscribeBackpressure: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tmode: mode === \"json\" ? \"json\" : \"print\",\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t\texpectedLeafId: navigateOptions?.expectedLeafId,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\teditAssistantMessage: async (entryId, text, editOptions) => {\n\t\t\t\t\tconst result = await session.editAssistantMessage(entryId, text, {\n\t\t\t\t\t\tsummarize: editOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: editOptions?.customInstructions,\n\t\t\t\t\t\texpectedLeafId: editOptions?.expectedLeafId,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled, unchanged: result.unchanged, entryId: result.entryId };\n\t\t\t\t},\n\t\t\t\teditUserMessage: async (entryId, text, editOptions) => {\n\t\t\t\t\tconst result = await session.editUserMessage(entryId, text, {\n\t\t\t\t\t\tsummarize: editOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: editOptions?.customInstructions,\n\t\t\t\t\t\texpectedLeafId: editOptions?.expectedLeafId,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled, unchanged: result.unchanged, entryId: result.entryId };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (event.type === \"retry_fallback_applied\") {\n\t\t\t\tconsole.error(`Model fallback: ${event.from} -> ${event.to} (${event.reason})`);\n\t\t\t} else if (event.type === \"retry_fallback_exhausted\") {\n\t\t\t\tconsole.error(`Model fallback exhausted: ${event.chainKey} (${event.lastError})`);\n\t\t\t} else if (event.type === \"retry_fallback_reverted\") {\n\t\t\t\tconsole.error(`Model fallback reverted: ${event.from} -> ${event.to}`);\n\t\t\t}\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(toJsonEvent(event))}\\n`);\n\t\t\t}\n\t\t});\n\t\tunsubscribeBackpressure =\n\t\t\tmode === \"json\"\n\t\t\t\t? session.agent.subscribe(async () => {\n\t\t\t\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages, sessionTitlePrompt: false });\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message, { sessionTitlePrompt: false });\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst state = session.state;\n\t\t\tconst lastMessage = state.messages.findLast((message) => message.role === \"assistant\");\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\tconst assistantMsg = lastMessage;\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\t// A provider-stream stall or transport drop keeps the classifier wording\n\t\t\t\t\t// on the message; stderr gets the plain-language version instead.\n\t\t\t\t\tconst described = describeProviderFailureForUser(assistantMsg.errorMessage);\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\tdescribed ??\n\t\t\t\t\t\t\t(stripTurnRetrySuppressionPrefix(assistantMsg.errorMessage ?? \"\") ||\n\t\t\t\t\t\t\t\t`Request ${assistantMsg.stopReason}`),\n\t\t\t\t\t);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t} else if (content.type === \"providerNative\") {\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeSummary(assistantMsg, content, false)}\\n`);\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeBody(content, false)}\\n`);\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\n\t\tawait session.waitForSettledSessionWork();\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type SessionActivitySnapshot } from "../../core/session-activity.ts";
|
|
2
|
+
/** Handoff preserves turns and requests, but durable wake sources resume when the file is reopened. */
|
|
3
|
+
export declare function isHandoffBusy(snapshot: SessionActivitySnapshot): boolean;
|
|
4
|
+
//# sourceMappingURL=handoff-activity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoff-activity.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/handoff-activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAErG,uGAAuG;AACvG,wBAAgB,aAAa,CAAC,QAAQ,EAAE,uBAAuB,GAAG,OAAO,CAExE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { isSessionBusySnapshot } from "../../core/session-activity.js";
|
|
2
|
+
/** Handoff preserves turns and requests, but durable wake sources resume when the file is reopened. */
|
|
3
|
+
export function isHandoffBusy(snapshot) {
|
|
4
|
+
return isSessionBusySnapshot({ ...snapshot, hasActiveWakeSource: false });
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=handoff-activity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoff-activity.js","sourceRoot":"","sources":["../../../src/modes/rpc/handoff-activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAgC,MAAM,gCAAgC,CAAC;AAErG,uGAAuG;AACvG,MAAM,UAAU,aAAa,CAAC,QAAiC;IAC9D,OAAO,qBAAqB,CAAC,EAAE,GAAG,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["import { isSessionBusySnapshot, type SessionActivitySnapshot } from \"../../core/session-activity.ts\";\n\n/** Handoff preserves turns and requests, but durable wake sources resume when the file is reopened. */\nexport function isHandoffBusy(snapshot: SessionActivitySnapshot): boolean {\n\treturn isSessionBusySnapshot({ ...snapshot, hasActiveWakeSource: false });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-ensure.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-ensure.ts"],"names":[],"mappings":"AA0CA,OAAO,EAA6B,KAAK,aAAa,EAAE,KAAK,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"host-ensure.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-ensure.ts"],"names":[],"mappings":"AA0CA,OAAO,EAA6B,KAAK,aAAa,EAAE,KAAK,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAOnH,OAAO,EACN,qBAAqB,EACrB,mBAAmB,EACnB,KAAK,eAAe,EACpB,oBAAoB,EACpB,KAAK,mBAAmB,GACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EAAE,aAAa,EAAE,wBAAwB,EAAE,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,mBAAmB,CAAC;AAE9D,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAC3C,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,sFAAsF;IACtF,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACvD,iGAAiG;IACjG,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE;QAChB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;SAAE,CAAC;QAChF,6FAA6F;QAC7F,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK;YAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;SAAE,CAAC;QAC9G,oFAAoF;QACpF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QACjD;;;;WAIG;QACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAClD,4EAA4E;QAC5E,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;KAC7E,CAAC;CACF;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CACzB;AAsBD,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAsBjF"}
|
|
@@ -17,6 +17,7 @@ import { DEFAULT_HOST_IDLE_EXIT_MS } from "./host-lifecycle.js";
|
|
|
17
17
|
import { probeProtocolInfo, probeSocketReachable } from "./host-probe.js";
|
|
18
18
|
import { acquireOwnershipSafeLock } from "./ownership-safe-lock.js";
|
|
19
19
|
import { HOST_GENERATION_ENV, HOST_INSTANCE_ID_ENV, hostLaunchProfile } from "./protocol-identity.js";
|
|
20
|
+
import { statSocketIdentity } from "./socket-ownership.js";
|
|
20
21
|
import { createSocketSecret, resolveSocketTransportAddress, socketSecretPath } from "./socket-transport.js";
|
|
21
22
|
export { createHostDaemonPaths, daemonDirectoryName, HostDaemonStateError, } from "./host-daemon-paths.js";
|
|
22
23
|
export { defaultHostLaunch, PINNED_HOST_CLIENT_CAPABILITIES } from "./host-launch.js";
|
|
@@ -91,29 +92,66 @@ async function ensureHostLocked(paths, socket, options) {
|
|
|
91
92
|
}
|
|
92
93
|
const probe = testOptions?.readProcessStartTime ?? readProcessStartTime;
|
|
93
94
|
const pidMatches = registeredHere && registered ? await matchesPidFileOrUnknown(registered.record, probe) : false;
|
|
95
|
+
// The generation this start leaves RUNNING beside the new one, when there is one.
|
|
96
|
+
let stranded;
|
|
94
97
|
if (registered && pidMatches) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
if (!startedByUs) {
|
|
99
|
+
// I1: the socket is silent, but the process behind it is alive. Only the process that WROTE
|
|
100
|
+
// this record may end it - anyone else refuses rather than signalling somebody else's host.
|
|
101
|
+
if (await publicEndpointAccepts(socket))
|
|
102
|
+
throw new HostEnsureRefusedError(socket, "foreign_writer", protocol);
|
|
103
|
+
// A foreign record whose public endpoint accepts NOTHING names a generation nobody can reach:
|
|
104
|
+
// its entry was replaced (so it is already draining, #1893) or removed, or a dead listener
|
|
105
|
+
// left the entry behind. Refusing here locked every client out until that process happened
|
|
106
|
+
// to exit (#1936). Binding a fresh generation there signals nothing, so that is what happens -
|
|
107
|
+
// the stranded one keeps its record.
|
|
108
|
+
stranded = registered;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// Silent is not the same as gone. A host serving many sessions can miss a probe budget
|
|
112
|
+
// while its event loop is busy; its socket still ACCEPTS the connection. Ending it then
|
|
113
|
+
// would destroy every live session to replace a host that was never broken, so a
|
|
114
|
+
// reachable socket is refused instead of signalled - the caller retries or falls back.
|
|
115
|
+
if (await probeSocketReachable(socket, EXISTING_HOST_PROBE_TIMEOUT_MS)) {
|
|
116
|
+
throw new HostEnsureRefusedError(socket, "host_busy", protocol);
|
|
117
|
+
}
|
|
118
|
+
await stopManagedHost(registered.record, testOptions?.stopTimeoutMs ?? DEFAULT_STOP_TIMEOUT_MS, probe);
|
|
105
119
|
}
|
|
106
|
-
await stopManagedHost(registered.record, testOptions?.stopTimeoutMs ?? DEFAULT_STOP_TIMEOUT_MS, probe);
|
|
107
120
|
}
|
|
108
121
|
// A host from before this layout registered itself in the FLAT directory. Its files are another
|
|
109
122
|
// process's state: never read as ours, never signalled, never removed - and while it is alive,
|
|
110
123
|
// this ensure refuses instead of binding a socket it may still be serving.
|
|
111
124
|
if (await legacyHostIsLive(paths, probe))
|
|
112
125
|
throw new HostEnsureRefusedError(socket, "legacy_host", protocol);
|
|
126
|
+
if (stranded !== undefined)
|
|
127
|
+
return startHost(paths, socket, options, stranded.generation + 1);
|
|
113
128
|
if (registeredHere)
|
|
114
129
|
await clearHostRegistration(paths);
|
|
115
130
|
return startHost(paths, socket, options);
|
|
116
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Only the connect matters here, never an answer: the kernel completes it from the listen backlog
|
|
134
|
+
* without the host's event loop, so a live owner under load still accepts within this budget.
|
|
135
|
+
*/
|
|
136
|
+
const FOREIGN_ENDPOINT_PROBE_TIMEOUT_MS = 2_000;
|
|
137
|
+
/**
|
|
138
|
+
* Whether SOMETHING still accepts connections at the public path - the one fact that says a
|
|
139
|
+
* registered process may still own the endpoint. A missing entry and an entry nobody listens
|
|
140
|
+
* behind (connection refused) both answer no; an accepted connection, however silent, answers yes.
|
|
141
|
+
* A named pipe has no entry to lose and an abstract socket has no path, so both read as owned;
|
|
142
|
+
* so does an entry this process cannot stat, because an owner that cannot be ruled out is one
|
|
143
|
+
* this ensure must not bind over.
|
|
144
|
+
*/
|
|
145
|
+
async function publicEndpointAccepts(socket) {
|
|
146
|
+
if (process.platform === "win32" || socket.startsWith("\0"))
|
|
147
|
+
return true;
|
|
148
|
+
const entry = await statSocketIdentity(socket).then((identity) => (identity === undefined ? "absent" : "present"), () => "unknown");
|
|
149
|
+
if (entry === "absent")
|
|
150
|
+
return false;
|
|
151
|
+
if (entry === "unknown")
|
|
152
|
+
return true;
|
|
153
|
+
return probeSocketReachable(socket, FOREIGN_ENDPOINT_PROBE_TIMEOUT_MS);
|
|
154
|
+
}
|
|
117
155
|
/** `fallback` belongs to clients that can live without a host; an ensure must produce one or fail. */
|
|
118
156
|
function decide(options, startedByUs, protocol) {
|
|
119
157
|
if (options.upgrade !== "if-engine-differs") {
|
|
@@ -169,7 +207,11 @@ function registersSocket(registered, socket) {
|
|
|
169
207
|
return false;
|
|
170
208
|
return registered.socket === undefined || registered.socket === socket;
|
|
171
209
|
}
|
|
172
|
-
|
|
210
|
+
/**
|
|
211
|
+
* `generation` is 0 for a fresh endpoint; a start that leaves a stranded generation running beside
|
|
212
|
+
* the new one numbers it after that generation, as a handoff would.
|
|
213
|
+
*/
|
|
214
|
+
async function startHost(paths, socket, options, generation = 0) {
|
|
173
215
|
const testOptions = options._test;
|
|
174
216
|
// The generation this ensure is about to spawn, chosen HERE so its directory exists before the
|
|
175
217
|
// host boots and the pointer can name it the moment the host is registered.
|
|
@@ -183,10 +225,11 @@ async function startHost(paths, socket, options) {
|
|
|
183
225
|
capabilities: PINNED_HOST_CLIENT_CAPABILITIES,
|
|
184
226
|
coldStart: options.policy?.coldStart ?? "transient",
|
|
185
227
|
idleExitMs: options.policy?.idleExitMs ?? DEFAULT_HOST_IDLE_EXIT_MS,
|
|
186
|
-
generation
|
|
228
|
+
generation,
|
|
187
229
|
instanceId,
|
|
188
230
|
});
|
|
189
|
-
|
|
231
|
+
// A stranded generation is still writing its diagnostics here; only a fresh endpoint starts over.
|
|
232
|
+
const stderr = await open(paths.stderrLog, generation === 0 ? "w" : "a", 0o600);
|
|
190
233
|
let pidFile;
|
|
191
234
|
let child;
|
|
192
235
|
let exitedEarly;
|
|
@@ -197,7 +240,7 @@ async function startHost(paths, socket, options) {
|
|
|
197
240
|
child = spawn(launch.command, [...launch.args], {
|
|
198
241
|
detached: true,
|
|
199
242
|
windowsHide: true,
|
|
200
|
-
env: hostEnv(options, { paths, instanceId }),
|
|
243
|
+
env: hostEnv(options, { paths, instanceId, generation }),
|
|
201
244
|
stdio: ["ignore", "ignore", stderr.fd],
|
|
202
245
|
});
|
|
203
246
|
childExit = new Promise((resolveExit) => {
|
|
@@ -232,7 +275,7 @@ async function startHost(paths, socket, options) {
|
|
|
232
275
|
record: pidFile,
|
|
233
276
|
socket,
|
|
234
277
|
instanceId,
|
|
235
|
-
generation
|
|
278
|
+
generation,
|
|
236
279
|
launchProfileId: hostLaunchProfile(hostChildArgv(options.hostArgs ?? []), process.cwd()).profile_id,
|
|
237
280
|
});
|
|
238
281
|
child.unref();
|
|
@@ -432,7 +475,7 @@ function hostEnv(options, generation) {
|
|
|
432
475
|
// its own host's identity to the one it spawns, and two hosts claiming one instance id make a
|
|
433
476
|
// handoff - which completes exactly when the instance id changes - impossible to observe.
|
|
434
477
|
env[HOST_INSTANCE_ID_ENV] = generation.instanceId;
|
|
435
|
-
env[HOST_GENERATION_ENV] =
|
|
478
|
+
env[HOST_GENERATION_ENV] = String(generation.generation);
|
|
436
479
|
env[HOST_DAEMON_DIR_ENV] = generation.paths.dir;
|
|
437
480
|
return env;
|
|
438
481
|
}
|