@code-yeongyu/senpi 2026.9.21-2 → 2026.9.22-2
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 +56 -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-PRNA6QQU.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-7TAGS2VU.js → azure-openai-responses-3AH7MJWF.js} +1 -1
- package/dist/bundle/chunks/{bun-extension-importer-UO7V2MZ7.js → bun-extension-importer-H4IJCWWQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-OSDJ2SYO.js → chunk-5XC2FNJ5.js} +1 -1
- package/dist/bundle/chunks/{chunk-D5CL7PPD.js → chunk-64JQFFHH.js} +2 -2
- package/dist/bundle/chunks/{chunk-Z3KQB2R3.js → chunk-6OD4TT33.js} +95 -39
- package/dist/bundle/chunks/{chunk-NEEAKXDT.js → chunk-7EH64T6E.js} +2 -2
- package/dist/bundle/chunks/{chunk-MIVOQT3Q.js → chunk-ARJJU3MS.js} +1 -1
- package/dist/bundle/chunks/chunk-BOZ37BOT.js +14 -0
- package/dist/bundle/chunks/{chunk-POMPEGWQ.js → chunk-F3DXL5MX.js} +1 -1
- package/dist/bundle/chunks/{chunk-GLKVDRNP.js → chunk-GXUYWMN2.js} +1 -1
- package/dist/bundle/chunks/chunk-HH3KJDWA.js +2 -0
- package/dist/bundle/chunks/{chunk-B7W62BM7.js → chunk-IPRJIKLL.js} +1 -1
- package/dist/bundle/chunks/chunk-JEFYJDHP.js +8 -0
- package/dist/bundle/chunks/{chunk-T6XA2IZR.js → chunk-JR4X6ECO.js} +1 -1
- package/dist/bundle/chunks/{chunk-I425CMTO.js → chunk-JZ6YQU3A.js} +4 -4
- package/dist/bundle/chunks/{chunk-KNM6SRPE.js → chunk-K3HEWWSS.js} +1 -1
- package/dist/bundle/chunks/{chunk-M2XAY6I7.js → chunk-M2HSO7MH.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-VEO3ABZR.js → chunk-OLJ7LQJY.js} +1 -1
- package/dist/bundle/chunks/{chunk-GVI2HP7N.js → chunk-OPNVT7BU.js} +1 -1
- package/dist/bundle/chunks/{chunk-XHMOFY4T.js → chunk-R6LVC7SP.js} +4 -4
- package/dist/bundle/chunks/{chunk-3SLCHXZO.js → chunk-UCPWK6TZ.js} +2 -2
- package/dist/bundle/chunks/{chunk-B2IM56LB.js → chunk-VYIJQQ5I.js} +1 -1
- package/dist/bundle/chunks/{chunk-47GF6XYZ.js → chunk-YT2ZSZOY.js} +1 -1
- package/dist/bundle/chunks/{cli-main-GQTEEZ2V.js → cli-main-AFJNXUSL.js} +1 -1
- package/dist/bundle/chunks/github-copilot.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-OVA6GEWC.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle-IDQPLYEA.js +3 -0
- package/dist/bundle/chunks/host-lifecycle.js +10 -6
- package/dist/bundle/chunks/{interactive-host-runtime-2KTFEW7O.js → interactive-host-runtime-F5L4USLR.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-I3ILWXQB.js → interactive-mode-UFBSCOP7.js} +1 -1
- package/dist/bundle/chunks/kimi-coding.js +2 -2
- package/dist/bundle/chunks/{list-tips-2KX65NWZ.js → list-tips-2QG7ASHS.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-VOBYATVJ.js → mistral-conversations-ZYDVFRYF.js} +1 -1
- package/dist/bundle/chunks/multi-session-host-EUTEGVLS.js +21 -0
- 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-JPUWMUEJ.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-S56Y7WMM.js +2 -0
- package/dist/bundle/chunks/{rpc-mode-L3DSGTVM.js → rpc-mode-JDVHUBZY.js} +1 -1
- package/dist/bundle/chunks/{session-picker-L3FYEQBL.js → session-picker-PFPJVVIC.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +225 -164
- 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/claude-sdk-oauth/api-id.d.ts +7 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/api-id.d.ts.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/api-id.js +7 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/api-id.js.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/index.js +3 -2
- package/dist/core/extensions/builtin/claude-sdk-oauth/index.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +22 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts +2 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js +4 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +18 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js +18 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.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/gpt-apply-patch/extension.js +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/extension.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/extensions/builtin/prompt-preset/file-operations.js +1 -1
- package/dist/core/extensions/builtin/prompt-preset/file-operations.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.d.ts +3 -0
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.d.ts.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.js +105 -0
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.js +14 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
- package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
- package/dist/core/extensions/bun-extension-importer.d.ts +1 -0
- package/dist/core/extensions/bun-extension-importer.d.ts.map +1 -1
- package/dist/core/extensions/bun-extension-importer.js +4 -0
- package/dist/core/extensions/bun-extension-importer.js.map +1 -1
- package/dist/core/extensions/extension-module-cache.d.ts +48 -0
- package/dist/core/extensions/extension-module-cache.d.ts.map +1 -0
- package/dist/core/extensions/extension-module-cache.js +111 -0
- package/dist/core/extensions/extension-module-cache.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +14 -56
- package/dist/core/extensions/loader.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/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/retry-fallback/billing.d.ts.map +1 -1
- package/dist/core/retry-fallback/billing.js +20 -1
- package/dist/core/retry-fallback/billing.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +12 -6
- package/dist/core/session-manager.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/custom-capability.d.ts +7 -0
- package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
- package/dist/modes/rpc/custom-capability.js +7 -0
- package/dist/modes/rpc/custom-capability.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-child-exit.d.ts +19 -0
- package/dist/modes/rpc/host-child-exit.d.ts.map +1 -0
- package/dist/modes/rpc/host-child-exit.js +35 -0
- package/dist/modes/rpc/host-child-exit.js.map +1 -0
- package/dist/modes/rpc/host-crash-record.d.ts +24 -0
- package/dist/modes/rpc/host-crash-record.d.ts.map +1 -0
- package/dist/modes/rpc/host-crash-record.js +75 -0
- package/dist/modes/rpc/host-crash-record.js.map +1 -0
- package/dist/modes/rpc/host-crash-record.test.d.ts +2 -0
- package/dist/modes/rpc/host-crash-record.test.d.ts.map +1 -0
- package/dist/modes/rpc/host-crash-record.test.js +91 -0
- package/dist/modes/rpc/host-crash-record.test.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 +4 -10
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +83 -51
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/host-supersession.d.ts +13 -2
- package/dist/modes/rpc/host-supersession.d.ts.map +1 -1
- package/dist/modes/rpc/host-supersession.js +40 -7
- package/dist/modes/rpc/host-supersession.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/observer-link.d.ts +48 -0
- package/dist/modes/rpc/observer-link.d.ts.map +1 -0
- package/dist/modes/rpc/observer-link.js +56 -0
- package/dist/modes/rpc/observer-link.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts +12 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +12 -2
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +36 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js +8 -0
- 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 +95 -19
- 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-registry.d.ts +6 -1
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +34 -3
- package/dist/modes/rpc/session-registry.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/dist/modes/rpc/socket-ownership.d.ts +16 -0
- package/dist/modes/rpc/socket-ownership.d.ts.map +1 -1
- package/dist/modes/rpc/socket-ownership.js +28 -4
- package/dist/modes/rpc/socket-ownership.js.map +1 -1
- package/dist/modes/rpc/worker-session-registry.d.ts +12 -5
- package/dist/modes/rpc/worker-session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/worker-session-registry.js +10 -2
- package/dist/modes/rpc/worker-session-registry.js.map +1 -1
- package/docs/providers.md +9 -1
- package/docs/rpc.md +72 -10
- package/docs/settings.md +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +29 -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 +6 -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 +32 -8
- 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/dist/agent-loop.d.ts +2 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +2 -13
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/tool-arguments.d.ts +5 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/tool-arguments.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/tool-arguments.js +20 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/tool-arguments.js.map +1 -0
- 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/compat.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/compat.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +2 -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 +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/legacy-provider-ids.d.ts +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/legacy-provider-ids.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/legacy-provider-ids.js +26 -0
- package/node_modules/@earendil-works/pi-ai/dist/legacy-provider-ids.js.map +1 -0
- 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/github-copilot.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/opencode.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/venice.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/data/xai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi.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-profile/classifiers.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.js +5 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/classifiers.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +17 -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 +22 -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/dist/tui.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +12 -2
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +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/chunk-IDTLJYJ5.js +0 -10
- package/dist/bundle/chunks/chunk-U6Z6OBX4.js +0 -2
- package/dist/bundle/chunks/host-lifecycle-DGZJTBDJ.js +0 -3
- package/dist/bundle/chunks/multi-session-host-S5FWCIWE.js +0 -20
- 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
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
+
import{HOST_INSTANCE_ID_ENV,MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader,engineBuildIdentity}from"./chunk-M2HSO7MH.js";import{envValue,getAgentDir,isBunBinary,isBundledNode}from"./chunk-Y65WFI5H.js";import{spawn}from"node:child_process";import{randomUUID}from"node:crypto";import{existsSync,readFileSync as readFileSync2,realpathSync,writeSync}from"node:fs";import{access,chmod as chmod3,mkdir as mkdir5,readFile as readFile5,rename as rename4,rm as rm5,unlink as unlink2,writeFile as writeFile6}from"node:fs/promises";import{createConnection,createServer}from"node:net";import{tmpdir}from"node:os";import{dirname as dirname3,extname,join as join4,resolve}from"node:path";import{fileURLToPath}from"node:url";import{execFile}from"node:child_process";function parseDaemonPidFile(text){let parsed;try{parsed=JSON.parse(text)}catch(error){if(error instanceof SyntaxError)return;throw error}let unguarded=parsed!==null&&isRecord(parsed)&&parsed.processStartTime===null;if(!(!isRecord(parsed)||typeof parsed.pid!="number"||!unguarded&&typeof parsed.processStartTime!="string")&&!(!Number.isInteger(parsed.pid)||parsed.pid<=0)){if(unguarded)return{pid:parsed.pid,processStartTime:null};if(!(typeof parsed.processStartTime!="string"||parsed.processStartTime.trim()===""))return{pid:parsed.pid,processStartTime:parsed.processStartTime}}}var ProcessIdentityUnreadableError=class extends Error{constructor(pid,attempts,cause){super(`process identity for live pid ${pid} stayed unreadable after ${attempts} probe attempt(s): ${cause instanceof Error?cause.message:String(cause)}`),this.name="ProcessIdentityUnreadableError",this.pid=pid,this.attempts=attempts,this.cause=cause}};async function processMatchesPidFile(pidFile,readStartTime=readProcessStartTime,isLive=processIsLive,retry={}){if(pidFile.processStartTime===null){if(!isLive(pidFile.pid))return!1;throw new ProcessIdentityUnreadableError(pidFile.pid,0,new Error("pidfile carries no process identity guard"))}let attempts=Math.max(1,retry.attempts??5),delayMs=retry.delayMs??200,lastError;for(let attempt=1;attempt<=attempts;attempt++)try{let current=await readStartTime(pidFile.pid);if(current!==void 0)return current===pidFile.processStartTime;if(!isLive(pidFile.pid))return!1;lastError=new Error("process identity probe returned no identity for a live process"),attempt<attempts&&await new Promise(resolve2=>setTimeout(resolve2,delayMs))}catch(error){if(!isLive(pidFile.pid))return!1;lastError=error,attempt<attempts&&await new Promise(resolve2=>setTimeout(resolve2,delayMs))}throw new ProcessIdentityUnreadableError(pidFile.pid,attempts,lastError)}async function readProcessIdentity(pid,platform=process.platform,timeoutMs,isLive=processIsLive){let command=platform==="win32"?{executable:"powershell.exe",args:["-NoProfile","-NonInteractive","-Command",`$process = Get-CimInstance Win32_Process -Filter "ProcessId=${String(pid)}" -ErrorAction Stop; if ($null -eq $process) { Write-Output '__SENPI_ABSENT__'; exit 0 }; $process.CreationDate.ToFileTimeUtc().ToString("D", [Globalization.CultureInfo]::InvariantCulture)`]}:{executable:"ps",args:["-o","lstart=","-p",String(pid)]};return new Promise(resolve2=>{let effectiveTimeoutMs=timeoutMs??(platform==="win32"?1e3:void 0);execFile(command.executable,command.args,{windowsHide:!0,...effectiveTimeoutMs===void 0?{}:{timeout:effectiveTimeoutMs}},(error,stdout)=>{if(error){let code="code"in error?error.code:void 0;if(platform!=="win32"&&code===1||!isLive(pid)){resolve2({kind:"absent"});return}resolve2({kind:"error",error});return}let output=stdout.trim();if(output==="__SENPI_ABSENT__")return resolve2({kind:"absent"});if(!output||platform==="win32"&&!/^\d+$/.test(output))return resolve2({kind:"error",error:new Error("invalid process identity output")});resolve2({kind:"present",identity:output})}).once("error",error=>resolve2({kind:"error",error}))})}async function stopValidatedPid(pidFile,signal){if(await processMatchesPidFile(pidFile)){try{process.kill(pidFile.pid,signal)}catch(error){if(!isNodeErrorCode(error,"ESRCH"))throw error}signal==="SIGTERM"&&await waitForGone(pidFile,1e4),signal==="SIGKILL"&&await waitForGone(pidFile,2e3)}}async function waitForGone(pidFile,timeoutMs){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(!await processMatchesPidFile(pidFile))return!0;await delay(100)}return!await processMatchesPidFile(pidFile)}async function readProcessStartTime(pid,platform=process.platform,timeoutMs){return readProcessIdentity(pid,platform,timeoutMs).then(result=>{if(result.kind==="error")throw result.error;return result.kind==="present"?result.identity:void 0})}function processIsLive(pid){try{return process.kill(pid,0),!0}catch(error){if(isNodeErrorCode(error,"ESRCH"))return!1;if(isNodeErrorCode(error,"EPERM"))return!0;throw error}}async function waitForStartTime(pid,timeoutMs,readStartTime=readProcessStartTime,isLive=processIsLive){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){let startTime;try{startTime=await readStartTime(pid)}catch{}if(startTime)return startTime;await delay(20)}if(!isLive(pid))throw new Error(`spawned daemon pid ${pid} had no process start time`)}function delay(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isNodeErrorCode(error,code){return error instanceof Error&&"code"in error&&error.code===code}import{appendFileSync,mkdirSync,readFileSync,writeFileSync}from"node:fs";import{join}from"node:path";var HOST_CRASH_RECORD_LIMIT=50,CRASH_RECORD_FILE_MODE=384;function hostCrashRecordFile(daemonDir){return join(daemonDir,"crashes.jsonl")}function recordHostCrash(daemonDir,record){try{mkdirSync(daemonDir,{recursive:!0,mode:448}),appendFileSync(hostCrashRecordFile(daemonDir),`${JSON.stringify(record)}
|
|
3
|
+
`,{mode:CRASH_RECORD_FILE_MODE}),pruneHostCrashRecords(daemonDir)}catch{}}function readHostCrashRecords(daemonDir){let raw;try{raw=readFileSync(hostCrashRecordFile(daemonDir),"utf8")}catch{return[]}let records=[];for(let line of raw.split(`
|
|
4
|
+
`))if(line.trim()!=="")try{let value=JSON.parse(line);typeof value=="object"&&value!==null&&typeof Reflect.get(value,"at")=="string"&&records.push(value)}catch{}return records}function pruneHostCrashRecords(daemonDir){let records=readHostCrashRecords(daemonDir);if(records.length<=HOST_CRASH_RECORD_LIMIT)return;let kept=records.slice(records.length-HOST_CRASH_RECORD_LIMIT);writeFileSync(hostCrashRecordFile(daemonDir),`${kept.map(r=>JSON.stringify(r)).join(`
|
|
5
|
+
`)}
|
|
6
|
+
`,{mode:CRASH_RECORD_FILE_MODE})}function classifyChildExit(code,signal){return code===0&&signal===null?{reason:"rpc host exited on its own idle policy",exitCode:0}:{reason:`rpc host process exited unexpectedly (${code??signal})`,exitCode:1}}function noteChildExit(daemonDir,code,signal,childStartedAt,now=Date.now()){classifyChildExit(code,signal).exitCode!==0&&recordHostCrash(daemonDir,{at:new Date(now).toISOString(),...signal===null?{code:code??void 0}:{signal},uptimeMs:Math.max(0,now-childStartedAt)})}import{createHash}from"node:crypto";import{chmod,mkdir,writeFile}from"node:fs/promises";import{basename,join as join2,win32}from"node:path";var HOST_DAEMON_LAYOUT=2,HOST_DAEMON_DIR_ENV="SENPI_RPC_HOST_DAEMON_DIR",DIRECTORY_MODE=448,HOST_STATE_FILE_MODE=384;function daemonDirectoryName(socket,platform=process.platform){let canonical=platform==="win32"?win32.normalize(socket).toLowerCase():socket;return createHash("sha256").update(canonical,"utf8").digest("hex").slice(0,16)}function createHostDaemonPaths(target){let flatDir=join2(target.agentDir??getAgentDir(),"rpc-host-daemon");return{flatDir,layoutMarker:join2(flatDir,"layout.json"),legacyPidFile:join2(flatDir,"host.pid"),...hostDaemonDirectoryPaths(join2(flatDir,daemonDirectoryName(target.socket)))}}function hostDaemonDirectoryPaths(dir){return{dir,pointerFile:join2(dir,"host.pid"),lockFile:join2(dir,"daemon.lock"),settingsFile:join2(dir,"settings.json"),stderrLog:join2(dir,"stderr.log"),generationsDir:join2(dir,"generations"),reservationsDir:join2(dir,"reservations")}}function generationPaths(paths,instanceId){let dir=join2(paths.generationsDir,instanceId);return{dir,relativeDir:`generations/${instanceId}`,pidFile:join2(dir,"host.pid"),settingsFile:join2(dir,"settings.json"),scratchDir:join2(dir,"scratch")}}var HostDaemonStateError=class extends Error{constructor(path,cause){super(`RPC daemon state directory ${path} is not usable: ${cause instanceof Error?cause.message:cause}`,{cause}),this.name="HostDaemonStateError",this.path=path}};async function createDaemonDirectories(paths){try{await mkdir(paths.flatDir,{recursive:!0,mode:DIRECTORY_MODE});for(let directory of[paths.dir,paths.generationsDir,paths.reservationsDir])await mkdir(directory,{recursive:!0,mode:DIRECTORY_MODE}),await chmod(directory,DIRECTORY_MODE);await writeFile(paths.layoutMarker,`${JSON.stringify({layout:HOST_DAEMON_LAYOUT,dir:basename(paths.dir)})}
|
|
7
|
+
`,{mode:HOST_STATE_FILE_MODE})}catch(cause){throw new HostDaemonStateError(paths.dir,cause)}}async function createGenerationDirectory(generation){try{await mkdir(generation.scratchDir,{recursive:!0,mode:DIRECTORY_MODE}),await chmod(generation.dir,DIRECTORY_MODE)}catch(cause){throw new HostDaemonStateError(generation.dir,cause)}}import{rename as rename2,rm as rm3}from"node:fs/promises";import{readFile,writeFile as writeFile2}from"node:fs/promises";async function writeHostSettings(paths,settings){let generation=generationPaths(paths,settings.instanceId);await createGenerationDirectory(generation),await writeStateFile(paths.settingsFile,settings),await writeStateFile(generation.settingsFile,settings)}async function readHostSettings(paths){let parsed=parseJson(await readFileOrUndefined(paths.settingsFile));if(parsed)return{...typeof parsed.coldStart=="string"&&{coldStart:parsed.coldStart},...typeof parsed.idleExitMs=="number"&&{idleExitMs:parsed.idleExitMs}}}async function writeStateFile(path,content){try{await writeFile2(path,`${JSON.stringify(content)}
|
|
8
|
+
`,{mode:HOST_STATE_FILE_MODE})}catch(cause){throw new HostDaemonStateError(path,cause)}}async function readFileOrUndefined(path){try{return await readFile(path,"utf8")}catch(error){if(isNodeErrorCode2(error,"ENOENT")||isNodeErrorCode2(error,"ENOTDIR"))return;throw error}}function parseJson(text){if(text!==void 0)try{let parsed=JSON.parse(text);return isRecord2(parsed)?parsed:void 0}catch{return}}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isNodeErrorCode2(error,code){return error instanceof Error&&"code"in error&&error.code===code}import{readdir as readdir3,rm as rm2}from"node:fs/promises";import{execFile as execFile2}from"node:child_process";import{readdir}from"node:fs/promises";import{promisify}from"node:util";var run=promisify(execFile2),PS_TIMEOUT_MS=5e3,KILOBYTES_PER_MEGABYTE=1024,UNOBSERVED={rss_mb:null,open_fds:null,zombies:null};async function readHostProcessMetrics(pid,platform=process.platform){if(platform==="win32")return UNOBSERVED;let rows=await processTable();if(rows===void 0)return UNOBSERVED;let tree=descendants(rows,pid);return tree.length===0?UNOBSERVED:{rss_mb:Math.round(tree.reduce((total,row)=>total+row.rssKb,0)/KILOBYTES_PER_MEGABYTE),open_fds:platform==="linux"?await openDescriptors(tree):null,zombies:tree.filter(row=>row.state.startsWith("Z")).length}}async function processTable(){try{let{stdout}=await run("ps",["-A","-o","pid=,ppid=,stat=,rss="],{timeout:PS_TIMEOUT_MS});return stdout.split(`
|
|
9
|
+
`).flatMap(line=>{let[pid,ppid,state,rss]=line.trim().split(/\s+/u);if(pid===void 0||ppid===void 0||state===void 0||rss===void 0)return[];let row={pid:Number(pid),ppid:Number(ppid),state,rssKb:Number(rss)};return Number.isInteger(row.pid)&&Number.isInteger(row.ppid)&&Number.isFinite(row.rssKb)?[row]:[]})}catch{return}}function descendants(rows,root){let tree=rows.filter(row=>row.pid===root);if(tree.length===0)return tree;for(let index=0;index<tree.length;index++){let parent=tree[index].pid;for(let row of rows)row.ppid===parent&&!tree.includes(row)&&tree.push(row)}return tree}async function openDescriptors(tree){let total=0,counted=!1;for(let row of tree){let entries=await readdir(`/proc/${row.pid}/fd`).catch(()=>{});entries!==void 0&&(counted=!0,total+=entries.length)}return counted?total:null}import{createHash as createHash2}from"node:crypto";import{mkdir as mkdir2,readdir as readdir2,readFile as readFile2,rename,rm,writeFile as writeFile3}from"node:fs/promises";import{join as join3}from"node:path";var SESSION_PATH_RETRY_AFTER_MS=2e3;function reservationFile(dir,sessionPath){return join3(dir,`${createHash2("sha256").update(sessionPath,"utf8").digest("hex").slice(0,16)}.json`)}function createEndpointReservations(host){let told=process.env[HOST_DAEMON_DIR_ENV],dir=told!==void 0&&told.trim()!==""?told:host.socket===void 0?void 0:createHostDaemonPaths({socket:host.socket,agentDir:host.agentDir}).dir;if(dir!==void 0)return createSessionPathReservations({daemonDir:dir,instanceId:host.instanceId,...host.onFailure?{onFailure:host.onFailure}:{}})}function createSessionPathReservations(options){let paths=hostDaemonDirectoryPaths(options.daemonDir),dir=paths.reservationsDir,pid=options.pid??process.pid,startTime=readProcessStartTime(pid).then(value=>value??null,()=>null),held=new Set,report=message=>options.onFailure?.(message),publish=async(sessionPath,attached,stillHeld)=>{let owner={instanceId:options.instanceId,pid,processStartTime:await startTime,sessionPath,attached},file=reservationFile(dir,sessionPath);await mkdir2(dir,{recursive:!0,mode:448});let staging=`${file}.${pid}.tmp`;if(await writeFile3(staging,`${JSON.stringify(owner)}
|
|
10
|
+
`,{mode:384}),stillHeld?.()===!1){await rm(staging,{force:!0});return}await rename(staging,file)};return{async claim(sessionPath,attached=!0){let existing=await readOwner(reservationFile(dir,sessionPath));if(existing&&existing.pid!==pid){let standing=await standingOwner(existing,paths.pointerFile);if(standing)return standing}try{await publish(sessionPath,attached),held.add(sessionPath)}catch(cause){report(`session path reservation for ${sessionPath} could not be written (${errorMessage(cause)})`)}},release(sessionPath){held.delete(sessionPath)&&rm(reservationFile(dir,sessionPath),{force:!0}).catch(cause=>{report(`session path reservation for ${sessionPath} could not be removed (${errorMessage(cause)})`)})},setAttached(sessionPath,attached){held.has(sessionPath)&&publish(sessionPath,attached,()=>held.has(sessionPath)).catch(cause=>{report(`session path reservation for ${sessionPath} could not be updated (${errorMessage(cause)})`)})}}}async function readSessionPathClaims(dir){let entries=await readdir2(dir).catch(()=>[]),claims=[];for(let entry of entries){if(!entry.endsWith(".json"))continue;let file=join3(dir,entry),owner=await readOwner(file);owner&&claims.push({file,owner})}return claims}async function standingOwner(owner,pointerFile){if(!await claimOwnerIsLive(owner))return;let current=await currentInstanceId(pointerFile)===owner.instanceId;return current||owner.attached!==!1?{...owner,current}:void 0}async function currentInstanceId(pointerFile){let pointer=parseJson(await readFileOrUndefined(pointerFile).catch(()=>{}));return typeof pointer?.instance_id=="string"?pointer.instance_id:void 0}async function readOwner(file){let parsed;try{parsed=JSON.parse(await readFile2(file,"utf8"))}catch{return}if(typeof parsed!="object"||parsed===null)return;let{instanceId,pid,processStartTime,sessionPath,attached}=parsed;if(!(typeof instanceId!="string"||typeof pid!="number"||typeof sessionPath!="string"))return{instanceId,pid,processStartTime:typeof processStartTime=="string"?processStartTime:null,sessionPath,...typeof attached=="boolean"?{attached}:{}}}async function claimOwnerIsLive(owner){if(!processIsLive(owner.pid))return!1;if(owner.processStartTime===null)return!0;let current=await readProcessStartTime(owner.pid).catch(()=>{});return current===void 0||current===owner.processStartTime}function errorMessage(cause){return cause instanceof Error?cause.message:String(cause)}async function pruneDeadGenerations(paths){let pointer=parseJson(await readFileOrUndefined(paths.pointerFile).catch(()=>{})),pointedAt=typeof pointer?.instance_id=="string"?pointer.instance_id:void 0,generations=[];for(let instanceId of await readdir3(paths.generationsDir).catch(()=>[])){let record=parseJson(await readFileOrUndefined(generationPaths(paths,instanceId).pidFile));typeof record?.pid!="number"||processIsLive(record.pid)||(await rm2(generationPaths(paths,instanceId).dir,{recursive:!0,force:!0}).catch(()=>{}),generations.push(instanceId))}let pointerRemoved=pointedAt!==void 0&&generations.includes(pointedAt);pointerRemoved&&await rm2(paths.pointerFile,{force:!0}).catch(()=>{});let claims=[];for(let claim of await readSessionPathClaims(paths.reservationsDir))await claimOwnerIsLive(claim.owner)||(await rm2(claim.file,{force:!0}).catch(()=>{}),claims.push(claim.owner.sessionPath));return{generations,claims,pointer:pointerRemoved}}async function readGenerationRows(paths){let pointer=parseJson(await readFileOrUndefined(paths.pointerFile).catch(()=>{})),currentId=typeof pointer?.instance_id=="string"?pointer.instance_id:void 0,claims=await readSessionPathClaims(paths.reservationsDir),rows=[];for(let instanceId of await readdir3(paths.generationsDir).catch(()=>[])){let record=parseJson(await readFileOrUndefined(generationPaths(paths,instanceId).pidFile));typeof record?.pid!="number"||!processIsLive(record.pid)||rows.push({instanceId,generation:typeof record.generation=="number"?record.generation:0,pid:record.pid,engineVersion:typeof record.engineVersion=="string"?record.engineVersion:null,rss_mb:(await readHostProcessMetrics(record.pid)).rss_mb,sessions:claims.filter(claim=>claim.owner.instanceId===instanceId).length,current:instanceId===currentId,alive:!0})}return rows.sort((left,right)=>left.generation-right.generation)}async function readHostRegistration(paths){let pointer=parseJson(await readFileOrUndefined(paths.pointerFile));if(!pointer||typeof pointer.instance_id!="string")return;let text=await readFileOrUndefined(generationPaths(paths,pointer.instance_id).pidFile),record=text===void 0?void 0:parseDaemonPidFile(text);if(record===void 0)return;let parsed=parseJson(text)??{},writer=parseWriter(parsed);return{record,...writer&&{writer},...typeof parsed.socket=="string"&&{socket:parsed.socket},instanceId:pointer.instance_id,generation:typeof parsed.generation=="number"?parsed.generation:0}}async function writeHostRegistration(paths,registration){await pruneDeadGenerations(paths);let generation=generationPaths(paths,registration.instanceId),writer={pid:process.pid,startTime:await thisProcessStartTime()},build=engineBuildIdentity();await createGenerationDirectory(generation),await writeStateFile(generation.pidFile,{...registration.record,instance_id:registration.instanceId,generation:registration.generation,engineVersion:build.text,engineOrdinal:build.ordinal,launchProfileId:registration.launchProfileId,socket:registration.socket,writer}),await writeStateFile(`${paths.pointerFile}.${process.pid}.tmp`,{layout:HOST_DAEMON_LAYOUT,instance_id:registration.instanceId,generation_dir:generation.relativeDir,writer}),await rename2(`${paths.pointerFile}.${process.pid}.tmp`,paths.pointerFile)}async function clearHostRegistration(paths){let pointer=parseJson(await readFileOrUndefined(paths.pointerFile));typeof pointer?.instance_id=="string"&&await rm3(generationPaths(paths,pointer.instance_id).dir,{recursive:!0,force:!0}),await rm3(paths.pointerFile,{force:!0}),await rm3(paths.settingsFile,{force:!0})}async function releaseGeneration(paths,owner){let generation=generationPaths(paths,owner.instanceId),record=parseDaemonPidFile(await readFileOrUndefined(generation.pidFile)??"");if(record!==void 0&&record.pid!==owner.pid)return;parseJson(await readFileOrUndefined(paths.pointerFile))?.instance_id===owner.instanceId&&(await rm3(paths.pointerFile,{force:!0}),await rm3(paths.settingsFile,{force:!0})),await rm3(generation.dir,{recursive:!0,force:!0})}async function readLegacyHostRecord(paths){let text=await readFileOrUndefined(paths.legacyPidFile);return text===void 0?void 0:parseDaemonPidFile(text)}async function provenOwner(registered,socket){let record=registered?.record;if(!record||record.processStartTime===null||registered?.socket!==void 0&®istered.socket!==socket)return;let identity={pid:record.pid,processStartTime:record.processStartTime};return await processMatchesPidFile(identity,readProcessStartTime).catch(()=>!1)?{...identity,instanceId:registered.instanceId}:void 0}async function legacyHostIsLive(paths,probe){let record=await readLegacyHostRecord(paths);if(record===void 0)return!1;try{return await processMatchesPidFile(record,probe)}catch(error){if(error instanceof ProcessIdentityUnreadableError)return!0;throw error}}async function writtenByThisProcess(writer){return writer===void 0||writer.pid!==process.pid||writer.startTime===null?!1:writer.startTime===await thisProcessStartTime()}var selfStartTime;function thisProcessStartTime(){return selfStartTime??=readProcessStartTime(process.pid).then(value=>value??null,()=>null),selfStartTime}function parseWriter(parsed){if(!isRecord2(parsed.writer)||typeof parsed.writer.pid!="number")return;let{pid,startTime}=parsed.writer;return{pid,startTime:typeof startTime=="string"?startTime:null}}import{mkdir as mkdir3,readFile as readFile3,rename as rename3,stat,unlink,writeFile as writeFile4}from"node:fs/promises";import{dirname}from"node:path";var PUBLIC_SOCKET_IDENTITY_FILE="public-socket.owner",SOCKET_IDENTITY_WAIT_MS=3e4,MAX_SOCKET_PATH_BYTES=103;function generationBindPath(publicSocket,generation){return`${publicSocket}.next-${generation}`}function sameSocketIdentity(a,b){return a.dev===b.dev&&a.ino===b.ino}async function statSocketIdentity(socketPath){try{let{dev,ino}=await stat(socketPath);return{dev,ino}}catch(cause){if(isNodeErrorCode3(cause,"ENOENT"))return;throw cause}}async function classifyEndpointOwnership(socketPath,identity){if(identity===void 0||process.platform==="win32"||socketPath.startsWith("\0"))return"unknown";let current;try{current=await statSocketIdentity(socketPath)}catch{return"unknown"}return current===void 0?"absent":sameSocketIdentity(current,identity)?"held":"replaced"}async function socketEntryReplaced(socketPath,identity){return await classifyEndpointOwnership(socketPath,identity)==="replaced"}async function writeSocketIdentityFile(path,identity){await mkdir3(dirname(path),{recursive:!0,mode:448});let tmpPath=`${path}.${process.pid}.tmp`;await writeFile4(tmpPath,`${JSON.stringify(identity)}
|
|
11
|
+
`,{mode:384}),await rename3(tmpPath,path)}async function readSocketIdentityFile(path){let raw;try{raw=await readFile3(path,"utf8")}catch(cause){if(isNodeErrorCode3(cause,"ENOENT"))return;throw cause}let parsed;try{parsed=JSON.parse(raw)}catch{return}if(!(typeof parsed!="object"||parsed===null||typeof parsed.dev!="number"||typeof parsed.ino!="number"))return{dev:parsed.dev,ino:parsed.ino}}async function waitForSocketIdentityFile(path,timeoutMs=SOCKET_IDENTITY_WAIT_MS,intervalMs=25){let deadline=Date.now()+timeoutMs;for(;;){let identity=await readSocketIdentityFile(path);if(identity!==void 0)return identity;if(Date.now()>=deadline)return;await delayUnrefed(intervalMs)}}async function unlinkOwnedSocket(socketPath,identity,log){if(process.platform==="win32"||socketPath.startsWith("\0"))return;let current;try{current=await statSocketIdentity(socketPath)}catch(cause){log(`socket ${socketPath} ownership could not be verified (${errorMessage2(cause)}); leaving it`);return}if(current!==void 0){if(identity===void 0){log(`socket path ${socketPath} ownership unknown; leaving it`);return}if(!sameSocketIdentity(current,identity)){log(`socket path ${socketPath} now owned by another host; leaving it`);return}try{await unlink(socketPath)}catch(cause){isNodeErrorCode3(cause,"ENOENT")||log(`socket ${socketPath} removal failed (${errorMessage2(cause)})`)}}}async function shieldSocketDuringClose(socketPath,close){if(process.platform==="win32"||socketPath.startsWith("\0"))return close();let shieldPath=`${socketPath}.shield-${process.pid}`,shielded=!1;try{await statSocketIdentity(socketPath)!==void 0&&(await rename3(socketPath,shieldPath),shielded=!0)}catch{}try{await close()}finally{if(shielded)try{await rename3(shieldPath,socketPath)}catch{}}}function delayUnrefed(ms){return new Promise(resolve2=>{setTimeout(resolve2,ms).unref?.()})}function errorMessage2(cause){return cause instanceof Error?cause.message:String(cause)}function isNodeErrorCode3(cause,code){return cause instanceof Error&&"code"in cause&&cause.code===code}var SUPERSESSION_POLL_MS=1e3,ABSENT_CONFIRMATIONS=3;function watchForSupersession(endpoint,onLost){if(endpoint.identity===void 0||process.platform==="win32")return()=>{};let absentPolls=0,lost=!1,lose=loss=>{lost||(lost=!0,stop(),onLost(loss))},timer=setInterval(()=>{endpoint.settled?.()!==!0&&classifyEndpointOwnership(endpoint.path,endpoint.identity).then(ownership=>{if(endpoint.settled?.()!==!0)switch(ownership){case"replaced":lose("replaced");return;case"absent":if(absentPolls+=1,absentPolls<ABSENT_CONFIRMATIONS)return;lose("absent");return;case"held":case"unknown":absentPolls=0;return}},ignore)},SUPERSESSION_POLL_MS);timer.unref?.();let stop=()=>clearInterval(timer);return stop}function ignore(){}import{rmSync}from"node:fs";import{rm as rm4}from"node:fs/promises";import{Socket}from"node:net";var HOST_WATCH_FD_ENV="SENPI_RPC_HOST_WATCH_FD",HOST_SCRATCH_DIR_ENV="SENPI_RPC_HOST_SCRATCH_DIR",HOST_PUBLIC_SOCKET_ENV="SENPI_RPC_HOST_PUBLIC_SOCKET",HOST_WATCH_PPID_ENV="SENPI_RPC_HOST_WATCH_PPID",HOST_WATCH_PPID_INTERVAL_MS=250,HOST_CLEANUP_PATHS_ENV="SENPI_RPC_HOST_CLEANUP_PATHS";function parsePositiveInteger(value){if(value===void 0||!/^\d+$/.test(value.trim()))return;let parsed=Number(value.trim());return Number.isSafeInteger(parsed)&&parsed>0?parsed:void 0}function readHostWatchdogConfig(env=process.env){let fd=parsePositiveInteger(env[HOST_WATCH_FD_ENV]),ppid=parsePositiveInteger(env[HOST_WATCH_PPID_ENV]);if(fd===void 0&&ppid===void 0)return;let scratchDir=env[HOST_SCRATCH_DIR_ENV],cleanupPaths=env[HOST_CLEANUP_PATHS_ENV]?.split(`
|
|
12
|
+
`).filter(Boolean),publicSocket=env[HOST_PUBLIC_SOCKET_ENV];return{fd,ppid,scratchDir:scratchDir===void 0||scratchDir===""?void 0:scratchDir,cleanupPaths,publicSocket:publicSocket===""?void 0:publicSocket}}function readHostWatchdogConfigFromBrandEnv(){return readHostWatchdogConfig({[HOST_WATCH_FD_ENV]:process.env[HOST_WATCH_FD_ENV]??envValue("RPC_HOST_WATCH_FD"),[HOST_WATCH_PPID_ENV]:process.env[HOST_WATCH_PPID_ENV]??envValue("RPC_HOST_WATCH_PPID"),[HOST_SCRATCH_DIR_ENV]:process.env[HOST_SCRATCH_DIR_ENV]??envValue("RPC_HOST_SCRATCH_DIR"),[HOST_PUBLIC_SOCKET_ENV]:process.env[HOST_PUBLIC_SOCKET_ENV]??envValue("RPC_HOST_PUBLIC_SOCKET"),[HOST_CLEANUP_PATHS_ENV]:process.env[HOST_CLEANUP_PATHS_ENV]??envValue("RPC_HOST_CLEANUP_PATHS")})}function armHostWatchdog(config,onSupervisorGone){if(!config)return()=>{};let fire=reason=>{disarm();let captured=captureBeforeCleanup(config);if(process.platform==="win32"){let cleanup=captured.then(()=>cleanupWatchdogPaths(config));onSupervisorGone(reason,cleanup)}else captured.then(()=>cleanupWatchdogPaths(config)).finally(()=>onSupervisorGone(reason))},disarmers=[],disarm=()=>{for(let stop of disarmers.splice(0))stop()};return config.fd!==void 0&&disarmers.push(watchFdForEof(config.fd,fire)),config.ppid!==void 0&&disarmers.push(watchPpid(config.ppid,fire)),disarm}function watchFdForEof(fd,fire){let stream,streamFailed=!1,fired=!1,fireOnce=reason=>{fired||(fired=!0,fire(reason))};try{stream=new Socket({fd,readable:!0,writable:!1})}catch{return()=>{}}stream.resume();let onEnd=()=>fireOnce(`supervisor pipe fd ${fd} closed`),onClose=()=>{streamFailed||onEnd()},onError=()=>{streamFailed=!0};return stream.once("end",onEnd),process.platform==="win32"&&stream.once("close",onClose),stream.once("error",onError),()=>{stream.off("end",onEnd),stream.off("close",onClose),stream.off("error",onError),stream.destroy()}}function watchPpid(supervisorPid,fire){if(supervisorPid===process.pid)return()=>{};let timer=setInterval(()=>{if(!processAlive(supervisorPid)){fire(`supervisor pid ${supervisorPid} is gone (ppid=${process.ppid})`);return}process.ppid!==supervisorPid&&fire(`supervisor pid ${supervisorPid} is gone (ppid=${process.ppid})`)},HOST_WATCH_PPID_INTERVAL_MS);return timer.unref?.(),()=>clearInterval(timer)}function processAlive(pid){try{return process.kill(pid,0),!0}catch(cause){return cause instanceof Error&&"code"in cause&&cause.code!=="ESRCH"}}function captureBeforeCleanup(config){return config.beforeCleanup===void 0?Promise.resolve():Promise.resolve().then(config.beforeCleanup).catch(()=>{})}async function cleanupWatchdogPaths(config){let paths=[...config.cleanupPaths??[],...config.scratchDir?[config.scratchDir]:[]];if(process.platform==="win32"){for(let path of paths)try{rmSync(path,{recursive:!0,force:!0,maxRetries:10,retryDelay:100})}catch{}return}await Promise.all(paths.map(async path=>{try{await rm4(path,{recursive:!0,force:!0})}catch{}}))}function activeTurnsForIdleDecision(input){return input.healthy?input.observedBusy:input.unhealthySince===void 0||input.now-input.unhealthySince<input.unknownGraceMs?1:0}function createObserverLink(options){let current,healthy=!1,unhealthySince,retry,armRetry=()=>{retry!==void 0||options.settled()||(retry=options.setTimer(()=>{retry=void 0,open().catch(armRetry)},options.retryDelayMs))};async function open(){let socket=await options.open();current=socket,healthy=!0,unhealthySince=void 0,socket.onLost(()=>{current!==socket||options.settled()||(healthy=!1,unhealthySince??=options.now(),current=void 0,armRetry())})}return{open,healthy:()=>healthy,unhealthySince:()=>unhealthySince,stop:()=>{retry?.cancel(),retry=void 0,current=void 0}}}import{createHash as createHash3,randomBytes,timingSafeEqual}from"node:crypto";import{chmod as chmod2,mkdir as mkdir4,readFile as readFile4,writeFile as writeFile5}from"node:fs/promises";import{dirname as dirname2,win32 as win322}from"node:path";var WINDOWS_PIPE_PREFIX="\\\\.\\pipe\\senpi-rpc-",SOCKET_SECRET_BYTES=32,SOCKET_SECRET_SUFFIX=".secret",SOCKET_SECRET_FILE_ENV="SENPI_RPC_SOCKET_SECRET_FILE",SOCKET_HANDSHAKE_TIMEOUT_MS=2e3;function socketSecretPath(logicalPath){if(logicalPath.toLowerCase().startsWith("\\\\.\\pipe\\"))throw new Error(`Windows RPC named-pipe addresses need a logical filesystem path for their secret: ${logicalPath}`);return`${logicalPath}${SOCKET_SECRET_SUFFIX}`}async function ensureSocketSecret(path){try{let existing=await readFile4(path);if(existing.length===SOCKET_SECRET_BYTES)return existing}catch(error){if(!isNodeErrorCode4(error,"ENOENT"))throw error}return createSocketSecret(path)}async function createSocketSecret(path){await mkdir4(dirname2(path),{recursive:!0});let secret=randomBytes(SOCKET_SECRET_BYTES);return await writeFile5(path,secret,{mode:384}),await chmod2(path,384),secret}async function readSocketSecret(path){let secret=await readFile4(path);if(secret.length!==SOCKET_SECRET_BYTES)throw new Error(`invalid RPC socket secret: ${path}`);return secret}function resolveSocketTransportAddress(socketPath,platform,secret){if(platform!=="win32"||socketPath.toLowerCase().startsWith("\\\\.\\pipe\\"))return socketPath;if(!/^[a-zA-Z]:[\\/]/.test(socketPath)&&!/^\\\\[^/]/.test(socketPath))throw new Error(`Windows RPC socket path must be drive-qualified or UNC: ${socketPath}`);let canonical=win322.normalize(socketPath).toLowerCase(),identity=Buffer.concat([Buffer.from(canonical,"utf8"),Buffer.from(secret??[])]),name=createHash3("sha256").update(identity).digest("hex").slice(0,32);return`${WINDOWS_PIPE_PREFIX}${name}`}function authenticateSocket(socket,secret,onAuthenticated){let received=Buffer.alloc(0),finish=()=>{clearTimeout(timer),socket.off("data",onData),socket.off("error",onError)},onError=()=>{finish(),socket.destroy()},timer=setTimeout(()=>{finish(),socket.destroy()},SOCKET_HANDSHAKE_TIMEOUT_MS),onData=chunk=>{if(received=Buffer.concat([received,chunk]),received.length<secret.length)return;if(finish(),!timingSafeEqual(received.subarray(0,secret.length),Buffer.from(secret))){socket.destroy();return}let remainder=received.subarray(secret.length);remainder.length>0&&socket.unshift(remainder),onAuthenticated()};socket.on("data",onData),socket.once("error",onError),socket.once("close",finish)}function sendSocketHandshake(socket,secret){socket.write(Buffer.from(secret))}function isNodeErrorCode4(error,code){return error instanceof Error&&"code"in error&&error.code===code}var HOST_COLD_START_ENV="SENPI_RPC_HOST_COLD_START",HOST_IDLE_EXIT_MS_ENV="SENPI_RPC_HOST_IDLE_EXIT_MS",DEFAULT_HOST_IDLE_EXIT_MS=15*6e4,HANDOFF_GRACE_MS_ENV="SENPI_RPC_HANDOFF_GRACE_MS",DEFAULT_HANDOFF_GRACE_MS=10*6e4,CHILD_STOP_TIMEOUT_MS=5e3,WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS=2e3,CHILD_WATCH_FD=3;async function createInternalSocketPath(baseDir=tmpdir(),platform=process.platform){if(platform==="win32"){let dir2=join4(baseDir,`internal-${randomUUID()}`);return await mkdir5(dir2,{recursive:!0,mode:448}),{socket:`\\\\.\\pipe\\senpi-rpc-internal-${randomUUID()}`,dir:dir2,secretPath:join4(dir2,"secret")}}let dir=join4(tmpdir(),`senpi-rpc-host-internal-${randomUUID().slice(0,8)}`);return await mkdir5(dir,{recursive:!1,mode:448}),await writeFile6(join4(dir,".owner"),JSON.stringify({pid:process.pid,processStartTime:await readProcessStartTime(process.pid),createdAt:Date.now()}),{mode:384}),{socket:join4(dir,"host.sock"),dir,secretPath:join4(dir,".secret")}}function parseColdStart(value){return value==="transient"||value==="persistent"?value:void 0}function parseIdleExitMs(value){if(value===void 0||!/^\d+$/.test(value.trim()))return;let parsed=Number(value.trim());return Number.isFinite(parsed)&&parsed>0?parsed:void 0}function resolveHostPolicy(settings,env){let record=isRecord3(settings)?settings:{},coldStart=parseColdStart(env[HOST_COLD_START_ENV])??parseColdStart(asOptionalString(record.coldStart))??"transient",idleExitMs=parseIdleExitMs(env[HOST_IDLE_EXIT_MS_ENV])??parseIdleExitMs(asOptionalString(record.idleExitMs))??DEFAULT_HOST_IDLE_EXIT_MS;return{coldStart,idleExitMs}}var IdleExitDecider=class{constructor(idleExitMs,now=Date.now){this.idleExitMs=idleExitMs,this.now=now}update(activity){return activity.connections>0||activity.activeTurns>0?(this.idleSince=void 0,"active"):this.idleExitMs===Number.POSITIVE_INFINITY?"idle":this.idleSince===void 0?(this.idleSince=this.now(),"idle"):this.now()-this.idleSince>=this.idleExitMs?"exit":"idle"}},INTERNAL_SUPERVISOR_FLAG="--internal-rpc-host-supervisor",INJECTABLE_PREFIX_FLAGS=new Set(["--extension"]);function findInternalSupervisorArgs(argv){for(let index=0;index<argv.length;index++){let arg=argv[index];if(arg===INTERNAL_SUPERVISOR_FLAG)return argv.slice(index+1);if(!INJECTABLE_PREFIX_FLAGS.has(arg)||index+1>=argv.length)return;index++}}function parseSupervisorArgs(argv){let hostArgs=[],socket,childCommand,childArgs,agentDir,bindSocket,replaceIdentity;for(let index=0;index<argv.length;index++){let arg=argv[index];if(arg==="--socket"&&index+1<argv.length){socket=argv[++index];continue}if(arg==="--child-command"&&index+1<argv.length){childCommand=argv[++index];continue}if(arg==="--child-args"&&index+1<argv.length){try{let parsed=JSON.parse(argv[++index]);Array.isArray(parsed)&&parsed.every(value=>typeof value=="string")&&(childArgs=parsed)}catch{return}continue}if(arg==="--agent-dir"&&index+1<argv.length){agentDir=argv[++index];continue}if(arg==="--bind"&&index+1<argv.length){bindSocket=argv[++index];continue}if(arg==="--replace"&&index+1<argv.length){replaceIdentity=parseSocketIdentity(argv[++index]);continue}hostArgs.push(arg)}return socket===void 0?void 0:{socket,hostArgs,childCommand,childArgs,agentDir,bindSocket,replaceIdentity}}function parseSocketIdentity(value){let match=/^(\d+):(\d+)$/.exec(value);return match?{dev:Number(match[1]),ino:Number(match[2])}:void 0}function resolveCliMainPath(){let modulePath=fileURLToPath(import.meta.url),extension=modulePath.endsWith(".ts")?".ts":".js",unbundled=resolve(dirname3(modulePath),"..","..",`cli-main${extension}`);return existsSync(unbundled)?unbundled:resolveDeclaredCliEntry(modulePath)??unbundled}function resolveDeclaredCliEntry(modulePath){let dir=dirname3(modulePath);for(let depth=0;depth<8;depth+=1){let manifestPath=resolve(dir,"package.json");if(existsSync(manifestPath)){try{let declared=JSON.parse(readFileSync2(manifestPath,"utf8")).bin,candidates=typeof declared=="string"?[declared]:Object.values(declared??{});for(let candidate of candidates){let entry=resolve(dir,candidate);if(existsSync(entry))return entry}}catch{}return}let parent=dirname3(dir);if(parent===dir)return;dir=parent}}function resolveHostChildLaunch(launch,internalSocket,compiled=isBunBinary){return launch.childCommand?{command:launch.childCommand,args:[...launch.childArgs??[],"--listen",`unix://${internalSocket}`]}:{command:process.execPath,args:[...compiled?[]:[...process.execArgv,resolveCliMainPath()],"--mode","rpc","--multi-session","--listen",`unix://${internalSocket}`,...launch.hostArgs]}}function quoteWindowsShellArg(value){return`"${value.replace(/(\\*)"/g,'$1$1\\"').replace(/(\\*)$/,"$1$1").replace(/([()%!^"<>&|;,])/g,"^$1")}"`}function spawnableChildLaunch(launch,platform=process.platform){let extension=extname(launch.command).toLowerCase();return platform!=="win32"||extension!==".cmd"&&extension!==".bat"?{...launch,shell:!1}:{command:quoteWindowsShellArg(launch.command),args:launch.args.map(quoteWindowsShellArg),shell:!0}}async function runHostSupervisor(launch){let paths=createHostDaemonPaths({socket:launch.socket,agentDir:launch.agentDir??getAgentDir()}),told=process.env[HOST_INSTANCE_ID_ENV],instanceId=told!==void 0&&told.trim()!==""?told:randomUUID(),generation=generationPaths(paths,instanceId),policy=resolveHostPolicy(await readSettingsFile(paths.settingsFile),process.env),publicSocket=launch.socket,bindSocket=launch.bindSocket??publicSocket,successor=launch.bindSocket!==void 0,publicSecret=process.platform==="win32"?await ensurePublicSocketSecret(publicSocket):void 0,internal=await createInternalSocketPath(paths.dir),internalSocket=internal.socket,internalSecretPath=internal.secretPath??socketSecretPath(internalSocket),internalSecret=process.platform==="win32"?await createSocketSecret(internalSecretPath):void 0,clientSockets=new Set,busySessions=new Map,observerSocket,observerLink=createObserverLink({open:async()=>{let secret=internalSecret,next=createConnection(resolveSocketTransportAddress(internalSocket,process.platform,secret));return secret&&sendSocketHandshake(next,secret),await waitForConnect(next,5e3),observerSocket=next,attachJsonlLineReader(next,observeHostEvent,{maxLineLength:MAX_RPC_LINE_CHARACTERS}),{onLost:handler=>{next.once("close",handler),next.once("error",handler)}}},settled:()=>shuttingDown,retryDelayMs:250,now:Date.now,setTimer:(run2,ms)=>{let timer=setTimeout(run2,ms);return timer.unref?.(),{cancel:()=>clearTimeout(timer)}}}),childExitWatchTimer,stopSupersessionWatch,shuttingDown=!1,draining=!1,handoffGraceTimer,shutdownPromise,childLaunch=spawnableChildLaunch(resolveHostChildLaunch(launch,internalSocket)),child=spawn(childLaunch.command,childLaunch.args,{env:{...process.env,...launch.agentDir?{SENPI_CODING_AGENT_DIR:launch.agentDir}:{},[HOST_DAEMON_DIR_ENV]:paths.dir,[HOST_INSTANCE_ID_ENV]:instanceId,[HOST_WATCH_FD_ENV]:String(CHILD_WATCH_FD),[HOST_WATCH_PPID_ENV]:String(process.pid),...internal.dir?{[HOST_SCRATCH_DIR_ENV]:internal.dir}:{},...internalSecret?{[SOCKET_SECRET_FILE_ENV]:internalSecretPath}:{},[HOST_CLEANUP_PATHS_ENV]:[...successor?[]:[paths.pointerFile,generation.pidFile,paths.settingsFile],...process.platform==="win32"?[publicSocket]:[]].join(`
|
|
13
|
+
`),...process.platform==="win32"?{}:{[HOST_PUBLIC_SOCKET_ENV]:publicSocket}},shell:childLaunch.shell,stdio:["ignore","ignore","inherit","pipe"],windowsHide:!0}),childStartedAt=Date.now();child.stdio[CHILD_WATCH_FD]?.on("error",()=>{}),child.once("exit",(code,signal)=>{if(shuttingDown)return;let{reason,exitCode}=classifyChildExit(code,signal);noteChildExit(paths.dir,code,signal,childStartedAt),shutdown(reason,exitCode)});let server=createServer(client=>{let accept=()=>{if(shuttingDown||draining){client.destroy();return}let internal2=createConnection(resolveSocketTransportAddress(internalSocket,process.platform,internalSecret));internalSecret&&sendSocketHandshake(internal2,internalSecret),clientSockets.add(client),decider.update(currentActivity());let detach=()=>{clientSockets.delete(client),decider.update(currentActivity()),internal2.destroy(),client.destroy()};client.pipe(internal2),internal2.pipe(client),client.once("close",detach),client.once("error",detach),internal2.once("end",()=>client.end(()=>client.destroy())),internal2.once("close",()=>{internal2.readableEnded||detach()}),internal2.once("error",detach)};publicSecret?authenticateSocket(client,publicSecret,accept):accept()});server.once("error",cause=>{shuttingDown||shutdown(`public socket listener failed: ${errorMessage3(cause)}`,1)});let decider=new IdleExitDecider(policy.coldStart==="persistent"?Number.POSITIVE_INFINITY:policy.idleExitMs),tickIntervalMs=Math.max(20,Math.min(1e3,policy.idleExitMs/4)),ticker=setInterval(()=>{!draining&&decider.update(currentActivity())==="exit"&&shutdown("idle",0)},tickIntervalMs);function currentActivity(){return{connections:clientSockets.size,activeTurns:activeTurnsForIdleDecision({healthy:observerLink.healthy(),unhealthySince:observerLink.unhealthySince(),now:Date.now(),unknownGraceMs:decider.idleExitMs,observedBusy:countBusySessions()})}}function countBusySessions(){let busy=0;for(let count of busySessions.values())count>0&&busy++;return busy}function observeHostEvent(line){let event;try{event=JSON.parse(line)}catch{return}if(typeof event!="object"||event===null)return;let{type,sessionId}=event;if(typeof sessionId=="string"){if(type==="agent_start")busySessions.set(sessionId,(busySessions.get(sessionId)??0)+1);else if(type==="agent_settled")busySessions.set(sessionId,Math.max(0,(busySessions.get(sessionId)??1)-1));else return;decider.update(currentActivity())}}async function shutdown(reason,exitCode){return shutdownPromise??=performShutdown(reason,exitCode),shutdownPromise}async function performShutdown(reason,exitCode){shuttingDown&&process.exit(exitCode),shuttingDown=!0,clearInterval(ticker),handoffGraceTimer&&clearTimeout(handoffGraceTimer),childExitWatchTimer&&clearInterval(childExitWatchTimer),stopSupersessionWatch?.();let hardExit=process.platform==="win32"?setTimeout(()=>process.exit(exitCode),WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS):void 0;try{writeStderrLine(`senpi rpc host supervisor: ${reason} shutdown`);for(let client of clientSockets)client.destroy();draining||await shieldSocketDuringClose(publicSocket,()=>closeServer(server)),internal.dir&&await rm5(internal.dir,{recursive:!0,force:!0}),await stopChild(child),observerLink.stop(),observerSocket?.destroy(),publicSocketOwned&&process.platform!=="win32"&&await unlinkOwnedSocket(publicSocket,publicSocketIdentity,supervisorLog),await releaseGeneration(paths,{instanceId,pid:process.pid})}finally{hardExit&&clearTimeout(hardExit),process.exit(exitCode)}}let publicSocketOwned=!1,publicSocketIdentity;function supervisorLog(message){writeStderrLine(`senpi rpc host supervisor: ${message}`)}function drainForHandoff(){if(draining||shuttingDown)return;draining=!0,supervisorLog("draining into the next generation");let graceMs=parseIdleExitMs(process.env[HANDOFF_GRACE_MS_ENV])??DEFAULT_HANDOFF_GRACE_MS;handoffGraceTimer=setTimeout(()=>{supervisorLog(JSON.stringify({event:"handoff_grace_expired",graceMs})),requestChildDrain()},graceMs),handoffGraceTimer.unref(),requestChildDrain()}function requestChildDrain(){if(child.pid!==void 0&&child.exitCode===null&&child.signalCode===null)try{process.kill(child.pid,"SIGUSR1")}catch(cause){supervisorLog(`could not ask the host to drain: ${errorMessage3(cause)}`)}}registerSupervisorSignals(shutdown,drainForHandoff);try{await waitForListener(internalSocket,3e4,internalSecret),await observerLink.open(),await prepareSocketPath(bindSocket),await listen(server,bindSocket,publicSecret),publicSocketOwned=!0,successor&&await adoptPublicSocket(bindSocket,publicSocket,launch.replaceIdentity),publicSocketIdentity=await statSocketIdentity(publicSocket),publicSocketIdentity&&internal.dir&&await writeSocketIdentityFile(join4(internal.dir,PUBLIC_SOCKET_IDENTITY_FILE),publicSocketIdentity),stopSupersessionWatch=watchForSupersession({path:publicSocket,identity:publicSocketIdentity,settled:()=>shuttingDown||draining},loss=>{supervisorLog(loss==="absent"?"the public socket entry is gone; nothing can reach this generation; draining":"another generation owns the public socket; draining this one"),drainForHandoff()})}catch(cause){await shutdown(`startup failed: ${errorMessage3(cause)}`,1)}if(process.platform==="win32"&&child.pid!==void 0){let childStartTime=await readProcessStartTime(child.pid,process.platform,1e3).catch(()=>{}),missingIdentityChecks=0,checkingChildIdentity=!1;childExitWatchTimer=setInterval(()=>{shuttingDown||checkingChildIdentity||child.exitCode!==null||child.signalCode!==null||(checkingChildIdentity=!0,readProcessStartTime(child.pid,process.platform,1e3).then(currentStartTime=>{currentStartTime===void 0&&!processIsLive(child.pid)?missingIdentityChecks++:currentStartTime!==void 0&&(missingIdentityChecks=0),(childStartTime!==void 0&¤tStartTime!==void 0&¤tStartTime!==childStartTime||missingIdentityChecks>=2)&&shutdown("rpc host child exit observed by identity watchdog",0)}).catch(()=>{}).finally(()=>{checkingChildIdentity=!1}))},500),childExitWatchTimer.unref?.()}writeStderrLine(`senpi rpc host ready on unix://${publicSocket} (coldStart=${policy.coldStart}, idleExitMs=${policy.coldStart==="persistent"?"never":String(policy.idleExitMs)})`),await new Promise(()=>{})}function registerSupervisorSignals(shutdown,drain){for(let signal of process.platform==="win32"?["SIGTERM"]:["SIGTERM","SIGHUP"])process.on(signal,()=>{shutdown(`signal:${signal}`,signal==="SIGHUP"?129:143)});process.platform!=="win32"&&process.on("SIGUSR1",drain)}async function adoptPublicSocket(bindSocket,publicSocket,expected){if(expected===void 0)throw new Error(`${publicSocket}: a generation launch must name the entry it replaces`);let current=await statSocketIdentity(publicSocket);if(current===void 0||current.dev!==expected.dev||current.ino!==expected.ino)throw new Error(`${publicSocket}: owned by another socket entry now; refusing to replace it`);await rename4(bindSocket,publicSocket)}async function ensurePublicSocketSecret(publicSocket){let secretPath=socketSecretPath(publicSocket);try{return await ensureSocketSecret(secretPath)}catch(cause){throw new Error(`senpi rpc host supervisor: cannot provision public socket secret ${secretPath}`,{cause})}}async function readSettingsFile(settingsFile){try{return JSON.parse(await readFile5(settingsFile,"utf8"))}catch{return}}async function stopChild(child){if(!(child.exitCode!==null||child.signalCode!==null)){try{child.kill("SIGTERM")}catch{return}if(!await waitForChildExit(child,CHILD_STOP_TIMEOUT_MS)){try{child.kill("SIGKILL")}catch{return}await waitForChildExit(child,2e3)}}}function waitForChildExit(child,timeoutMs){return child.exitCode!==null||child.signalCode!==null?Promise.resolve(!0):new Promise(resolve2=>{let timer=setTimeout(()=>{child.off("exit",onExit),resolve2(!1)},timeoutMs),onExit=()=>{clearTimeout(timer),resolve2(!0)};child.once("exit",onExit)})}async function waitForListener(socketPath,timeoutMs,secret){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(await canConnect(socketPath,secret))return;await delay2(50)}throw new Error(`${socketPath}: host did not start listening within ${timeoutMs}ms`)}function canConnect(socketPath,secret){return new Promise(resolve2=>{let socket=createConnection(resolveSocketTransportAddress(socketPath,process.platform,secret));secret&&sendSocketHandshake(socket,secret);let settle=value=>{socket.destroy(),resolve2(value)};socket.once("connect",()=>settle(!0)),socket.once("error",()=>settle(!1))})}function waitForConnect(socket,timeoutMs){return new Promise((resolve2,reject)=>{let timer=setTimeout(()=>{cleanup(),reject(new Error(`observer connection to internal host timed out after ${timeoutMs}ms`))},timeoutMs),onConnect=()=>{cleanup(),resolve2()},onError=cause=>{cleanup(),reject(cause)},cleanup=()=>{clearTimeout(timer),socket.off("connect",onConnect),socket.off("error",onError)};socket.once("connect",onConnect),socket.once("error",onError)})}async function prepareSocketPath(socketPath){if(process.platform!=="win32"){if(Buffer.byteLength(socketPath)>MAX_SOCKET_PATH_BYTES)throw new Error(`${socketPath}: socket path is ${Buffer.byteLength(socketPath)} bytes, over the ${MAX_SOCKET_PATH_BYTES}-byte limit.`);await mkdir5(dirname3(socketPath),{recursive:!0,mode:448});try{await access(socketPath)}catch(cause){if(isNodeErrorCode5(cause,"ENOENT"))return;throw cause}if(await canConnect(socketPath))throw new Error(`${socketPath}: address already in use by a live server.`);await unlink2(socketPath)}}function listen(server,socketPath,secret){return new Promise((resolve2,reject)=>{server.once("error",reject),server.listen({path:resolveSocketTransportAddress(socketPath,process.platform,secret),readableAll:!1,writableAll:!1},async()=>{server.off("error",reject);try{process.platform!=="win32"&&!socketPath.startsWith("\0")&&await chmod3(socketPath,384),resolve2()}catch(cause){reject(cause)}})})}function closeServer(server){return new Promise(resolve2=>{server.close(()=>resolve2())})}function writeStderrLine(text){try{writeSync(2,`${text}
|
|
14
|
+
`)}catch{}}function delay2(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function errorMessage3(cause){return cause instanceof Error?cause.message:String(cause)}function isNodeErrorCode5(cause,code){return cause instanceof Error&&"code"in cause&&cause.code===code}function isRecord3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function asOptionalString(value){return typeof value=="string"?value:typeof value=="number"?String(value):void 0}function isEntryScript(){let entry=process.argv[1];if(!entry)return!1;try{return fileURLToPath(import.meta.url)===realpathSync(entry)}catch{return!1}}if(!isBundledNode&&isEntryScript()){let launch=parseSupervisorArgs(process.argv.slice(2));launch||(writeStderrLine("usage: host-lifecycle.ts --socket <path> [host cli args...]"),process.exit(2)),runHostSupervisor(launch)}export{HOST_DAEMON_DIR_ENV,createHostDaemonPaths,createDaemonDirectories,writeHostSettings,readHostSettings,writeStateFile,readFileOrUndefined,parseJson,parseDaemonPidFile,ProcessIdentityUnreadableError,processMatchesPidFile,stopValidatedPid,waitForGone,readProcessStartTime,processIsLive,waitForStartTime,readHostProcessMetrics,SESSION_PATH_RETRY_AFTER_MS,createEndpointReservations,pruneDeadGenerations,readGenerationRows,readHostRegistration,writeHostRegistration,clearHostRegistration,releaseGeneration,provenOwner,legacyHostIsLive,writtenByThisProcess,SOCKET_SECRET_FILE_ENV,socketSecretPath,ensureSocketSecret,createSocketSecret,readSocketSecret,resolveSocketTransportAddress,authenticateSocket,sendSocketHandshake,classifyChildExit,PUBLIC_SOCKET_IDENTITY_FILE,MAX_SOCKET_PATH_BYTES,generationBindPath,statSocketIdentity,socketEntryReplaced,readSocketIdentityFile,waitForSocketIdentityFile,unlinkOwnedSocket,shieldSocketDuringClose,readHostWatchdogConfigFromBrandEnv,armHostWatchdog,HOST_COLD_START_ENV,HOST_IDLE_EXIT_MS_ENV,DEFAULT_HOST_IDLE_EXIT_MS,HANDOFF_GRACE_MS_ENV,DEFAULT_HANDOFF_GRACE_MS,createInternalSocketPath,parseColdStart,parseIdleExitMs,resolveHostPolicy,IdleExitDecider,INTERNAL_SUPERVISOR_FLAG,findInternalSupervisorArgs,parseSupervisorArgs,resolveCliMainPath,resolveHostChildLaunch,spawnableChildLaunch,runHostSupervisor};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{estimateContextTokens}from"./chunk-
|
|
2
|
+
import{estimateContextTokens}from"./chunk-NMB4C6ZZ.js";var CONTEXT_SAFETY_TOKENS=4096,MIN_ANSWER_TOKENS=1024,MIN_MAX_TOKENS=1,CONTEXT_GUARD_MIN_WINDOW=CONTEXT_SAFETY_TOKENS+MIN_ANSWER_TOKENS,ContextWindowExhaustedError=class extends Error{constructor(estimatedTokens,contextWindow){super(`Context window exhausted: the conversation is estimated at ${estimatedTokens} of ${contextWindow} tokens, leaving fewer than ${MIN_ANSWER_TOKENS} tokens for a response. Compact the conversation, enable auto-compaction, or start a new session before retrying.`),this.name="ContextWindowExhaustedError",this.estimatedTokens=estimatedTokens,this.contextWindow=contextWindow}};function clampMaxTokensToContext(model,context,maxTokens){if(model.contextWindow<=0)return Number.isFinite(maxTokens)&&maxTokens>0?Math.max(MIN_MAX_TOKENS,Math.floor(maxTokens)):MIN_MAX_TOKENS;let estimatedTokens=estimateContextTokens(context).tokens,available=model.contextWindow-estimatedTokens-CONTEXT_SAFETY_TOKENS;if(model.contextWindow>=CONTEXT_GUARD_MIN_WINDOW&&available<MIN_ANSWER_TOKENS)throw new ContextWindowExhaustedError(estimatedTokens,model.contextWindow);let safeAvailable=Math.max(MIN_MAX_TOKENS,available),requested=Number.isFinite(maxTokens)&&maxTokens>0?Math.floor(maxTokens):safeAvailable;return Math.min(requested,safeAvailable)}function applyExtraBody(target,extraBody,reservedKeys){if(extraBody)for(let[key,value]of Object.entries(extraBody))reservedKeys.has(key)||Reflect.set(target,key,value)}var OPENAI_COMPLETIONS_RESERVED_BODY_KEYS=new Set(["model","messages","stream","stream_options","tools","tool_choice","store","temperature","max_tokens","max_completion_tokens","reasoning_effort","reasoning","thinking","enable_thinking","chat_template_kwargs","tool_stream","provider","providerOptions"]),OPENAI_RESPONSES_RESERVED_BODY_KEYS=new Set(["model","input","instructions","stream","tools","tool_choice","parallel_tool_calls","reasoning","max_output_tokens","temperature","text","store","include","prompt_cache_key","prompt_cache_retention","service_tier"]),GOOGLE_RESERVED_BODY_KEYS=new Set(["systemInstruction","tools","toolConfig","temperature","maxOutputTokens","thinkingConfig","responseMimeType","responseSchema","cachedContent","abortSignal","httpOptions"]),ANTHROPIC_RESERVED_BODY_KEYS=new Set(["model","messages","system","stream","tools","tool_choice","temperature","max_tokens","thinking","output_config","metadata"]),MISTRAL_RESERVED_BODY_KEYS=new Set(["model","messages","stream","tools","toolChoice","temperature","maxTokens","promptMode"]);function buildBaseOptions(model,context,options,apiKey){let samplingParams=model.samplingParams||options?.samplingParams?{...model.samplingParams,...options?.samplingParams}:void 0;return{temperature:options?.temperature,samplingParams,maxTokens:clampMaxTokensToContext(model,context,options?.maxTokens??model.maxTokens),signal:options?.signal,abortServerSideFallback:options?.abortServerSideFallback,telemetryContext:options?.telemetryContext,apiKey:apiKey||options?.apiKey,fetch:options?.fetch,transport:options?.transport,cacheRetention:options?.cacheRetention??model.cacheRetention,sessionId:options?.sessionId,headers:options?.headers,extraBody:options?.extraBody,onPayload:options?.onPayload,onResponse:options?.onResponse,timeoutMs:options?.timeoutMs,websocketConnectTimeoutMs:options?.websocketConnectTimeoutMs,maxRetries:options?.maxRetries,maxRetryDelayMs:options?.maxRetryDelayMs,metadata:options?.metadata,env:options?.env}}var DEFAULT_THINKING_BUDGETS={minimal:1024,low:2048,medium:8192,high:16384};function clampReasoning(effort){return effort==="xhigh"||effort==="max"?"high":effort}function clampMaxForOpenAI(effort,xhighSupported){return effort==="max"?xhighSupported?"xhigh":"high":effort}function thinkingBudgetForLevel(reasoningLevel,customBudgets){let budgets={...DEFAULT_THINKING_BUDGETS,...customBudgets},level=clampReasoning(reasoningLevel);return budgets[level]}function clampThinkingBudgetToAnswerRoom(thinkingBudget,ceiling){return Math.min(thinkingBudget,Math.max(0,ceiling-MIN_ANSWER_TOKENS))}function adjustMaxTokensForThinking(baseMaxTokens,modelMaxTokens,reasoningLevel,customBudgets){let level=clampReasoning(reasoningLevel);if(!level)return{maxTokens:baseMaxTokens??modelMaxTokens,thinkingBudget:0};let thinkingBudget=thinkingBudgetForLevel(level,customBudgets),maxTokens=baseMaxTokens===void 0?modelMaxTokens:Math.min(baseMaxTokens+thinkingBudget,modelMaxTokens);return maxTokens<=thinkingBudget&&(thinkingBudget=clampThinkingBudgetToAnswerRoom(thinkingBudget,maxTokens)),{maxTokens,thinkingBudget}}export{clampMaxTokensToContext,applyExtraBody,OPENAI_COMPLETIONS_RESERVED_BODY_KEYS,OPENAI_RESPONSES_RESERVED_BODY_KEYS,GOOGLE_RESERVED_BODY_KEYS,ANTHROPIC_RESERVED_BODY_KEYS,MISTRAL_RESERVED_BODY_KEYS,buildBaseOptions,clampMaxForOpenAI,thinkingBudgetForLevel,clampThinkingBudgetToAnswerRoom,adjustMaxTokensForThinking};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{contentText}from"./chunk-
|
|
2
|
+
import{contentText}from"./chunk-R6LVC7SP.js";var EDIT_CODES={empty:"empty","not-assistant":"not_assistant","not-found":"not_found","stale-leaf":"stale_leaf"},AssistantEditError=class extends Error{constructor(reason,message){super(message),this.name="AssistantEditError",this.reason=reason}get code(){return EDIT_CODES[this.reason]}},SessionStreamingError=class extends Error{constructor(){super("Wait for the current response to finish before navigating the session tree."),this.code="streaming",this.name="SessionStreamingError"}};function assertExpectedLeaf(expectedLeafId,currentLeafId){if(!(expectedLeafId===void 0||expectedLeafId===currentLeafId))throw new AssistantEditError("stale-leaf",`Session leaf moved (expected ${expectedLeafId}, now ${currentLeafId??"root"})`)}function assistantTextEquals(original,text){return contentText(original.content,"").trim()===text.trim()}function buildEditedAssistantMessage(original,text){let trimmed=text.trim();if(trimmed.length===0)throw new AssistantEditError("empty","Edited assistant response cannot be empty");return{role:"assistant",content:[{type:"text",text:trimmed}],api:original.api,provider:original.provider,model:original.model,...original.responseModel!==void 0?{responseModel:original.responseModel}:{},usage:original.usage,stopReason:"stop",timestamp:Date.now()}}var EDIT_CODES2={empty:"empty","not-user":"not_user","not-found":"not_found","stale-leaf":"stale_leaf"},UserEditError=class extends Error{constructor(reason,message){super(message),this.name="UserEditError",this.reason=reason}get code(){return EDIT_CODES2[this.reason]}};function assertExpectedUserLeaf(expectedLeafId,currentLeafId){if(!(expectedLeafId===void 0||expectedLeafId===currentLeafId))throw new UserEditError("stale-leaf",`Session leaf moved (expected ${expectedLeafId}, now ${currentLeafId??"root"})`)}function userTextEquals(original,text){return contentText(original.content,"").trim()===text.trim()}function buildEditedUserMessage(original,text){let trimmed=text.trim();if(trimmed.length===0)throw new UserEditError("empty","Edited user message cannot be empty");let attachments=Array.isArray(original.content)?original.content.filter(block=>block.type!=="text"):[];return{role:"user",content:[{type:"text",text:trimmed},...attachments],timestamp:Date.now()}}export{AssistantEditError,SessionStreamingError,assertExpectedLeaf,assistantTextEquals,buildEditedAssistantMessage,UserEditError,assertExpectedUserLeaf,userTextEquals,buildEditedUserMessage};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
+
import*as crypto from"node:crypto";var CUSTOM_UNSUPPORTED_CAPABILITY="custom_unsupported",EXTENSION_EVENTS_CAPABILITY="extension_events",RENDERED_COMPONENTS_CAPABILITY="rendered_components",AUTO_TITLE_SESSIONS_CAPABILITY="auto_title_sessions",MEDIA_PLACEHOLDERS_CAPABILITY="media_placeholders",QUESTION_CAPABILITY="question",RETAIN_ON_DISCONNECT_CAPABILITY="retain_on_disconnect",SESSION_CONTEXT_CAPABILITY="session_context",SESSION_KIND_CAPABILITY="session_kind",AUTO_TITLE_PER_SESSION_CAPABILITY="auto_title_per_session",DURABLE_SESSION_ID_CAPABILITY="durable_session_id",RPC_CLIENT_CAPABILITIES_ENV="SENPI_RPC_CLIENT_CAPABILITIES";function parseClientCapabilities(value){return value?value.split(",").map(part=>part.trim()).filter(part=>part.length>0):[]}var DEFAULT_CUSTOM_EXTENSION_LABEL="custom UI component";function buildCustomUnsupportedRequest(capabilities,extensionName){if(!capabilities?.includes(CUSTOM_UNSUPPORTED_CAPABILITY))return;let name=extensionName.trim()||DEFAULT_CUSTOM_EXTENSION_LABEL;return{type:"extension_ui_request",id:crypto.randomUUID(),method:"custom_unsupported",extensionName:name}}export{CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,RENDERED_COMPONENTS_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,QUESTION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,RPC_CLIENT_CAPABILITIES_ENV,parseClientCapabilities,DEFAULT_CUSTOM_EXTENSION_LABEL,buildCustomUnsupportedRequest};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{HOST_PROTOCOL_VERSION,HostEnsureRefusedError,REQUIRED_HOST_CAPABILITIES,decideHostAction,ensureHost,handoffHost,probeProtocolInfo,requestOnSocket,stopHost}from"./chunk-3SLCHXZO.js";import{createHostDaemonPaths,parseJson,pruneDeadGenerations,readFileOrUndefined,readGenerationRows,readHostProcessMetrics,writeStateFile}from"./chunk-IDTLJYJ5.js";import{engineBuildIdentity}from"./chunk-M2XAY6I7.js";import{isSessionRuntimeKind}from"./chunk-KICRBRVS.js";import{APP_NAME,envValue,getAgentDir}from"./chunk-Y65WFI5H.js";import{writeSync}from"node:fs";import{resolve as resolve2}from"node:path";import{readFile,realpath,stat}from"node:fs/promises";import{dirname,isAbsolute,relative,resolve}from"node:path";var SPEC_ENV_NAME=/^(SENPI|OMO|PI)_[A-Z0-9_]+$/u,HostLaunchSpecError=class extends Error{constructor(reason,detail){super(`${reason}: ${detail}`),this.name="HostLaunchSpecError",this.reason=reason,this.detail=detail}},DEFAULT_HOST_LAUNCH_SPEC={hostArgs:[],policy:{},env:{}};async function loadHostLaunchSpec(specPath,platform=process.platform){let absolute=resolve(specPath);await assertTrustedFile(absolute,platform);let spec=parseHostLaunchSpec(await readSpecText(absolute)),env=trustedEnv(spec.env),extensions=await resolveExtensions(spec.core.extensions,dirname(absolute));return{hostArgs:["--session-runtime",spec.core.session_runtime,...extensions.flatMap(path=>["--extension",path])],policy:{...spec.tunables?.idleExitMs!==void 0&&{idleExitMs:spec.tunables.idleExitMs},...spec.tunables?.coldStart!==void 0&&{coldStart:spec.tunables.coldStart}},env}}function parseHostLaunchSpec(text){let parsed;try{parsed=JSON.parse(text)}catch(error){throw new HostLaunchSpecError("launch_spec_invalid",error instanceof Error?error.message:"not JSON")}if(!isRecord(parsed))throw new HostLaunchSpecError("launch_spec_invalid","the spec is not a JSON object");if(parsed.spec_version!==1)throw new HostLaunchSpecError("launch_spec_invalid",`unsupported spec_version ${String(parsed.spec_version)}`);let core=parsed.core;if(!isRecord(core))throw new HostLaunchSpecError("launch_spec_invalid","core must be an object");if(typeof core.session_runtime!="string"||!isSessionRuntimeKind(core.session_runtime))throw new HostLaunchSpecError("launch_spec_invalid","core.session_runtime must be in-process or worker");if(core.multi_session!==!0)throw new HostLaunchSpecError("launch_spec_invalid","core.multi_session must be true");if(!Array.isArray(core.extensions)||!core.extensions.every(entry=>typeof entry=="string"))throw new HostLaunchSpecError("launch_spec_invalid","core.extensions must be an array of strings");let tunables=parsedTunables(parsed.tunables);return{spec_version:1,core:{session_runtime:core.session_runtime,multi_session:!0,extensions:core.extensions},...tunables&&{tunables},...isRecord(parsed.env)&&{env:parsedEnv(parsed.env)}}}async function readSpecText(absolute){try{return await readFile(absolute,"utf8")}catch(error){throw new HostLaunchSpecError("launch_spec_unreadable",error instanceof Error?error.message:absolute)}}async function assertTrustedFile(absolute,platform){if(platform==="win32")return;let stats=await stat(absolute).catch(error=>{throw new HostLaunchSpecError("launch_spec_unreadable",error instanceof Error?error.message:absolute)}),uid=process.getuid?.();if(uid!==void 0&&stats.uid!==uid)throw new HostLaunchSpecError("launch_spec_insecure",`${absolute} is owned by uid ${stats.uid}, not ${uid}`);if((stats.mode&18)!==0)throw new HostLaunchSpecError("launch_spec_insecure",`${absolute} is group/world writable (mode ${(stats.mode&511).toString(8)})`)}function trustedEnv(env){for(let name of Object.keys(env??{}))if(!SPEC_ENV_NAME.test(name))throw new HostLaunchSpecError("launch_spec_env_denied",`${name} is outside ${SPEC_ENV_NAME.source}`);return env??{}}async function resolveExtensions(extensions,specDir){let rootReal=await realpath(specDir).catch(()=>specDir),resolved=[];for(let entry of extensions){let target=resolve(specDir,entry);if(escapes(specDir,target))throw new HostLaunchSpecError("launch_spec_path_escape",`${entry} resolves outside ${specDir}`);let real=await realpath(target).catch(()=>{});if(real===void 0)throw new HostLaunchSpecError("launch_spec_missing_extension",`${target} does not exist`);if(escapes(rootReal,real))throw new HostLaunchSpecError("launch_spec_path_escape",`${entry} links outside ${specDir}`);resolved.push(real)}return resolved}function escapes(root,target){let step=relative(root,target);return step.startsWith("..")||isAbsolute(step)}function parsedTunables(value){if(!isRecord(value))return;let idleExitMs=value.idleExitMs,coldStart=value.coldStart;return{...typeof idleExitMs=="number"&&Number.isFinite(idleExitMs)&&idleExitMs>0&&{idleExitMs},...(coldStart==="transient"||coldStart==="persistent")&&{coldStart}}}function parsedEnv(value){let env={};for(let[name,entry]of Object.entries(value)){if(typeof entry!="string")throw new HostLaunchSpecError("launch_spec_invalid",`env.${name} must be a string`);env[name]=entry}return env}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{join}from"node:path";var ALLOWED_ENV_NAMES=[/^(PATH|HOME|USER|LOGNAME|SHELL|TMPDIR|TERM|LANG)$/u,/^(LC|XDG)_/u,/^(SENPI|OMO|PI)_/u,/^(HTTPS?_PROXY|NO_PROXY)$/u,/^[A-Z0-9_]+_API_KEY$/u,/^(ANTHROPIC|OPENAI|GOOGLE|GEMINI|AZURE|AWS|OPENROUTER|XAI|MISTRAL|DEEPSEEK|GROQ|CEREBRAS|MINIMAX)_/u],WINDOWS_SYSTEM_ENV_NAMES=new Set(["SYSTEMROOT","SYSTEMDRIVE","WINDIR","COMSPEC","PATHEXT","TEMP","TMP","USERPROFILE","APPDATA","LOCALAPPDATA","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","HOMEDRIVE","HOMEPATH","NUMBER_OF_PROCESSORS","PROCESSOR_ARCHITECTURE","OS"]);function daemonEnvIsAllowed(name,platform=process.platform){if(platform!=="win32")return ALLOWED_ENV_NAMES.some(pattern=>pattern.test(name));let upper=name.toUpperCase();return WINDOWS_SYSTEM_ENV_NAMES.has(upper)||ALLOWED_ENV_NAMES.some(pattern=>pattern.test(upper))}function daemonEnvOverrides(processEnv,specEnv={},platform=process.platform){let overrides={};for(let name of Object.keys(processEnv))daemonEnvIsAllowed(name,platform)||(overrides[name]=null);for(let[name,value]of Object.entries(specEnv))overrides[name]=value;return overrides}function daemonEnvKeys(processEnv,specEnv={},platform=process.platform){let kept=Object.keys(processEnv).filter(name=>daemonEnvIsAllowed(name,platform));return[...new Set([...kept,...Object.keys(specEnv)])].sort()}async function writeDaemonEnvKeys(paths,keys){await writeStateFile(daemonEnvKeysFile(paths),{env_keys:keys})}async function readDaemonEnvKeys(paths){let keys=parseJson(await readFileOrUndefined(daemonEnvKeysFile(paths)))?.env_keys;return Array.isArray(keys)?keys.filter(key=>typeof key=="string"):[]}function daemonEnvKeysFile(paths){return join(paths.dir,"env-keys.json")}var STATUS_PROBE_TIMEOUT_MS=1e4;async function readHostStatus(options){let paths=createHostDaemonPaths({socket:options.socket,...options.agentDir?{agentDir:options.agentDir}:{}}),host=await probeProtocolInfo(options.socket,STATUS_PROBE_TIMEOUT_MS);await pruneDeadGenerations(paths);let generations=await readGenerationRows(paths),current=generations.find(row=>row.current),metrics=current?await readHostProcessMetrics(current.pid):UNOBSERVED_METRICS;return{reachable:host!==void 0,socket:options.socket,pid:current?.pid??null,instanceId:host?.instanceId??current?.instanceId??null,generation:host?.generation??current?.generation??null,engineVersion:host?.engineVersion??current?.engineVersion??null,capabilities:host?.capabilities??[],launchProfile:host?.launch_profile??null,sessions:await readSessionCounts(options.socket,options.includeWorkers===!0),zombies:metrics.zombies,rss_mb:metrics.rss_mb,open_fds:metrics.open_fds,env_keys:await readDaemonEnvKeys(paths),generations}}async function readSessionCounts(socket,includeWorkers){let reply=await requestOnSocket(socket,{type:"list_sessions",...includeWorkers?{include_workers:!0}:{}},STATUS_PROBE_TIMEOUT_MS),rows=sessionRows(reply),attached=rows.filter(row=>row.attachments>0).length,retained=rows.length-attached;return{total:rows.length,interactive:rows.filter(row=>row.kind!=="worker").length,worker:rows.filter(row=>row.kind==="worker").length,retained,foreign_attached:attached,foreign_retained:retained}}function hostSummary(host){return host===void 0?null:{protocolVersion:host.protocolVersion,serverVersion:host.serverVersion,capabilities:host.capabilities,instanceId:host.instanceId??null,generation:host.generation??null,engineVersion:host.engineVersion??null,launchProfileId:host.launch_profile?.profile_id??null}}var UNOBSERVED_METRICS={rss_mb:null,open_fds:null,zombies:null};function sessionRows(reply){return!isRecord2(reply)||!Array.isArray(reply.sessions)?[]:reply.sessions.flatMap(entry=>isRecord2(entry)?[{kind:typeof entry.kind=="string"?entry.kind:"interactive",attachments:typeof entry.attachments=="number"?entry.attachments:0}]:[])}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}var HOST_EXIT_OK=0,HOST_EXIT_ERROR=1,HOST_EXIT_USAGE=2,HOST_EXIT_REFUSED=3,HOST_EXIT_FALLBACK=4,PROBE_TIMEOUT_MS=1e4;async function runHostRequest(request){switch(request.action){case"ensure":return ensureOutcome(request.target,request.spec,request.policy);case"status":return statusOutcome(request.target,request.includeWorkers);case"stop":return stopOutcome(request.target,request.drain,request.force);case"handoff":return handoffOutcome(request.target,request.spec);default:return assertNever(request)}}async function ensureOutcome(target,spec,policy){let before=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS);if(policy==="fallback"){let decision=decideHostAction(decisionClient(),before,"fallback");if(decision.action==="fallback")return refusal("fallback",before,{reason:decision.reason,socket:target.socket})}let ensured;try{ensured=await ensureHost({socket:target.socket,agentDir:target.agentDir,hostArgs:spec.hostArgs,env:daemonEnvOverrides(process.env,spec.env),policy:spec.policy,upgrade:policy==="upgrade"?"if-engine-differs":"never"})}catch(error){if(!(error instanceof HostEnsureRefusedError))throw error;return refusal("refuse",before,{reason:error.reason,socket:target.socket})}let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS);return ensured.reused||await recordEnvScope(target,spec),{exitCode:HOST_EXIT_OK,payload:{action:ensureAction(ensured.reused,before,host),...identityPayload(target.socket,ensured.pid,host),reused:ensured.reused}}}function ensureAction(reused,before,after){return reused?"reuse":before!==void 0&&before.instanceId!==after?.instanceId?"handoff":"start"}async function statusOutcome(target,includeWorkers){let status=await readHostStatus({socket:target.socket,agentDir:target.agentDir,includeWorkers});return{exitCode:status.reachable?HOST_EXIT_OK:HOST_EXIT_REFUSED,payload:{...status}}}async function stopOutcome(target,drain,force){let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS),sessions=await readSessionCounts(target.socket,!0),occupied=sessions.foreign_attached+sessions.foreign_retained>0;if(!drain&&!force&&occupied)return refusal("refuse",host,{reason:"sessions_live",socket:target.socket,sessions});let result=await stopHost({socket:target.socket,agentDir:target.agentDir,drain,force});return result.action==="refuse"?refusal("refuse",host,{reason:result.reason,socket:target.socket,sessions}):{exitCode:HOST_EXIT_OK,payload:{action:result.action,socket:target.socket,pid:result.pid,sessions}}}async function handoffOutcome(target,spec){let before=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS),result=await handoffHost({socket:target.socket,agentDir:target.agentDir,hostArgs:spec.hostArgs,env:daemonEnvOverrides(process.env,spec.env),policy:spec.policy});if(result.action==="refuse")return refusal("refuse",before,{reason:upgradeRefusal(result.reason),socket:target.socket,detail:result.reason,upgradeable:result.upgradeable});await recordEnvScope(target,spec);let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS);return{exitCode:HOST_EXIT_OK,payload:{action:"handoff",...identityPayload(target.socket,result.pid,host),reused:!1}}}function upgradeRefusal(reason){return reason==="handoff_unsupported"?"upgrade_unsupported":reason}function identityPayload(socket,pid,host){return{socket,pid,instanceId:host?.instanceId??null,generation:host?.generation??null,engineVersion:host?.engineVersion??null,engineOrdinal:host?.engineOrdinal??null,capabilities:host?.capabilities??[],launchProfileId:host?.launch_profile?.profile_id??null,upgradeable:decideHostAction(decisionClient(),host,"upgrade").upgradeable}}function refusal(kind,host,body){return{exitCode:kind==="refuse"?HOST_EXIT_REFUSED:HOST_EXIT_FALLBACK,payload:{action:kind,...body,host:hostSummary(host)}}}async function recordEnvScope(target,spec){let paths=createHostDaemonPaths({socket:target.socket,agentDir:target.agentDir});await writeDaemonEnvKeys(paths,daemonEnvKeys(process.env,spec.env))}function decisionClient(){return{protocolVersion:HOST_PROTOCOL_VERSION,requiredCapabilities:REQUIRED_HOST_CAPABILITIES,identity:engineBuildIdentity(),startedByUs:!1,platform:process.platform}}function assertNever(value){throw new Error(`unreachable host request: ${JSON.stringify(value)}`)}var SUBCOMMANDS=["ensure","status","stop","handoff"],POLICIES=["upgrade","fallback","never"],USAGE=`usage: ${APP_NAME} host <ensure|status|stop|handoff> [options]
|
|
2
|
+
import{HOST_PROTOCOL_VERSION,HostEnsureRefusedError,REQUIRED_HOST_CAPABILITIES,decideHostAction,ensureHost,handoffHost,probeProtocolInfo,requestOnSocket,stopHost}from"./chunk-UCPWK6TZ.js";import{createHostDaemonPaths,parseJson,pruneDeadGenerations,readFileOrUndefined,readGenerationRows,readHostProcessMetrics,writeStateFile}from"./chunk-BOZ37BOT.js";import{engineBuildIdentity}from"./chunk-M2HSO7MH.js";import{isSessionRuntimeKind}from"./chunk-KICRBRVS.js";import{APP_NAME,envValue,getAgentDir}from"./chunk-Y65WFI5H.js";import{writeSync}from"node:fs";import{resolve as resolve2}from"node:path";import{readFile,realpath,stat}from"node:fs/promises";import{dirname,isAbsolute,relative,resolve}from"node:path";var SPEC_ENV_NAME=/^(SENPI|OMO|PI)_[A-Z0-9_]+$/u,HostLaunchSpecError=class extends Error{constructor(reason,detail){super(`${reason}: ${detail}`),this.name="HostLaunchSpecError",this.reason=reason,this.detail=detail}},DEFAULT_HOST_LAUNCH_SPEC={hostArgs:[],policy:{},env:{}};async function loadHostLaunchSpec(specPath,platform=process.platform){let absolute=resolve(specPath);await assertTrustedFile(absolute,platform);let spec=parseHostLaunchSpec(await readSpecText(absolute)),env=trustedEnv(spec.env),extensions=await resolveExtensions(spec.core.extensions,dirname(absolute));return{hostArgs:["--session-runtime",spec.core.session_runtime,...extensions.flatMap(path=>["--extension",path])],policy:{...spec.tunables?.idleExitMs!==void 0&&{idleExitMs:spec.tunables.idleExitMs},...spec.tunables?.coldStart!==void 0&&{coldStart:spec.tunables.coldStart}},env}}function parseHostLaunchSpec(text){let parsed;try{parsed=JSON.parse(text)}catch(error){throw new HostLaunchSpecError("launch_spec_invalid",error instanceof Error?error.message:"not JSON")}if(!isRecord(parsed))throw new HostLaunchSpecError("launch_spec_invalid","the spec is not a JSON object");if(parsed.spec_version!==1)throw new HostLaunchSpecError("launch_spec_invalid",`unsupported spec_version ${String(parsed.spec_version)}`);let core=parsed.core;if(!isRecord(core))throw new HostLaunchSpecError("launch_spec_invalid","core must be an object");if(typeof core.session_runtime!="string"||!isSessionRuntimeKind(core.session_runtime))throw new HostLaunchSpecError("launch_spec_invalid","core.session_runtime must be in-process or worker");if(core.multi_session!==!0)throw new HostLaunchSpecError("launch_spec_invalid","core.multi_session must be true");if(!Array.isArray(core.extensions)||!core.extensions.every(entry=>typeof entry=="string"))throw new HostLaunchSpecError("launch_spec_invalid","core.extensions must be an array of strings");let tunables=parsedTunables(parsed.tunables);return{spec_version:1,core:{session_runtime:core.session_runtime,multi_session:!0,extensions:core.extensions},...tunables&&{tunables},...isRecord(parsed.env)&&{env:parsedEnv(parsed.env)}}}async function readSpecText(absolute){try{return await readFile(absolute,"utf8")}catch(error){throw new HostLaunchSpecError("launch_spec_unreadable",error instanceof Error?error.message:absolute)}}async function assertTrustedFile(absolute,platform){if(platform==="win32")return;let stats=await stat(absolute).catch(error=>{throw new HostLaunchSpecError("launch_spec_unreadable",error instanceof Error?error.message:absolute)}),uid=process.getuid?.();if(uid!==void 0&&stats.uid!==uid)throw new HostLaunchSpecError("launch_spec_insecure",`${absolute} is owned by uid ${stats.uid}, not ${uid}`);if((stats.mode&18)!==0)throw new HostLaunchSpecError("launch_spec_insecure",`${absolute} is group/world writable (mode ${(stats.mode&511).toString(8)})`)}function trustedEnv(env){for(let name of Object.keys(env??{}))if(!SPEC_ENV_NAME.test(name))throw new HostLaunchSpecError("launch_spec_env_denied",`${name} is outside ${SPEC_ENV_NAME.source}`);return env??{}}async function resolveExtensions(extensions,specDir){let rootReal=await realpath(specDir).catch(()=>specDir),resolved=[];for(let entry of extensions){let target=resolve(specDir,entry);if(escapes(specDir,target))throw new HostLaunchSpecError("launch_spec_path_escape",`${entry} resolves outside ${specDir}`);let real=await realpath(target).catch(()=>{});if(real===void 0)throw new HostLaunchSpecError("launch_spec_missing_extension",`${target} does not exist`);if(escapes(rootReal,real))throw new HostLaunchSpecError("launch_spec_path_escape",`${entry} links outside ${specDir}`);resolved.push(real)}return resolved}function escapes(root,target){let step=relative(root,target);return step.startsWith("..")||isAbsolute(step)}function parsedTunables(value){if(!isRecord(value))return;let idleExitMs=value.idleExitMs,coldStart=value.coldStart;return{...typeof idleExitMs=="number"&&Number.isFinite(idleExitMs)&&idleExitMs>0&&{idleExitMs},...(coldStart==="transient"||coldStart==="persistent")&&{coldStart}}}function parsedEnv(value){let env={};for(let[name,entry]of Object.entries(value)){if(typeof entry!="string")throw new HostLaunchSpecError("launch_spec_invalid",`env.${name} must be a string`);env[name]=entry}return env}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{join}from"node:path";var ALLOWED_ENV_NAMES=[/^(PATH|HOME|USER|LOGNAME|SHELL|TMPDIR|TERM|LANG)$/u,/^(LC|XDG)_/u,/^(SENPI|OMO|PI)_/u,/^(HTTPS?_PROXY|NO_PROXY)$/u,/^[A-Z0-9_]+_API_KEY$/u,/^(ANTHROPIC|OPENAI|GOOGLE|GEMINI|AZURE|AWS|OPENROUTER|XAI|MISTRAL|DEEPSEEK|GROQ|CEREBRAS|MINIMAX)_/u],WINDOWS_SYSTEM_ENV_NAMES=new Set(["SYSTEMROOT","SYSTEMDRIVE","WINDIR","COMSPEC","PATHEXT","TEMP","TMP","USERPROFILE","APPDATA","LOCALAPPDATA","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","HOMEDRIVE","HOMEPATH","NUMBER_OF_PROCESSORS","PROCESSOR_ARCHITECTURE","OS"]);function daemonEnvIsAllowed(name,platform=process.platform){if(platform!=="win32")return ALLOWED_ENV_NAMES.some(pattern=>pattern.test(name));let upper=name.toUpperCase();return WINDOWS_SYSTEM_ENV_NAMES.has(upper)||ALLOWED_ENV_NAMES.some(pattern=>pattern.test(upper))}function daemonEnvOverrides(processEnv,specEnv={},platform=process.platform){let overrides={};for(let name of Object.keys(processEnv))daemonEnvIsAllowed(name,platform)||(overrides[name]=null);for(let[name,value]of Object.entries(specEnv))overrides[name]=value;return overrides}function daemonEnvKeys(processEnv,specEnv={},platform=process.platform){let kept=Object.keys(processEnv).filter(name=>daemonEnvIsAllowed(name,platform));return[...new Set([...kept,...Object.keys(specEnv)])].sort()}async function writeDaemonEnvKeys(paths,keys){await writeStateFile(daemonEnvKeysFile(paths),{env_keys:keys})}async function readDaemonEnvKeys(paths){let keys=parseJson(await readFileOrUndefined(daemonEnvKeysFile(paths)))?.env_keys;return Array.isArray(keys)?keys.filter(key=>typeof key=="string"):[]}function daemonEnvKeysFile(paths){return join(paths.dir,"env-keys.json")}var STATUS_PROBE_TIMEOUT_MS=1e4;async function readHostStatus(options){let paths=createHostDaemonPaths({socket:options.socket,...options.agentDir?{agentDir:options.agentDir}:{}}),host=await probeProtocolInfo(options.socket,STATUS_PROBE_TIMEOUT_MS);await pruneDeadGenerations(paths);let generations=await readGenerationRows(paths),current=generations.find(row=>row.current),metrics=current?await readHostProcessMetrics(current.pid):UNOBSERVED_METRICS;return{reachable:host!==void 0,socket:options.socket,pid:current?.pid??null,instanceId:host?.instanceId??current?.instanceId??null,generation:host?.generation??current?.generation??null,engineVersion:host?.engineVersion??current?.engineVersion??null,capabilities:host?.capabilities??[],launchProfile:host?.launch_profile??null,sessions:await readSessionCounts(options.socket,options.includeWorkers===!0),zombies:metrics.zombies,rss_mb:metrics.rss_mb,open_fds:metrics.open_fds,env_keys:await readDaemonEnvKeys(paths),generations}}async function readSessionCounts(socket,includeWorkers){let reply=await requestOnSocket(socket,{type:"list_sessions",...includeWorkers?{include_workers:!0}:{}},STATUS_PROBE_TIMEOUT_MS),rows=sessionRows(reply),attached=rows.filter(row=>row.attachments>0).length,retained=rows.length-attached;return{total:rows.length,interactive:rows.filter(row=>row.kind!=="worker").length,worker:rows.filter(row=>row.kind==="worker").length,retained,foreign_attached:attached,foreign_retained:retained}}function hostSummary(host){return host===void 0?null:{protocolVersion:host.protocolVersion,serverVersion:host.serverVersion,capabilities:host.capabilities,instanceId:host.instanceId??null,generation:host.generation??null,engineVersion:host.engineVersion??null,launchProfileId:host.launch_profile?.profile_id??null}}var UNOBSERVED_METRICS={rss_mb:null,open_fds:null,zombies:null};function sessionRows(reply){return!isRecord2(reply)||!Array.isArray(reply.sessions)?[]:reply.sessions.flatMap(entry=>isRecord2(entry)?[{kind:typeof entry.kind=="string"?entry.kind:"interactive",attachments:typeof entry.attachments=="number"?entry.attachments:0}]:[])}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}var HOST_EXIT_OK=0,HOST_EXIT_ERROR=1,HOST_EXIT_USAGE=2,HOST_EXIT_REFUSED=3,HOST_EXIT_FALLBACK=4,PROBE_TIMEOUT_MS=1e4;async function runHostRequest(request){switch(request.action){case"ensure":return ensureOutcome(request.target,request.spec,request.policy);case"status":return statusOutcome(request.target,request.includeWorkers);case"stop":return stopOutcome(request.target,request.drain,request.force);case"handoff":return handoffOutcome(request.target,request.spec);default:return assertNever(request)}}async function ensureOutcome(target,spec,policy){let before=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS);if(policy==="fallback"){let decision=decideHostAction(decisionClient(),before,"fallback");if(decision.action==="fallback")return refusal("fallback",before,{reason:decision.reason,socket:target.socket})}let ensured;try{ensured=await ensureHost({socket:target.socket,agentDir:target.agentDir,hostArgs:spec.hostArgs,env:daemonEnvOverrides(process.env,spec.env),policy:spec.policy,upgrade:policy==="upgrade"?"if-engine-differs":"never"})}catch(error){if(!(error instanceof HostEnsureRefusedError))throw error;return refusal("refuse",before,{reason:error.reason,socket:target.socket})}let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS);return ensured.reused||await recordEnvScope(target,spec),{exitCode:HOST_EXIT_OK,payload:{action:ensureAction(ensured.reused,before,host),...identityPayload(target.socket,ensured.pid,host),reused:ensured.reused}}}function ensureAction(reused,before,after){return reused?"reuse":before!==void 0&&before.instanceId!==after?.instanceId?"handoff":"start"}async function statusOutcome(target,includeWorkers){let status=await readHostStatus({socket:target.socket,agentDir:target.agentDir,includeWorkers});return{exitCode:status.reachable?HOST_EXIT_OK:HOST_EXIT_REFUSED,payload:{...status}}}async function stopOutcome(target,drain,force){let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS),sessions=await readSessionCounts(target.socket,!0),occupied=sessions.foreign_attached+sessions.foreign_retained>0;if(!drain&&!force&&occupied)return refusal("refuse",host,{reason:"sessions_live",socket:target.socket,sessions});let result=await stopHost({socket:target.socket,agentDir:target.agentDir,drain,force});return result.action==="refuse"?refusal("refuse",host,{reason:result.reason,socket:target.socket,sessions}):{exitCode:HOST_EXIT_OK,payload:{action:result.action,socket:target.socket,pid:result.pid,sessions}}}async function handoffOutcome(target,spec){let before=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS),result=await handoffHost({socket:target.socket,agentDir:target.agentDir,hostArgs:spec.hostArgs,env:daemonEnvOverrides(process.env,spec.env),policy:spec.policy});if(result.action==="refuse")return refusal("refuse",before,{reason:upgradeRefusal(result.reason),socket:target.socket,detail:result.reason,upgradeable:result.upgradeable});await recordEnvScope(target,spec);let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS);return{exitCode:HOST_EXIT_OK,payload:{action:"handoff",...identityPayload(target.socket,result.pid,host),reused:!1}}}function upgradeRefusal(reason){return reason==="handoff_unsupported"?"upgrade_unsupported":reason}function identityPayload(socket,pid,host){return{socket,pid,instanceId:host?.instanceId??null,generation:host?.generation??null,engineVersion:host?.engineVersion??null,engineOrdinal:host?.engineOrdinal??null,capabilities:host?.capabilities??[],launchProfileId:host?.launch_profile?.profile_id??null,upgradeable:decideHostAction(decisionClient(),host,"upgrade").upgradeable}}function refusal(kind,host,body){return{exitCode:kind==="refuse"?HOST_EXIT_REFUSED:HOST_EXIT_FALLBACK,payload:{action:kind,...body,host:hostSummary(host)}}}async function recordEnvScope(target,spec){let paths=createHostDaemonPaths({socket:target.socket,agentDir:target.agentDir});await writeDaemonEnvKeys(paths,daemonEnvKeys(process.env,spec.env))}function decisionClient(){return{protocolVersion:HOST_PROTOCOL_VERSION,requiredCapabilities:REQUIRED_HOST_CAPABILITIES,identity:engineBuildIdentity(),startedByUs:!1,platform:process.platform}}function assertNever(value){throw new Error(`unreachable host request: ${JSON.stringify(value)}`)}var SUBCOMMANDS=["ensure","status","stop","handoff"],POLICIES=["upgrade","fallback","never"],USAGE=`usage: ${APP_NAME} host <ensure|status|stop|handoff> [options]
|
|
3
3
|
|
|
4
4
|
ensure [--launch-spec <file>] [--policy upgrade|fallback|never] [--socket <path>]
|
|
5
5
|
status [--include-workers] [--socket <path>]
|