@code-yeongyu/senpi 2026.11.10 → 2026.11.11
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 +95 -0
- package/dist/bundle/{SKILL-B4R7BVOT.md → SKILL-R7FEIQKG.md} +1 -1
- package/dist/bundle/chunks/{SKILL-AZ6ONO52.js → SKILL-5O2UKORG.js} +1 -1
- package/dist/bundle/chunks/{SKILL-B4R7BVOT.md → SKILL-R7FEIQKG.md} +1 -1
- package/dist/bundle/chunks/{args-77GYOPEO.js → args-HFYB6URH.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-YFZ734T3.js → azure-openai-responses-MNN2TINI.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZUQCYIRY.js → chunk-2ODGHBUD.js} +1 -1
- package/dist/bundle/chunks/chunk-3IYEGHBI.js +2 -0
- package/dist/bundle/chunks/{chunk-I5ASHSLZ.js → chunk-4JMGWVRH.js} +1 -1
- package/dist/bundle/chunks/{chunk-YKYWL2NO.js → chunk-5F2XC6UC.js} +3 -3
- package/dist/bundle/chunks/{chunk-MSDBBOB2.js → chunk-5H43O4MA.js} +1 -1
- package/dist/bundle/chunks/{chunk-R3OP7IA4.js → chunk-5PIZWSNG.js} +4 -4
- package/dist/bundle/chunks/{chunk-33MZJTQ3.js → chunk-B4WD5XHP.js} +1 -1
- package/dist/bundle/chunks/{chunk-Q63YLZMN.js → chunk-BPEA5SWW.js} +2 -2
- package/dist/bundle/chunks/{chunk-MOVJQVMC.js → chunk-BUDJLVMF.js} +3 -3
- package/dist/bundle/chunks/{chunk-V5FSENW6.js → chunk-COKX65TE.js} +1 -1
- package/dist/bundle/chunks/{chunk-2EJ4BGBM.js → chunk-DHORIIVQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-NH7SYIGN.js → chunk-DLPV4B3R.js} +1 -1
- package/dist/bundle/chunks/{chunk-RCHIMH7N.js → chunk-DQY26AX3.js} +1 -1
- package/dist/bundle/chunks/{chunk-Y7Z7XPUF.js → chunk-DZQA5LVN.js} +1 -1
- package/dist/bundle/chunks/{chunk-2CNSCMYC.js → chunk-E5O4SP5I.js} +1 -1
- package/dist/bundle/chunks/{chunk-3Q5ZENSD.js → chunk-E6ZBTSC6.js} +1 -1
- package/dist/bundle/chunks/{chunk-GVPZPVVO.js → chunk-IBDAV2AL.js} +3 -3
- package/dist/bundle/chunks/chunk-IREUIMFE.js +11 -0
- package/dist/bundle/chunks/{chunk-KU7OCWJF.js → chunk-J4ADZ2OK.js} +1 -1
- package/dist/bundle/chunks/{chunk-T2SMQPRE.js → chunk-K3GAGIPX.js} +1 -1
- package/dist/bundle/chunks/{chunk-BELNOPAI.js → chunk-L3KVP7VJ.js} +3 -3
- package/dist/bundle/chunks/{chunk-IYSJFQUU.js → chunk-L6DF5G6K.js} +1 -1
- package/dist/bundle/chunks/{chunk-7MN7YNO5.js → chunk-L7DGTA3L.js} +1 -1
- package/dist/bundle/chunks/chunk-LJFQYCFH.js +2 -0
- package/dist/bundle/chunks/{chunk-J2NGJKXL.js → chunk-LXINMDMX.js} +1 -1
- package/dist/bundle/chunks/{chunk-H33A33M4.js → chunk-M2VJVJMK.js} +1 -1
- package/dist/bundle/chunks/{chunk-2U6HXWXS.js → chunk-NNQ34ZDW.js} +1 -1
- package/dist/bundle/chunks/chunk-NQKCJQHB.js +2 -0
- package/dist/bundle/chunks/{chunk-EJB5E2JK.js → chunk-NRZAJUUO.js} +2 -2
- package/dist/bundle/chunks/{chunk-R2Z7CX77.js → chunk-OSNR3IRD.js} +1 -1
- package/dist/bundle/chunks/{chunk-O3FG6HML.js → chunk-PJI5GT7U.js} +1 -1
- package/dist/bundle/chunks/{chunk-FDNM2DAE.js → chunk-PUZDKFRT.js} +164 -164
- package/dist/bundle/chunks/{chunk-BPNSOZ2C.js → chunk-QUVSIW2R.js} +1 -1
- package/dist/bundle/chunks/{chunk-WXYMAUFX.js → chunk-QX7WD3IM.js} +1 -1
- package/dist/bundle/chunks/{chunk-Y4ONXQMR.js → chunk-RGHVPUUX.js} +1 -1
- package/dist/bundle/chunks/{chunk-RYPM5BZQ.js → chunk-S7NAJQB3.js} +1 -1
- package/dist/bundle/chunks/{chunk-2BH54YQR.js → chunk-SANWO37B.js} +1 -1
- package/dist/bundle/chunks/{chunk-YQZNARTX.js → chunk-SS5VTBAV.js} +1 -1
- package/dist/bundle/chunks/{chunk-LT353NSF.js → chunk-T4CUD7RF.js} +1 -1
- package/dist/bundle/chunks/{chunk-J7FW7MED.js → chunk-TCZORL3V.js} +1 -1
- package/dist/bundle/chunks/{chunk-KU72IKV5.js → chunk-VGSWOLIY.js} +1 -1
- package/dist/bundle/chunks/{chunk-DBQBJTMF.js → chunk-VUY4BZDI.js} +1 -1
- package/dist/bundle/chunks/chunk-XI6THO4F.js +2 -0
- package/dist/bundle/chunks/{chunk-FAFIGBUD.js → chunk-XUDKT4UH.js} +3 -3
- package/dist/bundle/chunks/{cli-main-BX5AFWJQ.js → cli-main-7II7GCIR.js} +1 -1
- package/dist/bundle/chunks/{credential-accounts-LVVPKFEY.js → credential-accounts-N3B5YJS7.js} +1 -1
- package/dist/bundle/chunks/{dispatch-EP35KKJ3.js → dispatch-YUYZQXRP.js} +1 -1
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{hand-entry-F6PWKNPJ.js → hand-entry-ONOLRMVB.js} +3 -3
- package/dist/bundle/chunks/{headless-host-HKGNJGYT.js → headless-host-53UMJMM6.js} +1 -1
- package/dist/bundle/chunks/{health-write-FBF74QJ7.js → health-write-JLSF5EVV.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-5SCPY3OH.js → help-fast-path-552QLMWT.js} +1 -1
- package/dist/bundle/chunks/{host-command-47QQKJEY.js → host-command-KWMJLPBS.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-VSAH4M3R.js → host-lifecycle-4WQDCN3Y.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +5 -5
- package/dist/bundle/chunks/{host-session-command-SL4AN5WD.js → host-session-command-ZDYEKCUB.js} +1 -1
- package/dist/bundle/chunks/{host-socket-request-DMYXC56U.js → host-socket-request-QN4Q2P5E.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-JDMIHJMQ.js → interactive-mode-EPE4M32G.js} +1 -1
- package/dist/bundle/chunks/{login-health-EVXVLHB2.js → login-health-TOSQT5RG.js} +1 -1
- package/dist/bundle/chunks/{main-4RITUAQF.js → main-OM7BKVZG.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-SKDD4OWM.js → multi-session-host-DB6XMY53.js} +11 -8
- package/dist/bundle/chunks/openai-codex-responses-VRGOAFEG.js +10 -0
- package/dist/bundle/chunks/{openai-responses-NIVBWE2H.js → openai-responses-I7PXRWCM.js} +2 -2
- package/dist/bundle/chunks/{package-manager-cli-B5VA4KFO.js → package-manager-cli-GLU5Q2KV.js} +1 -1
- package/dist/bundle/chunks/{role-HQUN4XXK.js → role-AEOLJRTP.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-F3BEMXBE.js → rotation-stream-E3FJFHXJ.js} +1 -1
- package/dist/bundle/chunks/rpc-mode-SDJVBT36.js +2 -0
- package/dist/bundle/chunks/{rpc-monitor-source-C6VQ3BC4.js → rpc-monitor-source-PGTDSGWP.js} +1 -1
- package/dist/bundle/chunks/{run-attached-tui-R3RB5P7G.js → run-attached-tui-4AENRP7P.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-FPEQCX33.js → schedule-command-5SQD7M5N.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-R25A2QGS.js +3 -0
- package/dist/bundle/chunks/{session-picker-2FZSNFS7.js → session-picker-GZM5CVQL.js} +1 -1
- package/dist/bundle/chunks/{session-slot-CZGQQCOC.js → session-slot-RH7JLO3F.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +335 -332
- package/dist/bundle/chunks/{state-store-S7QAESIF.js → state-store-IECVTYXC.js} +1 -1
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/host-supervisor.js +5 -5
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/cli.js +9 -3
- package/dist/core/agent-session-runtime.d.ts +2 -0
- package/dist/core/agent-session-runtime.js +5 -0
- package/dist/core/agent-session.d.ts +15 -3
- package/dist/core/agent-session.js +91 -18
- package/dist/core/assistant-error-redaction.d.ts +9 -0
- package/dist/core/assistant-error-redaction.js +27 -0
- package/dist/core/config-reference-redaction.js +90 -10
- package/dist/core/context-files.d.ts +10 -0
- package/dist/core/context-files.js +58 -12
- package/dist/core/credential-accounts.d.ts +2 -0
- package/dist/core/credential-accounts.js +10 -1
- package/dist/core/dynamic-prompt/intent-gate.js +2 -2
- package/dist/core/dynamic-prompt/style.js +2 -2
- package/dist/core/dynamic-prompt/verification.js +2 -2
- package/dist/core/egress/wire.d.ts +13 -0
- package/dist/core/extensions/builtin/anthropic-subscription/accounts.d.ts +3 -0
- package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js +3 -2
- package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-account-test.js +3 -1
- package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-connection-test.d.ts +3 -1
- package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-connection-test.js +47 -16
- package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-login-slots.d.ts +1 -1
- package/dist/core/extensions/builtin/anthropic-subscription/claude-cli-login-slots.js +4 -2
- package/dist/core/extensions/builtin/anthropic-subscription/claude-settings-env.d.ts +20 -0
- package/dist/core/extensions/builtin/anthropic-subscription/claude-settings-env.js +39 -0
- package/dist/core/extensions/builtin/anthropic-subscription/context-window.d.ts +17 -0
- package/dist/core/extensions/builtin/anthropic-subscription/context-window.js +23 -0
- package/dist/core/extensions/builtin/anthropic-subscription/errors.d.ts +1 -0
- package/dist/core/extensions/builtin/anthropic-subscription/errors.js +14 -5
- package/dist/core/extensions/builtin/anthropic-subscription/oauth-login.js +3 -3
- package/dist/core/extensions/builtin/anthropic-subscription/prompt-cache-ttl.d.ts +10 -4
- package/dist/core/extensions/builtin/anthropic-subscription/prompt-cache-ttl.js +14 -5
- package/dist/core/extensions/builtin/anthropic-subscription/query-environment.d.ts +3 -2
- package/dist/core/extensions/builtin/anthropic-subscription/query-environment.js +5 -4
- package/dist/core/extensions/builtin/anthropic-subscription/sdk-boundary.lazy.d.ts +2 -1
- package/dist/core/extensions/builtin/anthropic-subscription/sdk-boundary.lazy.js +1 -0
- package/dist/core/extensions/builtin/anthropic-subscription/stream.js +11 -1
- package/dist/core/extensions/builtin/config-reload/change-groups.js +6 -2
- package/dist/core/extensions/builtin/goal/continuation.d.ts +6 -0
- package/dist/core/extensions/builtin/goal/continuation.js +3 -2
- package/dist/core/extensions/builtin/goal/index.js +14 -26
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +8 -6
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +77 -39
- package/dist/core/extensions/builtin/goal/monitor-continuation.js +66 -7
- package/dist/core/extensions/builtin/goal/persistence.js +20 -0
- package/dist/core/extensions/builtin/goal/provider-retry.d.ts +9 -0
- package/dist/core/extensions/builtin/goal/provider-retry.js +16 -0
- package/dist/core/extensions/builtin/goal/reload-reengagement.d.ts +3 -2
- package/dist/core/extensions/builtin/goal/reload-reengagement.js +4 -4
- package/dist/core/extensions/builtin/goal/session-start-continuation.d.ts +28 -0
- package/dist/core/extensions/builtin/goal/session-start-continuation.js +75 -0
- package/dist/core/extensions/builtin/goal/store.d.ts +3 -2
- package/dist/core/extensions/builtin/goal/store.js +9 -2
- package/dist/core/extensions/builtin/goal/types.d.ts +9 -0
- package/dist/core/extensions/builtin/handoff-hint/index.js +15 -11
- package/dist/core/extensions/builtin/handoff-hint/replacement-relay.d.ts +16 -0
- package/dist/core/extensions/builtin/handoff-hint/replacement-relay.js +17 -0
- package/dist/core/extensions/builtin/html-render/tool.js +13 -3
- package/dist/core/extensions/builtin/imagegen/skill/SKILL.md +1 -1
- package/dist/core/extensions/builtin/imagegen/tool.js +4 -14
- package/dist/core/extensions/builtin/mcp/auth/catalog-identity.js +32 -8
- package/dist/core/extensions/builtin/mcp/auth/commands-auth.js +2 -1
- package/dist/core/extensions/builtin/mcp/auth/context.js +3 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-grant.d.ts +43 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-grant.js +196 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.d.ts +7 -1
- package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.js +13 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.d.ts +6 -17
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +67 -88
- package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.d.ts +1 -1
- package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.js +25 -4
- package/dist/core/extensions/builtin/mcp/auth/oauth.js +10 -7
- package/dist/core/extensions/builtin/mcp/auth/registered-redirect.d.ts +19 -0
- package/dist/core/extensions/builtin/mcp/auth/registered-redirect.js +55 -0
- package/dist/core/extensions/builtin/mcp/auth/token-store.d.ts +23 -1
- package/dist/core/extensions/builtin/mcp/auth/token-store.js +3 -0
- package/dist/core/extensions/builtin/mcp/catalog-cache.js +7 -6
- package/dist/core/extensions/builtin/mcp/catalog.js +3 -2
- package/dist/core/extensions/builtin/mcp/invocation.js +6 -0
- package/dist/core/extensions/builtin/mcp/service-register.js +16 -2
- package/dist/core/extensions/builtin/mcp/service-tools-changed.js +61 -54
- package/dist/core/extensions/builtin/mcp/startup-race.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/startup-race.js +25 -7
- package/dist/core/extensions/builtin/permission-system/parsers.js +1 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-2.js +9 -8
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/claude-haiku-5-5.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5-5.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +4 -4
- package/dist/core/extensions/builtin/prompt-preset/claude-sonnet-5-5.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +2 -2
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.6.js +4 -4
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.js +5 -5
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3-1.js +4 -4
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +7 -6
- package/dist/core/extensions/loader.js +24 -4
- package/dist/core/extensions/runner.d.ts +9 -1
- package/dist/core/extensions/runner.js +9 -4
- package/dist/core/extensions/types.d.ts +19 -3
- package/dist/core/hand/hook-advertise.d.ts +41 -0
- package/dist/core/hand/hook-advertise.js +98 -0
- package/dist/core/hand/hook-contract.d.ts +66 -0
- package/dist/core/hand/hook-contract.js +138 -0
- package/dist/core/open-timing.d.ts +2 -0
- package/dist/core/open-timing.js +7 -1
- package/dist/core/resource-loader.js +21 -3
- package/dist/core/retry-fallback/controller-types.d.ts +2 -0
- package/dist/core/retry-fallback/controller.js +9 -2
- package/dist/core/retry-fallback/cooldown.d.ts +7 -0
- package/dist/core/retry-fallback/cooldown.js +13 -1
- package/dist/core/retry-fallback/credential-recovery.d.ts +7 -0
- package/dist/core/retry-fallback/credential-recovery.js +24 -0
- package/dist/core/retry-fallback/log.d.ts +7 -1
- package/dist/core/retry-fallback/log.js +82 -5
- package/dist/core/retry-fallback/model-config-error.js +2 -1
- package/dist/core/retry-fallback/settings.d.ts +8 -5
- package/dist/core/retry-fallback/settings.js +9 -6
- package/dist/core/session-manager.d.ts +2 -0
- package/dist/core/session-manager.js +15 -1
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.js +8 -0
- package/dist/core/turn-origin.d.ts +18 -10
- package/dist/core/turn-origin.js +34 -30
- package/dist/core/ultrafast-lanes.d.ts +1 -0
- package/dist/core/ultrafast-lanes.js +4 -2
- package/dist/modes/interactive/components/footer.d.ts +23 -5
- package/dist/modes/interactive/components/footer.js +45 -16
- package/dist/modes/interactive/interactive-mode.js +9 -1
- package/dist/modes/interactive/session-control-rpc-commands.d.ts +1 -1
- package/dist/modes/interactive/session-control-rpc-commands.js +5 -0
- package/dist/modes/rpc/admit-external-message-command.d.ts +2 -0
- package/dist/modes/rpc/admit-external-message-command.js +5 -1
- package/dist/modes/rpc/compact-admission-validation.js +4 -1
- package/dist/modes/rpc/connection-authority.d.ts +2 -1
- package/dist/modes/rpc/connection-authority.js +11 -9
- package/dist/modes/rpc/connection-handler.d.ts +2 -0
- package/dist/modes/rpc/connection-handler.js +33 -7
- package/dist/modes/rpc/connection-roles.d.ts +7 -0
- package/dist/modes/rpc/connection-roles.js +15 -0
- package/dist/modes/rpc/custom-capability.d.ts +6 -0
- package/dist/modes/rpc/custom-capability.js +6 -0
- package/dist/modes/rpc/delegated-drive-origin.d.ts +6 -6
- package/dist/modes/rpc/delegated-drive-origin.js +7 -8
- package/dist/modes/rpc/delegation-declaration.d.ts +2 -0
- package/dist/modes/rpc/delegation-declaration.js +7 -3
- package/dist/modes/rpc/effect-commands.d.ts +33 -0
- package/dist/modes/rpc/host-capabilities.d.ts +1 -0
- package/dist/modes/rpc/host-capabilities.js +7 -1
- package/dist/modes/rpc/host-gc-evidence.d.ts +1 -1
- package/dist/modes/rpc/host-gc-evidence.js +9 -3
- package/dist/modes/rpc/host-gc.js +4 -1
- package/dist/modes/rpc/host-observe-request.d.ts +2 -0
- package/dist/modes/rpc/host-observe-request.js +6 -1
- package/dist/modes/rpc/host-park-ledger.d.ts +19 -0
- package/dist/modes/rpc/host-park-ledger.js +110 -0
- package/dist/modes/rpc/lifecycle-delivery.js +4 -1
- package/dist/modes/rpc/loopless-tool-handlers.d.ts +6 -0
- package/dist/modes/rpc/loopless-tool-handlers.js +14 -1
- package/dist/modes/rpc/media-placeholders.js +1 -0
- package/dist/modes/rpc/method-classes-schema-host.d.ts +42 -1
- package/dist/modes/rpc/method-classes-schema-host.js +24 -21
- package/dist/modes/rpc/method-classes-schema-session.d.ts +20 -0
- package/dist/modes/rpc/method-classes-schema-session.js +6 -0
- package/dist/modes/rpc/method-classes-schema.d.ts +62 -1
- package/dist/modes/rpc/method-classes-schema.js +5 -2
- package/dist/modes/rpc/method-classes.d.ts +4 -0
- package/dist/modes/rpc/method-classes.js +6 -0
- package/dist/modes/rpc/multi-session-host.js +1 -1
- package/dist/modes/rpc/project-file-commands.d.ts +32 -0
- package/dist/modes/rpc/project-file-commands.js +195 -0
- package/dist/modes/rpc/project-file-path.d.ts +34 -0
- package/dist/modes/rpc/project-file-path.js +93 -0
- package/dist/modes/rpc/rpc-error-types.d.ts +9 -1
- package/dist/modes/rpc/rpc-error-types.js +8 -0
- package/dist/modes/rpc/rpc-host-command-types.d.ts +14 -1
- package/dist/modes/rpc/rpc-host-response-types.d.ts +21 -0
- package/dist/modes/rpc/rpc-mutation-response-types.d.ts +7 -0
- package/dist/modes/rpc/rpc-read-response-types.d.ts +7 -0
- package/dist/modes/rpc/rpc-session-command-types.d.ts +10 -0
- package/dist/modes/rpc/rpc-session-state-types.d.ts +2 -0
- package/dist/modes/rpc/session-attachment-gate.js +6 -0
- package/dist/modes/rpc/session-binding.d.ts +1 -0
- package/dist/modes/rpc/session-binding.js +6 -1
- package/dist/modes/rpc/session-command-activity.js +1 -0
- package/dist/modes/rpc/session-connection-context.d.ts +2 -0
- package/dist/modes/rpc/session-connection-context.js +4 -0
- package/dist/modes/rpc/session-registry-attach.d.ts +2 -0
- package/dist/modes/rpc/session-registry-attach.js +15 -11
- package/dist/modes/rpc/session-registry-claims.js +2 -0
- package/dist/modes/rpc/session-registry-open.js +13 -7
- package/dist/modes/rpc/session-registry-opening.js +2 -1
- package/dist/modes/rpc/session-registry-types.d.ts +4 -0
- package/dist/modes/rpc/session-registry.d.ts +3 -0
- package/dist/modes/rpc/session-registry.js +27 -3
- package/dist/modes/rpc/session-router-close.js +1 -0
- package/dist/modes/rpc/session-router-context.d.ts +4 -2
- package/dist/modes/rpc/session-router-context.js +3 -0
- package/dist/modes/rpc/session-router-host-reads.js +1 -0
- package/dist/modes/rpc/session-router-occupancy.js +10 -1
- package/dist/modes/rpc/session-router-open-result.d.ts +12 -0
- package/dist/modes/rpc/session-router-open-result.js +63 -0
- package/dist/modes/rpc/session-router-open.d.ts +3 -0
- package/dist/modes/rpc/session-router-open.js +15 -63
- package/dist/modes/rpc/session-router-park.d.ts +15 -0
- package/dist/modes/rpc/session-router-park.js +176 -0
- package/dist/modes/rpc/session-router-routing.d.ts +1 -1
- package/dist/modes/rpc/session-router-routing.js +7 -0
- package/dist/modes/rpc/session-status-source.js +2 -2
- package/dist/private-fd-startup-fillers.d.ts +2 -2
- package/dist/private-fd-startup-fillers.js +34 -4
- package/dist/senpi +9 -3
- package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
- package/docs/engine-socket/fixtures/rpc-inbound-samples.json +44 -2
- package/docs/extensions.md +11 -1
- package/docs/rpc.md +106 -2
- package/docs/settings.md +5 -3
- package/docs/skills.md +1 -1
- package/docs/usage.md +1 -1
- package/native/socket-secret/prebuilds/win32-arm64/senpi_socket_secret.win32-arm64.node +0 -0
- package/native/socket-secret/prebuilds/win32-x64/senpi_socket_secret.win32-x64.node +0 -0
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-436DNN4Z.js +0 -2
- package/dist/bundle/chunks/chunk-DLAY7CIU.js +0 -2
- package/dist/bundle/chunks/chunk-SJI6UB23.js +0 -2
- package/dist/bundle/chunks/chunk-XH2MWTXA.js +0 -11
- package/dist/bundle/chunks/chunk-YK3ZZCHI.js +0 -2
- package/dist/bundle/chunks/openai-codex-responses-ABB2J43U.js +0 -10
- package/dist/bundle/chunks/rpc-mode-ZDUGW2IM.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-MEDV66PS.js +0 -3
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { runWithProviderScope } from "@earendil-works/pi-ai/node/provider-scope";
|
|
2
|
+
import { withoutOpenTiming } from "../../core/open-timing.js";
|
|
3
|
+
import { outsideCommand } from "./command-authority.js";
|
|
4
|
+
import { runSetThinkingLevel } from "./effect-commands.js";
|
|
5
|
+
import { runSetModel } from "./handlers-model.js";
|
|
6
|
+
import { runSetPermissionPreset } from "./permission-preset-command.js";
|
|
7
|
+
import { applyAttachedProfile } from "./session-registry-attach.js";
|
|
8
|
+
import { releaseOwnedSession, releaseOwnerAttachment } from "./session-router-attachments.js";
|
|
9
|
+
import { finalizeClose, tryClaimClose } from "./session-router-close.js";
|
|
10
|
+
import { code, error } from "./session-router-errors.js";
|
|
11
|
+
import { open } from "./session-router-open.js";
|
|
12
|
+
import { validatedOpenProfile } from "./session-router-open-profile.js";
|
|
13
|
+
import { holdOpenConnection, ownOpen, publishOpen, replyOpen } from "./session-router-open-result.js";
|
|
14
|
+
import { syncRetainedRecord } from "./session-router-residency.js";
|
|
15
|
+
function profileKey(profile) {
|
|
16
|
+
return JSON.stringify([
|
|
17
|
+
profile.cwd,
|
|
18
|
+
profile.sessionKind ?? "interactive",
|
|
19
|
+
Object.entries(profile.sessionContext ?? {}).sort(([a], [b]) => a.localeCompare(b)),
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
/** Same open, host-context merge, kind, media and binding; no owner and no publication. */
|
|
23
|
+
async function buildPark(host, command) {
|
|
24
|
+
let opened;
|
|
25
|
+
const response = await outsideCommand(() => host.writer.connectionContext.outside(() => withoutOpenTiming(() => open(host, { ...command, type: "open_session" }, undefined, {
|
|
26
|
+
reply: false,
|
|
27
|
+
park: (result) => {
|
|
28
|
+
opened = result;
|
|
29
|
+
},
|
|
30
|
+
}))));
|
|
31
|
+
if (response && !response.success)
|
|
32
|
+
throw new Error(response.error);
|
|
33
|
+
if (!opened)
|
|
34
|
+
throw new Error("park_open_failed");
|
|
35
|
+
return opened;
|
|
36
|
+
}
|
|
37
|
+
/** Quiet teardown: speculation never owes a public terminal record or a handover park. */
|
|
38
|
+
export async function closePark(host, opened) {
|
|
39
|
+
const claim = tryClaimClose(host, opened.sessionId, { drainAttachments: true });
|
|
40
|
+
if (claim?.finalizer)
|
|
41
|
+
await finalizeClose(host, opened.sessionId, host.bindings.get(opened.sessionId));
|
|
42
|
+
else
|
|
43
|
+
await host.finalizations.get(opened.sessionId)?.promise;
|
|
44
|
+
host.writer.forgetSession(opened.sessionId);
|
|
45
|
+
}
|
|
46
|
+
export async function parkSession(host, command) {
|
|
47
|
+
if (!host.registry.supportsParkClaim)
|
|
48
|
+
return error(command.id, command.type, "park_claim_unsupported");
|
|
49
|
+
if (host.draining || host.drainExitRequested)
|
|
50
|
+
return error(command.id, command.type, "host_draining");
|
|
51
|
+
const profile = validatedOpenProfile(host, { ...command, type: "open_session" });
|
|
52
|
+
if ("type" in profile)
|
|
53
|
+
return { ...profile, command: command.type };
|
|
54
|
+
try {
|
|
55
|
+
const state = await host.parks.park(profileKey(profile), () => buildPark(host, command));
|
|
56
|
+
if (host.draining || host.drainExitRequested)
|
|
57
|
+
return error(command.id, command.type, "host_draining");
|
|
58
|
+
return { id: command.id, type: "response", command: command.type, success: true, data: { state } };
|
|
59
|
+
}
|
|
60
|
+
catch (cause) {
|
|
61
|
+
return error(command.id, command.type, code(cause));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function claimSession(host, command) {
|
|
65
|
+
const owner = host.writer.currentConnection();
|
|
66
|
+
const release = owner === undefined ? undefined : holdOpenConnection(host, owner);
|
|
67
|
+
return claimReady(host, command, owner).finally(release);
|
|
68
|
+
}
|
|
69
|
+
async function claimReady(host, command, owner) {
|
|
70
|
+
if (!host.registry.supportsParkClaim || !host.registry.claimPark)
|
|
71
|
+
return error(command.id, command.type, "park_claim_unsupported");
|
|
72
|
+
if (host.draining || host.drainExitRequested)
|
|
73
|
+
return error(command.id, command.type, "host_draining");
|
|
74
|
+
const miss = () => ({
|
|
75
|
+
id: command.id,
|
|
76
|
+
type: "response",
|
|
77
|
+
command: "claim_session",
|
|
78
|
+
success: true,
|
|
79
|
+
data: { claimed: false },
|
|
80
|
+
});
|
|
81
|
+
// These require construction or a distinct admission contract. A miss leaves the park untouched.
|
|
82
|
+
if (command.sessionPath !== undefined ||
|
|
83
|
+
command.durableSessionId !== undefined ||
|
|
84
|
+
command.expectedHostInstance !== undefined ||
|
|
85
|
+
command.admissionId !== undefined ||
|
|
86
|
+
command.attended === false ||
|
|
87
|
+
command.retry !== undefined ||
|
|
88
|
+
(command.provider !== undefined) !== (command.modelId !== undefined) ||
|
|
89
|
+
command.spawnedBy !== undefined ||
|
|
90
|
+
command.env !== undefined ||
|
|
91
|
+
command.auto_title !== undefined ||
|
|
92
|
+
command.retryFallback !== undefined ||
|
|
93
|
+
(owner !== undefined && host.writer.compactSelection(owner)?.selected))
|
|
94
|
+
return miss();
|
|
95
|
+
const profile = validatedOpenProfile(host, { ...command, type: "open_session" });
|
|
96
|
+
if ("type" in profile)
|
|
97
|
+
return { ...profile, command: command.type };
|
|
98
|
+
const key = profileKey(profile);
|
|
99
|
+
const opened = host.parks.take(key);
|
|
100
|
+
if (!opened)
|
|
101
|
+
return miss();
|
|
102
|
+
let success = false;
|
|
103
|
+
try {
|
|
104
|
+
const entry = host.registry.peek(opened.sessionId);
|
|
105
|
+
if (entry?.state !== "open" || !entry.runtime)
|
|
106
|
+
return miss();
|
|
107
|
+
const runtime = entry.runtime;
|
|
108
|
+
const ctx = { session: runtime.session, sessionId: opened.sessionId, by: { connectionId: owner ?? "host" } };
|
|
109
|
+
await runWithProviderScope(entry.scope, async () => {
|
|
110
|
+
const responses = [];
|
|
111
|
+
if (command.provider !== undefined && command.modelId !== undefined)
|
|
112
|
+
responses.push(await runSetModel(ctx, {
|
|
113
|
+
type: "set_model",
|
|
114
|
+
provider: command.provider,
|
|
115
|
+
modelId: command.modelId,
|
|
116
|
+
scope: "session",
|
|
117
|
+
}));
|
|
118
|
+
if (command.thinkingLevel !== undefined)
|
|
119
|
+
responses.push(await runSetThinkingLevel(ctx, {
|
|
120
|
+
type: "set_thinking_level",
|
|
121
|
+
level: command.thinkingLevel,
|
|
122
|
+
scope: "turn",
|
|
123
|
+
}));
|
|
124
|
+
if (command.permissionPreset !== undefined)
|
|
125
|
+
responses.push(runSetPermissionPreset(runtime, {
|
|
126
|
+
type: "set_permission_preset",
|
|
127
|
+
permissionPreset: command.permissionPreset,
|
|
128
|
+
}));
|
|
129
|
+
const refused = responses.find((response) => !response.success);
|
|
130
|
+
if (refused && !refused.success)
|
|
131
|
+
throw new Error(refused.error);
|
|
132
|
+
applyAttachedProfile(entry, { ...profile, permissionPreset: undefined, permissionPresetSource: undefined });
|
|
133
|
+
if (runtime.launchProfile)
|
|
134
|
+
entry.profile = runtime.launchProfile;
|
|
135
|
+
});
|
|
136
|
+
if (host.draining || host.drainExitRequested || (owner !== undefined && host.releasedConnections.has(owner)))
|
|
137
|
+
return miss();
|
|
138
|
+
const claimed = await host.registry.claimPark(opened.sessionId, command.retain_on_disconnect === true);
|
|
139
|
+
if (host.draining || host.drainExitRequested)
|
|
140
|
+
return miss();
|
|
141
|
+
entry.acceptance?.applyTranscript(runtime.session.sessionManager.drainTranscript());
|
|
142
|
+
ownOpen(host, claimed, owner);
|
|
143
|
+
host.bindings
|
|
144
|
+
.get(claimed.sessionId)
|
|
145
|
+
?.setClientCapabilities?.((owner === undefined ? undefined : host.pendingCapabilities.get(owner)) ??
|
|
146
|
+
host.connectionOptions?.capabilities ??
|
|
147
|
+
[]);
|
|
148
|
+
publishOpen(host, claimed, entry);
|
|
149
|
+
await syncRetainedRecord(host, claimed.sessionId, undefined);
|
|
150
|
+
replyOpen(host, claimed, entry, command);
|
|
151
|
+
success = true;
|
|
152
|
+
if (owner !== undefined && host.releasedConnections.has(owner)) {
|
|
153
|
+
releaseOwnerAttachment(host, owner, claimed.sessionId);
|
|
154
|
+
await releaseOwnedSession(host, claimed.sessionId);
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
catch (cause) {
|
|
159
|
+
return error(command.id, command.type, code(cause));
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
if (!success)
|
|
163
|
+
await closePark(host, opened);
|
|
164
|
+
host.parks.finish(key);
|
|
165
|
+
if (success) {
|
|
166
|
+
const replacement = {
|
|
167
|
+
type: "park_session",
|
|
168
|
+
cwd: command.cwd,
|
|
169
|
+
kind: command.kind,
|
|
170
|
+
context: command.context,
|
|
171
|
+
};
|
|
172
|
+
host.parks.replace(key, () => buildPark(host, replacement));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=session-router-park.js.map
|
|
@@ -7,7 +7,7 @@ import type { RouterContext } from "./session-router-context.ts";
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function handle(host: RouterContext, command: RpcCommand): Promise<RpcResponse | undefined>;
|
|
9
9
|
export declare function dispatch(host: RouterContext, command: Exclude<RpcCommand, {
|
|
10
|
-
type: "warm";
|
|
10
|
+
type: "warm" | "park_session";
|
|
11
11
|
}>): Promise<RpcResponse | undefined>;
|
|
12
12
|
/** Any attached connection may patch; a host with no per-connection identity (stdio) owns every session. */
|
|
13
13
|
export declare function setSessionContext(host: RouterContext, command: Extract<RpcCommand, {
|
|
@@ -24,6 +24,7 @@ import { answerListSessions, answerProtocolInfo, answerSubscriptionLimits } from
|
|
|
24
24
|
import { acknowledgePrompt, otherRequestsSettled } from "./session-router-observation.js";
|
|
25
25
|
import { sweepDrain } from "./session-router-occupancy.js";
|
|
26
26
|
import { openWithBarrier } from "./session-router-open.js";
|
|
27
|
+
import { claimSession, parkSession } from "./session-router-park.js";
|
|
27
28
|
import { syncRetainedRecord } from "./session-router-residency.js";
|
|
28
29
|
import { answerSetSessionContext, answerSubscribeSessions, answerUnsubscribeSessions, notAttachedRefusal, } from "./session-status-commands.js";
|
|
29
30
|
import { unloadSession } from "./session-unload.js";
|
|
@@ -42,6 +43,10 @@ export function handle(host, command) {
|
|
|
42
43
|
return ownership ? Promise.resolve(ownership) : admitted(host, command);
|
|
43
44
|
}
|
|
44
45
|
function admitted(host, command) {
|
|
46
|
+
if ("sessionId" in command && command.sessionId !== undefined && host.registry.peek(command.sessionId)?.speculative)
|
|
47
|
+
return Promise.resolve(error(command.id, command.type, "unknown_session"));
|
|
48
|
+
if (command.type === "park_session")
|
|
49
|
+
return parkSession(host, command);
|
|
45
50
|
const refusal = attachmentGate(host, command) ?? compactAdmissionGate(host, command);
|
|
46
51
|
if (refusal)
|
|
47
52
|
return Promise.resolve(refusal);
|
|
@@ -117,6 +122,8 @@ export async function dispatch(host, command) {
|
|
|
117
122
|
return detachConnection(command, host.writer.currentConnection(), (id) => releaseConnection(host, id));
|
|
118
123
|
if (command.type === "open_session")
|
|
119
124
|
return openWithBarrier(host, command);
|
|
125
|
+
if (command.type === "claim_session")
|
|
126
|
+
return claimSession(host, command);
|
|
120
127
|
if (command.type === "attach_session")
|
|
121
128
|
return attachSession(host, command);
|
|
122
129
|
if (command.type === "release_attachment")
|
|
@@ -63,11 +63,11 @@ export function registryStatusSource(registry) {
|
|
|
63
63
|
sessionIds: () => registry.list().map((row) => row.sessionId),
|
|
64
64
|
entryView: (sessionId) => {
|
|
65
65
|
const entry = registry.peek(sessionId);
|
|
66
|
-
return entry === undefined ? undefined : entryView(entry);
|
|
66
|
+
return entry === undefined || entry.speculative ? undefined : entryView(entry);
|
|
67
67
|
},
|
|
68
68
|
view: (sessionId) => {
|
|
69
69
|
const entry = registry.peek(sessionId);
|
|
70
|
-
if (entry === undefined)
|
|
70
|
+
if (entry === undefined || entry.speculative)
|
|
71
71
|
return undefined;
|
|
72
72
|
const runtime = runtimeView(entry);
|
|
73
73
|
return runtime === undefined ? { entry: entryView(entry) } : { entry: entryView(entry), runtime };
|
|
@@ -22,8 +22,8 @@ export declare function releaseStartupFillers(child: {
|
|
|
22
22
|
* them, see `withStartupPipe`) and removes their list from the hand-off, so a process this one re-executes or
|
|
23
23
|
* spawns never closes a descriptor that is not a filler. A slot the #4749 private table names is that
|
|
24
24
|
* channel's, never a filler, and stays open. A table that does not decode (the `unparseable` marker included)
|
|
25
|
-
* cannot prove any slot free of a channel, so no filler is closed.
|
|
26
|
-
* receive a hand-off.
|
|
25
|
+
* cannot prove any slot free of a channel, so no filler is closed. A slot that no longer holds its filler is
|
|
26
|
+
* the runtime's own and stays open (`inheritedFillerCheck`). Called first by every entry that can receive a hand-off.
|
|
27
27
|
*/
|
|
28
28
|
export declare function releaseInheritedStartupFillers(env: NodeJS.ProcessEnv): void;
|
|
29
29
|
//# sourceMappingURL=private-fd-startup-fillers.d.ts.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* the release of the ones this process inherited. Side-effect free and never imports `private-fds.ts`: the
|
|
4
4
|
* startup stub releases its fillers before that module adopts the table at import.
|
|
5
5
|
*/
|
|
6
|
-
import { closeSync } from "node:fs";
|
|
6
|
+
import { closeSync, fstatSync } from "node:fs";
|
|
7
7
|
import { HOST_STARTUP_EVENTS_ENV } from "./modes/rpc/host-identity-env.js";
|
|
8
8
|
import { encodeStartupHandOff, parseStartupHandOff, STARTUP_EVENT_FD } from "./modes/rpc/host-startup-wire.js";
|
|
9
9
|
import { decodePrivateFdTable, PRIVATE_FDS_TABLE_ENV } from "./private-fd-table.js";
|
|
@@ -53,13 +53,42 @@ function namedPrivateSlots(encoded) {
|
|
|
53
53
|
slots.add(fd);
|
|
54
54
|
return slots;
|
|
55
55
|
}
|
|
56
|
+
function statOf(fd) {
|
|
57
|
+
try {
|
|
58
|
+
return fstatSync(fd);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const sameFile = (a, b) => a.dev === b.dev && a.ino === b.ino;
|
|
65
|
+
/**
|
|
66
|
+
* Whether a listed slot still holds the filler the spawn put there. On POSIX a "pipe" slot is an AF_UNIX socketpair
|
|
67
|
+
* end under Node and Bun, and neither runtime holds a socket of its own this early; the startup pipe the same spawn
|
|
68
|
+
* placed at `STARTUP_EVENT_FD` must still be there too. A process that replaced its image between the spawn and this
|
|
69
|
+
* entry lost both, because Bun marks every inherited descriptor from 4 up close-on-exec at startup, and its runtime
|
|
70
|
+
* reuses the numbers: the compiled launcher's trust exec left Bun's own copies of stdout and stderr at 5 and 6, and
|
|
71
|
+
* closing them by number failed the host's first stderr write with EBADF (senpi#6282). Windows keeps the plain list.
|
|
72
|
+
*/
|
|
73
|
+
function inheritedFillerCheck() {
|
|
74
|
+
if (process.platform === "win32")
|
|
75
|
+
return () => true;
|
|
76
|
+
const startup = statOf(STARTUP_EVENT_FD);
|
|
77
|
+
if (!startup?.isSocket())
|
|
78
|
+
return () => false;
|
|
79
|
+
const kept = [startup, ...[0, 1, 2].map(statOf).filter((stat) => stat !== undefined)];
|
|
80
|
+
return (slot) => {
|
|
81
|
+
const stat = statOf(slot);
|
|
82
|
+
return stat !== undefined && stat.isSocket() && !kept.some((other) => sameFile(stat, other));
|
|
83
|
+
};
|
|
84
|
+
}
|
|
56
85
|
/**
|
|
57
86
|
* Closes the filler pipes this process inherited (they only kept libuv from aborting the spawn that created
|
|
58
87
|
* them, see `withStartupPipe`) and removes their list from the hand-off, so a process this one re-executes or
|
|
59
88
|
* spawns never closes a descriptor that is not a filler. A slot the #4749 private table names is that
|
|
60
89
|
* channel's, never a filler, and stays open. A table that does not decode (the `unparseable` marker included)
|
|
61
|
-
* cannot prove any slot free of a channel, so no filler is closed.
|
|
62
|
-
* receive a hand-off.
|
|
90
|
+
* cannot prove any slot free of a channel, so no filler is closed. A slot that no longer holds its filler is
|
|
91
|
+
* the runtime's own and stays open (`inheritedFillerCheck`). Called first by every entry that can receive a hand-off.
|
|
63
92
|
*/
|
|
64
93
|
export function releaseInheritedStartupFillers(env) {
|
|
65
94
|
const handOff = parseStartupHandOff(env[HOST_STARTUP_EVENTS_ENV]);
|
|
@@ -67,8 +96,9 @@ export function releaseInheritedStartupFillers(env) {
|
|
|
67
96
|
return;
|
|
68
97
|
const privateSlots = namedPrivateSlots(env[PRIVATE_FDS_TABLE_ENV]);
|
|
69
98
|
if (privateSlots) {
|
|
99
|
+
const inherited = inheritedFillerCheck();
|
|
70
100
|
for (const slot of handOff.fillers) {
|
|
71
|
-
if (privateSlots.has(slot))
|
|
101
|
+
if (privateSlots.has(slot) || !inherited(slot))
|
|
72
102
|
continue;
|
|
73
103
|
try {
|
|
74
104
|
closeSync(slot);
|
package/dist/senpi
CHANGED
|
@@ -26,6 +26,7 @@ import { dispatchKillGuardCommand } from "./cli/kill-guard-command.js";
|
|
|
26
26
|
import { enableStartupCompileCache } from "./compile-cache.js";
|
|
27
27
|
import { APP_NAME, DISPLAY_VERSION, findNodePackageDir, getAgentDir, getInstallPackageDir, isBundledNode, } from "./config.js";
|
|
28
28
|
import { hasInheritedInspectorOption, releaseInheritedInspectorForChild } from "./inspector-policy.js";
|
|
29
|
+
import { runtimeExecArgv } from "./utils/runtime-exec-argv.js";
|
|
29
30
|
import { prepareRuntimeSnapshot } from "./runtime-snapshot/enter.js";
|
|
30
31
|
import { handleBootstrapSelfUpdate } from "./self-update-bootstrap.js";
|
|
31
32
|
import { preparePrivateFdSpawn, spawnWithPrivateFds } from "./private-fd-spawn.js";
|
|
@@ -172,7 +173,9 @@ function requiresIsolatedProcess() {
|
|
|
172
173
|
// same exec arguments and spawn again forever. The marker is read before anything else runs.
|
|
173
174
|
if (process.env[ISOLATED_CHILD_ENV] === "1")
|
|
174
175
|
return false;
|
|
175
|
-
|
|
176
|
+
// Decide on the sanitized argv (senpi#2952): the caller's entry mode (-e/-p/-i and friends) is
|
|
177
|
+
// not a runtime option, so an eval caller alone must not force an isolated re-launch.
|
|
178
|
+
return runtimeExecArgv().length > 0 || hasInheritedInspectorOption();
|
|
176
179
|
}
|
|
177
180
|
async function spawnFullCli() {
|
|
178
181
|
const extension = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
|
|
@@ -184,9 +187,12 @@ async function spawnFullCli() {
|
|
|
184
187
|
? fileURLToPath(import.meta.url)
|
|
185
188
|
: fileURLToPath(new URL(`./cli-main${extension}`, import.meta.url));
|
|
186
189
|
releaseInheritedInspectorForChild();
|
|
187
|
-
|
|
190
|
+
// The child carries the caller's runtime options but never its entry mode (senpi#2952): forwarding
|
|
191
|
+
// raw execArgv replayed a `node -e` caller in the child. Both entries get the isolation marker so
|
|
192
|
+
// a re-entered cli.ts loads the agent in process instead of spawning again.
|
|
193
|
+
const childEnvironment = { ...process.env, [ISOLATED_CHILD_ENV]: "1" };
|
|
188
194
|
return await new Promise((resolve, reject) => {
|
|
189
|
-
const child = spawnWithPrivateFds(spawn, process.execPath, [...
|
|
195
|
+
const child = spawnWithPrivateFds(spawn, process.execPath, [...runtimeExecArgv(), fullCliPath, ...args], {
|
|
190
196
|
env: childEnvironment,
|
|
191
197
|
stdio: reexecStdio(),
|
|
192
198
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"rpcClientRequests": "{\"type\":\"get_protocol_info\",\"id\":\"rpc-auth-protocol\",\"observe\":true,\"auth\":{\"client_nonce\":\"<public-nonce>\"}}\n{\"type\":\"set_client_info\",\"width\":100,\"capabilities\":[],\"id\":\"req_1\"}\n{\"type\":\"open_session\",\"cwd\":\"<root>/cwd\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"id\":\"req_2\"}\n{\"type\":\"get_entries\",\"sessionId\":\"rpc-1\",\"id\":\"req_3\"}\n{\"type\":\"close_session\",\"sessionId\":\"rpc-1\",\"id\":\"req_4\"}\n",
|
|
3
|
-
"rpcClientFrames": "{\"id\":\"rpc-auth-protocol\",\"type\":\"response\",\"command\":\"get_protocol_info\",\"success\":true,\"data\":{\"protocolVersion\":1,\"serverVersion\":\"<server-version>\",\"capabilities\":[\"<capabilities>\"],\"mode\":\"multi\",\"instanceId\":\"<uuid-1>\",\"generation\":0,\"engineVersion\":\"<server-version>\",\"engineOrdinal\":\"<engine-ordinal>\",\"launch_profile\":{\"profile_id\":\"ca7a49435f02009fdda5dac49d29408dcfeb1ab5374353784c5a9def467f5be1\",\"core\":{\"extensions\":[],\"multi_session\":false,\"session_runtime\":\"worker\"}},\"agentDir\":\"<root>/agent\",\"method_classes\":{\"version\":1,\"digest\":\"7ea18de0fb5d28f89aabdc17cbaca72e973cdea7d5928fd82d91ccced025000e\",\"classes\":{\"get_protocol_info\":\"observe\",\"get_subscription_limits\":\"observe\",\"list_sessions\":\"observe\",\"list_hands\":\"observe\",\"get_state\":\"observe\",\"get_snapshot\":\"observe\",\"get_entries\":\"observe\",\"get_messages\":\"observe\",\"get_tree\":\"observe\",\"get_fork_messages\":\"observe\",\"get_last_assistant_text\":\"observe\",\"get_session_stats\":\"observe\",\"get_effect_status\":\"dynamic\",\"get_pending_inputs\":\"observe\",\"get_follow_up_messages\":\"observe\",\"get_steering_messages\":\"observe\",\"get_commands\":\"observe\",\"get_loaded_surfaces\":\"observe\",\"get_project_trust\":\"observe\",\"get_available_models\":\"observe\",\"get_available_thinking_levels\":\"observe\",\"get_model_thinking_level\":\"observe\",\"get_fast_mode\":\"observe\",\"get_media\":\"observe\",\"memory_report\":\"observe\",\"eval_cells.list\":\"observe\",\"eval_cells.peek\":\"observe\",\"prompt\":\"dynamic\",\"steer\":\"dynamic\",\"follow_up\":\"dynamic\",\"abort\":\"drive\",\"interrupt\":\"drive\",\"abort_retry\":\"drive\",\"abort_compaction\":\"drive\",\"abort_branch_summary\":\"drive\",\"compact\":\"drive\",\"clear_queue\":\"drive\",\"dequeue_message\":\"drive\",\"edit_queued_message\":\"drive\",\"hold_input\":\"drive\",\"withdraw_held_input\":\"drive\",\"append_user_message\":\"drive\",\"edit_user_message\":\"drive\",\"continue_from_leaf\":\"drive\",\"navigate_tree\":\"drive\",\"set_label\":\"drive\",\"set_session_name\":\"drive\",\"set_thinking_level\":\"dynamic\",\"set_model\":\"dynamic\",\"set_auto_compaction\":\"drive\",\"set_permission_preset\":\"device_admin\",\"set_retry_fallback\":\"drive\",\"pause_for_run\":\"drive\",\"resume_for_run\":\"drive\",\"wake\":\"drive\",\"admit_external_message\":\"drive\",\"release_tool_barrier\":\"drive\",\"request_self_settle\":\"drive\",\"eval_cells.stop\":\"drive\",\"append_session_entry\":\"dynamic\",\"extension_ui_response\":\"answer\",\"extension_ui_progress\":\"answer\",\"new_session\":\"dynamic\",\"open_session\":\"dynamic\",\"resume_session\":\"thread\",\"fork\":\"thread\",\"clone\":\"thread\",\"close_session\":\"thread\",\"unload_session\":\"thread\",\"set_session_context\":\"thread\",\"attach_session\":\"thread\",\"select_hand\":\"device_admin\",\"bash\":\"device_admin\",\"abort_bash\":\"device_admin\",\"record_bash_result\":\"device_admin\",\"cleanup_bash_output\":\"device_admin\",\"extension_request\":\"device_admin\",\"reload\":\"device_admin\",\"check_reload_veto\":\"device_admin\",\"resolve_path\":\"device_admin\",\"login_start\":\"device_admin\",\"login_cancel\":\"device_admin\",\"login_api_key\":\"device_admin\",\"logout\":\"device_admin\",\"verify_api_key\":\"device_admin\",\"get_auth_providers\":\"device_admin\",\"get_provider_accounts\":\"device_admin\",\"account_order\":\"device_admin\",\"account_pin\":\"device_admin\",\"account_remove\":\"device_admin\",\"account_reset\":\"device_admin\",\"test_provider_account\":\"device_admin\",\"set_favorite_models\":\"device_admin\",\"set_scoped_models\":\"device_admin\",\"cycle_model\":\"device_admin\",\"cycle_thinking_level\":\"device_admin\",\"set_fast_mode\":\"device_admin\",\"set_steering_mode\":\"device_admin\",\"set_follow_up_mode\":\"device_admin\",\"set_auto_retry\":\"device_admin\",\"set_project_trust\":\"device_admin\",\"get_project_settings\":\"device_admin\",\"set_project_setting\":\"device_admin\",\"edit_assistant_message\":\"device_admin\",\"send_custom_message\":\"device_admin\",\"switch_session\":\"device_admin\",\"import_jsonl\":\"device_admin\",\"export_html\":\"device_admin\",\"export_jsonl\":\"device_admin\",\"set_client_info\":\"connection_local\",\"subscribe_sessions\":\"connection_local\",\"unsubscribe_sessions\":\"connection_local\",\"record_user_activity\":\"connection_local\",\"detach_connection\":\"connection_local\",\"release_session\":\"connection_local\",\"warm\":\"connection_local\",\"host_response\":\"connection_local\",\"release_attachment\":\"connection_local\",\"reclaim_session\":\"connection_local\",\"move_session\":\"connection_local\",\"get_recovery_page\":\"connection_local\",\"release_recovery\":\"connection_local\",\"cancel_attempt\":\"connection_local\",\"reset_stream\":\"connection_local\"},\"dynamic_versions\":{\"get_effect_status\":1,\"prompt\":1,\"steer\":1,\"follow_up\":1,\"set_thinking_level\":1,\"set_model\":1,\"append_session_entry\":1,\"new_session\":1,\"open_session\":2}},\"memory_pressure\":false,\"path_identity_resolver\":{\"state\":\"not_started\",\"detail\":null}}}\n{\"id\":\"req_1\",\"type\":\"response\",\"command\":\"set_client_info\",\"success\":true}\n{\"type\":\"queued\",\"for_request\":\"req_2\",\"position\":1,\"in_flight\":0}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-2>\",\"method\":\"setWidget\",\"widgetKey\":\"todo-sidebar\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-3>\",\"method\":\"setStatus\",\"statusKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-4>\",\"method\":\"setWidget\",\"widgetKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-5>\",\"method\":\"setStatus\",\"statusKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-6>\",\"method\":\"setWidget\",\"widgetKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-7>\",\"method\":\"setStatus\",\"statusKey\":\"monitors\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-8>\",\"method\":\"setStatus\",\"statusKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-9>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-10>\",\"method\":\"setStatus\",\"statusKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-11>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"entry_appended\",\"entry\":{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-12>\",\"method\":\"setStatus\",\"statusKey\":\"todo-waiting\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-13>\",\"method\":\"setStatus\",\"statusKey\":\"goal\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_opened\",\"sessionId\":\"rpc-1\",\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\"}\n{\"id\":\"req_2\",\"type\":\"response\",\"command\":\"open_session\",\"success\":true,\"data\":{\"sessionId\":\"rpc-1\",\"state\":{\"answeredUiRequests\":[],\"paused\":false,\"pausedNoticeCount\":0,\"holds\":[],\"lifecycle\":{\"state\":\"done\",\"seq\":0,\"epoch\":0,\"epochOrigin\":\"automatic\",\"humanInputRevision\":0,\"selfSettleEligible\":true,\"restoring\":false,\"persisted\":false,\"runPaused\":false,\"since\":\"2026-10-29T00:00:00.000Z\",\"role\":\"root\",\"rootSessionId\":\"<uuid-14>\",\"activityRevision\":{\"instanceId\":\"<uuid-15>\",\"revision\":0},\"waitingOn\":{\"children\":0,\"background\":[],\"human\":[]},\"holds\":[],\"observedAt\":\"2026-10-29T00:00:00.000Z\"},\"pendingQuestions\":[],\"pendingDialogs\":[],\"permissionPreset\":\"full-access\",\"permissionPresetSource\":\"host_default\",\"permissionPresetStatus\":\"applied\",\"effectivePermissionPreset\":\"full-access\",\"model\":{\"id\":\"faux-a\",\"name\":\"faux-a\",\"api\":\"faux:fixture\",\"provider\":\"faux\",\"baseUrl\":\"http://localhost:0\",\"reasoning\":false,\"input\":[\"text\",\"image\"],\"cost\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0},\"contextWindow\":128000,\"maxTokens\":16384},\"pendingModelSwitch\":null,\"thinkingLevel\":\"off\",\"thinkingLevelSource\":\"default\",\"sessionModelThinkingLevels\":{\"faux/faux-a\":\"off\"},\"fastMode\":false,\"isStreaming\":false,\"pausedHeldInputCount\":0,\"runPaused\":false,\"pause\":{\"pauseSeq\":0,\"records\":[]},\"isCompacting\":false,\"retryAttempt\":0,\"isBashRunning\":false,\"steeringMode\":\"all\",\"followUpMode\":\"one-at-a-time\",\"sessionFile\":\"<root>/cwd/session.jsonl\",\"sessionId\":\"<uuid-14>\",\"cwd\":\"<root>/cwd\",\"projectTrusted\":false,\"entries\":[{\"type\":\"model_change\",\"id\":\"<entry-3>\",\"parentId\":null,\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"thinking_level_change\",\"id\":\"<entry-2>\",\"parentId\":\"<entry-3>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"thinkingLevel\":\"off\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"}],\"steering\":[],\"followUp\":[],\"ordered\":[],\"autoCompactionEnabled\":true,\"messageCount\":0,\"pendingMessageCount\":0,\"usageTotals\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"cost\":0},\"contextUsage\":{\"tokens\":0,\"contextWindow\":128000,\"percent\":0},\"favoriteModels\":[],\"scopedModels\":[]},\"permissionPreset\":\"full-access\",\"permissionPresetSource\":\"host_default\",\"permissionPresetStatus\":\"applied\"},\"sessionId\":\"rpc-1\"}\n{\"id\":\"req_3\",\"type\":\"response\",\"command\":\"get_entries\",\"success\":true,\"data\":{\"entries\":[{\"type\":\"model_change\",\"id\":\"<entry-3>\",\"parentId\":null,\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"thinking_level_change\",\"id\":\"<entry-2>\",\"parentId\":\"<entry-3>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"thinkingLevel\":\"off\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"}],\"leafId\":\"<entry-1>\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_closed\",\"sessionId\":\"rpc-1\",\"reason\":\"client_close\"}\n{\"id\":\"req_4\",\"type\":\"response\",\"command\":\"close_session\",\"success\":true,\"data\":{},\"sessionId\":\"rpc-1\"}\n",
|
|
3
|
+
"rpcClientFrames": "{\"id\":\"rpc-auth-protocol\",\"type\":\"response\",\"command\":\"get_protocol_info\",\"success\":true,\"data\":{\"protocolVersion\":1,\"serverVersion\":\"<server-version>\",\"capabilities\":[\"<capabilities>\"],\"mode\":\"multi\",\"instanceId\":\"<uuid-1>\",\"generation\":0,\"engineVersion\":\"<server-version>\",\"engineOrdinal\":\"<engine-ordinal>\",\"launch_profile\":{\"profile_id\":\"ca7a49435f02009fdda5dac49d29408dcfeb1ab5374353784c5a9def467f5be1\",\"core\":{\"extensions\":[],\"multi_session\":false,\"session_runtime\":\"worker\"}},\"agentDir\":\"<root>/agent\",\"method_classes\":{\"version\":1,\"digest\":\"bca41dd6cac2eff3dc82c24d763e4143d90f44ee75920da9bca1c2c8a98c5156\",\"classes\":{\"get_protocol_info\":\"observe\",\"get_subscription_limits\":\"observe\",\"list_sessions\":\"observe\",\"list_hands\":\"observe\",\"get_state\":\"observe\",\"get_snapshot\":\"observe\",\"get_entries\":\"observe\",\"get_messages\":\"observe\",\"get_tree\":\"observe\",\"get_fork_messages\":\"observe\",\"get_last_assistant_text\":\"observe\",\"get_session_stats\":\"observe\",\"get_effect_status\":\"dynamic\",\"get_pending_inputs\":\"observe\",\"get_follow_up_messages\":\"observe\",\"get_steering_messages\":\"observe\",\"get_commands\":\"observe\",\"get_loaded_surfaces\":\"observe\",\"get_project_trust\":\"observe\",\"get_available_models\":\"observe\",\"get_available_thinking_levels\":\"observe\",\"get_model_thinking_level\":\"observe\",\"get_fast_mode\":\"observe\",\"get_media\":\"observe\",\"memory_report\":\"observe\",\"eval_cells.list\":\"observe\",\"eval_cells.peek\":\"observe\",\"prompt\":\"dynamic\",\"steer\":\"dynamic\",\"follow_up\":\"dynamic\",\"abort\":\"drive\",\"interrupt\":\"drive\",\"abort_retry\":\"drive\",\"abort_compaction\":\"drive\",\"abort_branch_summary\":\"drive\",\"compact\":\"drive\",\"clear_queue\":\"drive\",\"dequeue_message\":\"drive\",\"edit_queued_message\":\"drive\",\"hold_input\":\"drive\",\"withdraw_held_input\":\"drive\",\"append_user_message\":\"drive\",\"edit_user_message\":\"drive\",\"continue_from_leaf\":\"drive\",\"navigate_tree\":\"drive\",\"set_label\":\"drive\",\"set_session_name\":\"drive\",\"set_thinking_level\":\"dynamic\",\"set_model\":\"dynamic\",\"set_auto_compaction\":\"drive\",\"set_permission_preset\":\"device_admin\",\"set_retry_fallback\":\"drive\",\"pause_for_run\":\"drive\",\"resume_for_run\":\"drive\",\"wake\":\"drive\",\"admit_external_message\":\"drive\",\"release_tool_barrier\":\"drive\",\"request_self_settle\":\"drive\",\"eval_cells.stop\":\"drive\",\"append_session_entry\":\"dynamic\",\"extension_ui_response\":\"answer\",\"extension_ui_progress\":\"answer\",\"new_session\":\"dynamic\",\"open_session\":\"dynamic\",\"claim_session\":\"device_admin\",\"park_session\":\"device_admin\",\"resume_session\":\"thread\",\"fork\":\"thread\",\"clone\":\"thread\",\"close_session\":\"thread\",\"unload_session\":\"thread\",\"set_session_context\":\"thread\",\"attach_session\":\"thread\",\"select_hand\":\"device_admin\",\"bash\":\"device_admin\",\"abort_bash\":\"device_admin\",\"record_bash_result\":\"device_admin\",\"cleanup_bash_output\":\"device_admin\",\"extension_request\":\"device_admin\",\"reload\":\"device_admin\",\"check_reload_veto\":\"device_admin\",\"resolve_path\":\"device_admin\",\"login_start\":\"device_admin\",\"login_cancel\":\"device_admin\",\"login_api_key\":\"device_admin\",\"logout\":\"device_admin\",\"verify_api_key\":\"device_admin\",\"get_auth_providers\":\"device_admin\",\"get_provider_accounts\":\"device_admin\",\"account_order\":\"device_admin\",\"account_pin\":\"device_admin\",\"account_remove\":\"device_admin\",\"account_reset\":\"device_admin\",\"test_provider_account\":\"device_admin\",\"set_favorite_models\":\"device_admin\",\"set_scoped_models\":\"device_admin\",\"cycle_model\":\"device_admin\",\"cycle_thinking_level\":\"device_admin\",\"set_fast_mode\":\"device_admin\",\"set_steering_mode\":\"device_admin\",\"set_follow_up_mode\":\"device_admin\",\"set_auto_retry\":\"device_admin\",\"set_project_trust\":\"device_admin\",\"get_project_settings\":\"device_admin\",\"set_project_setting\":\"device_admin\",\"read_project_file\":\"device_admin\",\"write_project_file\":\"device_admin\",\"edit_assistant_message\":\"device_admin\",\"send_custom_message\":\"device_admin\",\"switch_session\":\"device_admin\",\"import_jsonl\":\"device_admin\",\"export_html\":\"device_admin\",\"export_jsonl\":\"device_admin\",\"set_client_info\":\"connection_local\",\"subscribe_sessions\":\"connection_local\",\"unsubscribe_sessions\":\"connection_local\",\"record_user_activity\":\"connection_local\",\"detach_connection\":\"connection_local\",\"release_session\":\"connection_local\",\"warm\":\"connection_local\",\"host_response\":\"connection_local\",\"release_attachment\":\"connection_local\",\"reclaim_session\":\"connection_local\",\"move_session\":\"connection_local\",\"get_recovery_page\":\"connection_local\",\"release_recovery\":\"connection_local\",\"cancel_attempt\":\"connection_local\",\"reset_stream\":\"connection_local\"},\"dynamic_versions\":{\"get_effect_status\":1,\"prompt\":1,\"steer\":1,\"follow_up\":1,\"set_thinking_level\":1,\"set_model\":1,\"append_session_entry\":1,\"new_session\":1,\"open_session\":2}},\"memory_pressure\":false,\"path_identity_resolver\":{\"state\":\"not_started\",\"detail\":null}}}\n{\"id\":\"req_1\",\"type\":\"response\",\"command\":\"set_client_info\",\"success\":true}\n{\"type\":\"queued\",\"for_request\":\"req_2\",\"position\":1,\"in_flight\":0}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-2>\",\"method\":\"setWidget\",\"widgetKey\":\"todo-sidebar\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-3>\",\"method\":\"setStatus\",\"statusKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-4>\",\"method\":\"setWidget\",\"widgetKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-5>\",\"method\":\"setStatus\",\"statusKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-6>\",\"method\":\"setWidget\",\"widgetKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-7>\",\"method\":\"setStatus\",\"statusKey\":\"monitors\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-8>\",\"method\":\"setStatus\",\"statusKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-9>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-10>\",\"method\":\"setStatus\",\"statusKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-11>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"entry_appended\",\"entry\":{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-12>\",\"method\":\"setStatus\",\"statusKey\":\"todo-waiting\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-13>\",\"method\":\"setStatus\",\"statusKey\":\"goal\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_opened\",\"sessionId\":\"rpc-1\",\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\"}\n{\"id\":\"req_2\",\"type\":\"response\",\"command\":\"open_session\",\"success\":true,\"data\":{\"sessionId\":\"rpc-1\",\"state\":{\"answeredUiRequests\":[],\"paused\":false,\"pausedNoticeCount\":0,\"holds\":[],\"lifecycle\":{\"state\":\"done\",\"seq\":0,\"epoch\":0,\"epochOrigin\":\"automatic\",\"humanInputRevision\":0,\"selfSettleEligible\":true,\"restoring\":false,\"persisted\":false,\"runPaused\":false,\"since\":\"2026-10-29T00:00:00.000Z\",\"role\":\"root\",\"rootSessionId\":\"<uuid-14>\",\"activityRevision\":{\"instanceId\":\"<uuid-15>\",\"revision\":0},\"waitingOn\":{\"children\":0,\"background\":[],\"human\":[]},\"holds\":[],\"observedAt\":\"2026-10-29T00:00:00.000Z\"},\"pendingQuestions\":[],\"pendingDialogs\":[],\"permissionPreset\":\"full-access\",\"permissionPresetSource\":\"host_default\",\"permissionPresetStatus\":\"applied\",\"effectivePermissionPreset\":\"full-access\",\"model\":{\"id\":\"faux-a\",\"name\":\"faux-a\",\"api\":\"faux:fixture\",\"provider\":\"faux\",\"baseUrl\":\"http://localhost:0\",\"reasoning\":false,\"input\":[\"text\",\"image\"],\"cost\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0},\"contextWindow\":128000,\"maxTokens\":16384},\"pendingModelSwitch\":null,\"thinkingLevel\":\"off\",\"thinkingLevelSource\":\"default\",\"sessionModelThinkingLevels\":{\"faux/faux-a\":\"off\"},\"fastMode\":false,\"isStreaming\":false,\"pausedHeldInputCount\":0,\"runPaused\":false,\"pause\":{\"pauseSeq\":0,\"records\":[]},\"isCompacting\":false,\"retryAttempt\":0,\"isBashRunning\":false,\"steeringMode\":\"all\",\"followUpMode\":\"one-at-a-time\",\"sessionFile\":\"<root>/cwd/session.jsonl\",\"sessionId\":\"<uuid-14>\",\"cwd\":\"<root>/cwd\",\"projectTrusted\":false,\"entries\":[{\"type\":\"model_change\",\"id\":\"<entry-3>\",\"parentId\":null,\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"thinking_level_change\",\"id\":\"<entry-2>\",\"parentId\":\"<entry-3>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"thinkingLevel\":\"off\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"}],\"steering\":[],\"followUp\":[],\"ordered\":[],\"autoCompactionEnabled\":true,\"messageCount\":0,\"pendingMessageCount\":0,\"usageTotals\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"cost\":0},\"contextUsage\":{\"tokens\":0,\"contextWindow\":128000,\"percent\":0},\"favoriteModels\":[],\"scopedModels\":[]},\"permissionPreset\":\"full-access\",\"permissionPresetSource\":\"host_default\",\"permissionPresetStatus\":\"applied\"},\"sessionId\":\"rpc-1\"}\n{\"id\":\"req_3\",\"type\":\"response\",\"command\":\"get_entries\",\"success\":true,\"data\":{\"entries\":[{\"type\":\"model_change\",\"id\":\"<entry-3>\",\"parentId\":null,\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"thinking_level_change\",\"id\":\"<entry-2>\",\"parentId\":\"<entry-3>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"thinkingLevel\":\"off\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"}],\"leafId\":\"<entry-1>\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_closed\",\"sessionId\":\"rpc-1\",\"reason\":\"client_close\"}\n{\"id\":\"req_4\",\"type\":\"response\",\"command\":\"close_session\",\"success\":true,\"data\":{},\"sessionId\":\"rpc-1\"}\n",
|
|
4
4
|
"subscribeRequests": "{\"type\":\"subscribe_sessions\",\"mirror\":\"all\",\"id\":\"subscriber-1\"}\n{\"type\":\"unsubscribe_sessions\",\"subscriptionId\":\"sub-1\",\"id\":\"subscriber-2\"}\n",
|
|
5
5
|
"subscribeFrames": "{\"id\":\"subscriber-1\",\"type\":\"response\",\"command\":\"subscribe_sessions\",\"success\":true,\"data\":{\"subscriptionId\":\"sub-1\",\"snapshot\":[],\"seq\":0,\"hostGeneration\":\"0\",\"hostInstanceId\":\"<uuid-1>\"}}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-2>\",\"method\":\"setWidget\",\"widgetKey\":\"todo-sidebar\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-3>\",\"method\":\"setStatus\",\"statusKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-4>\",\"method\":\"setWidget\",\"widgetKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-5>\",\"method\":\"setStatus\",\"statusKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-6>\",\"method\":\"setWidget\",\"widgetKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-7>\",\"method\":\"setStatus\",\"statusKey\":\"monitors\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-8>\",\"method\":\"setStatus\",\"statusKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-9>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-10>\",\"method\":\"setStatus\",\"statusKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-11>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"entry_appended\",\"entry\":{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-12>\",\"method\":\"setStatus\",\"statusKey\":\"todo-waiting\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-13>\",\"method\":\"setStatus\",\"statusKey\":\"goal\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_opened\",\"sessionId\":\"rpc-1\",\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\"}\n{\"type\":\"session_status\",\"subscriptionId\":\"sub-1\",\"seq\":1,\"sessionId\":\"rpc-1\",\"status\":\"idle\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\",\"attachments\":1,\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"model\":{\"provider\":\"faux\",\"id\":\"faux-a\"},\"thinkingLevel\":\"off\",\"pendingQueue\":{\"steering\":0,\"followUp\":0},\"lastChange\":{\"at\":\"2026-10-29T00:00:00.000Z\",\"cause\":\"open\",\"by\":\"client\"}}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-15>\",\"method\":\"setStatus\",\"statusKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-16>\",\"method\":\"setWidget\",\"widgetKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-17>\",\"method\":\"setStatus\",\"statusKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-18>\",\"method\":\"setWidget\",\"widgetKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-19>\",\"method\":\"setStatus\",\"statusKey\":\"monitors\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-20>\",\"method\":\"setStatus\",\"statusKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-21>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-22>\",\"method\":\"setStatus\",\"statusKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-23>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-24>\",\"method\":\"setStatus\",\"statusKey\":\"loop\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_closed\",\"sessionId\":\"rpc-1\",\"reason\":\"client_close\"}\n{\"type\":\"session_status\",\"subscriptionId\":\"sub-1\",\"seq\":2,\"sessionId\":\"rpc-1\",\"status\":\"closed\",\"reason\":\"client_close\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\",\"attachments\":1,\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"model\":{\"provider\":\"faux\",\"id\":\"faux-a\"},\"thinkingLevel\":\"off\",\"pendingQueue\":{\"steering\":0,\"followUp\":0},\"lastChange\":{\"at\":\"2026-10-29T00:00:00.000Z\",\"cause\":\"close\",\"by\":\"client\"}}\n{\"id\":\"subscriber-2\",\"type\":\"response\",\"command\":\"unsubscribe_sessions\",\"success\":true}\n"
|
|
6
6
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"methodClassesVersion": 1,
|
|
3
|
-
"methodClassesDigest": "
|
|
3
|
+
"methodClassesDigest": "bca41dd6cac2eff3dc82c24d763e4143d90f44ee75920da9bca1c2c8a98c5156",
|
|
4
4
|
"sampleId": "00000000-0000-7000-8000-000000000000",
|
|
5
5
|
"samplePathRoot": "/nonexistent/senpi-rpc-inbound-sample",
|
|
6
|
-
"methodCount":
|
|
6
|
+
"methodCount": 128,
|
|
7
7
|
"methods": [
|
|
8
8
|
{
|
|
9
9
|
"method": "abort",
|
|
@@ -182,6 +182,16 @@
|
|
|
182
182
|
"type": "check_reload_veto"
|
|
183
183
|
}
|
|
184
184
|
},
|
|
185
|
+
{
|
|
186
|
+
"method": "claim_session",
|
|
187
|
+
"class": "device_admin",
|
|
188
|
+
"sampleClass": "device_admin",
|
|
189
|
+
"connectionLocal": false,
|
|
190
|
+
"sample": {
|
|
191
|
+
"type": "claim_session",
|
|
192
|
+
"cwd": "/nonexistent/senpi-rpc-inbound-sample/cwd"
|
|
193
|
+
}
|
|
194
|
+
},
|
|
185
195
|
{
|
|
186
196
|
"method": "cleanup_bash_output",
|
|
187
197
|
"class": "device_admin",
|
|
@@ -807,6 +817,16 @@
|
|
|
807
817
|
"type": "open_session"
|
|
808
818
|
}
|
|
809
819
|
},
|
|
820
|
+
{
|
|
821
|
+
"method": "park_session",
|
|
822
|
+
"class": "device_admin",
|
|
823
|
+
"sampleClass": "device_admin",
|
|
824
|
+
"connectionLocal": false,
|
|
825
|
+
"sample": {
|
|
826
|
+
"type": "park_session",
|
|
827
|
+
"cwd": "/nonexistent/senpi-rpc-inbound-sample/cwd"
|
|
828
|
+
}
|
|
829
|
+
},
|
|
810
830
|
{
|
|
811
831
|
"method": "pause_for_run",
|
|
812
832
|
"class": "drive",
|
|
@@ -833,6 +853,16 @@
|
|
|
833
853
|
"message": "Sample prompt."
|
|
834
854
|
}
|
|
835
855
|
},
|
|
856
|
+
{
|
|
857
|
+
"method": "read_project_file",
|
|
858
|
+
"class": "device_admin",
|
|
859
|
+
"sampleClass": "device_admin",
|
|
860
|
+
"connectionLocal": false,
|
|
861
|
+
"sample": {
|
|
862
|
+
"type": "read_project_file",
|
|
863
|
+
"path": "/nonexistent/senpi-rpc-inbound-sample/AGENTS.md"
|
|
864
|
+
}
|
|
865
|
+
},
|
|
836
866
|
{
|
|
837
867
|
"method": "reclaim_session",
|
|
838
868
|
"class": "connection_local",
|
|
@@ -1289,6 +1319,18 @@
|
|
|
1289
1319
|
"type": "withdraw_held_input",
|
|
1290
1320
|
"inputId": "00000000-0000-7000-8000-000000000000"
|
|
1291
1321
|
}
|
|
1322
|
+
},
|
|
1323
|
+
{
|
|
1324
|
+
"method": "write_project_file",
|
|
1325
|
+
"class": "device_admin",
|
|
1326
|
+
"sampleClass": "device_admin",
|
|
1327
|
+
"connectionLocal": false,
|
|
1328
|
+
"sample": {
|
|
1329
|
+
"type": "write_project_file",
|
|
1330
|
+
"path": "/nonexistent/senpi-rpc-inbound-sample/AGENTS.md",
|
|
1331
|
+
"content": "# Rules\n",
|
|
1332
|
+
"ifEtag": null
|
|
1333
|
+
}
|
|
1292
1334
|
}
|
|
1293
1335
|
]
|
|
1294
1336
|
}
|
package/docs/extensions.md
CHANGED
|
@@ -139,7 +139,7 @@ Use quick-set in non-TUI modes; the no-argument menu requires interactive UI. Pa
|
|
|
139
139
|
|
|
140
140
|
Senpi ships built-in extensions that inject provider-native server tools when the active model supports them. These run as ordinary extensions internally but are always loaded and require no user configuration beyond having valid credentials.
|
|
141
141
|
|
|
142
|
-
**openai-image-gen** injects the OpenAI Responses `image_generation` server tool when the model uses `openai-responses` on `api.openai.com`. It arbitrates against the client-side `generate_image` function tool so exactly one image surface is offered per request. A `message_end` handler decodes completed image results, writes them to `generated-images/`, and replaces the provider-native block with a text path reference before session persistence, so base64 payloads never reach the session file. Set `PI_OPENAI_IMAGE_GEN=false` to force the client tool path. Azure Responses endpoints default to the client tool unless `compat.supportsImageGeneration` opts in.
|
|
142
|
+
**openai-image-gen** injects the OpenAI Responses `image_generation` server tool when the model uses `openai-responses` on `api.openai.com`. It arbitrates against the client-side `generate_image` function tool so exactly one image surface is offered per request. `generate_image` itself is eval-only like `bash` (`exposure: "eval"`): whenever an `eval` tool is registered it is withheld from the model's direct tool list and called as `tool.generate_image({ prompt: "..." })` inside a cell; without an eval tool it is an ordinary direct tool. A `message_end` handler decodes completed image results, writes them to `generated-images/`, and replaces the provider-native block with a text path reference before session persistence, so base64 payloads never reach the session file. Set `PI_OPENAI_IMAGE_GEN=false` to force the client tool path. Azure Responses endpoints default to the client tool unless `compat.supportsImageGeneration` opts in.
|
|
143
143
|
|
|
144
144
|
**openai-web-search** injects the OpenAI Responses `web_search_preview` server tool following the same pattern: credential-gated, stripped on unsupported endpoints, arbitrated against its client-side counterpart.
|
|
145
145
|
|
|
@@ -1075,6 +1075,16 @@ pi.on("before_provider_request", (event, ctx) => {
|
|
|
1075
1075
|
|
|
1076
1076
|
This is mainly useful for debugging provider serialization and cache behavior.
|
|
1077
1077
|
|
|
1078
|
+
`before_provider_request`, `provider_stream_event` and `after_provider_response` handlers can declare the providers whose requests or streams they read or change:
|
|
1079
|
+
|
|
1080
|
+
```typescript
|
|
1081
|
+
pi.on("before_provider_request", (event) => ({ ...event.payload, metadata: { tag: "x" } }), {
|
|
1082
|
+
providers: ["anthropic"],
|
|
1083
|
+
});
|
|
1084
|
+
```
|
|
1085
|
+
|
|
1086
|
+
The declaration does not filter dispatch: the handler still receives every event. A device serving a hosted session advertises it, so the hosted side knows which providers' calls need that device's hooks. A handler without `providers` counts as touching every provider. The value must be a non-empty array of provider ids; anything else throws at registration, also for a handler whose `runs` side does not register it. Every other event ignores `providers`.
|
|
1087
|
+
|
|
1078
1088
|
#### after_provider_response
|
|
1079
1089
|
|
|
1080
1090
|
Fired after an HTTP response is received and before its stream body is consumed. Handlers run in extension load order.
|