@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
|
@@ -26,6 +26,8 @@ import { failure, success } from "./session-control-server.js";
|
|
|
26
26
|
import { TERMINAL_PRESENTER_COMMANDS } from "./terminal-presenter-surface.js";
|
|
27
27
|
export const TUI_RPC_COMMANDS = [
|
|
28
28
|
"open_session",
|
|
29
|
+
"park_session",
|
|
30
|
+
"claim_session",
|
|
29
31
|
"get_snapshot",
|
|
30
32
|
"subscribe_sessions",
|
|
31
33
|
"unsubscribe_sessions",
|
|
@@ -64,6 +66,9 @@ export async function runTuiRpcCommand(context, connection, command) {
|
|
|
64
66
|
}
|
|
65
67
|
case "open_session":
|
|
66
68
|
return openSession(context, connection, command);
|
|
69
|
+
case "park_session":
|
|
70
|
+
case "claim_session":
|
|
71
|
+
return failure(idOf(command), command.type, "multi_session_disabled");
|
|
67
72
|
case "subscribe_sessions":
|
|
68
73
|
return subscribe(context, connection, frame(command));
|
|
69
74
|
case "unsubscribe_sessions":
|
|
@@ -20,6 +20,8 @@ export interface DeliveryPeer {
|
|
|
20
20
|
/** The remote device the connection speaks for (`ConnectionRoles.originOf`); absent on a plain local connection. */
|
|
21
21
|
readonly origin: RpcRemoteOrigin | undefined;
|
|
22
22
|
readonly connectionOrigin: ConnectionOrigin;
|
|
23
|
+
/** The origin the turn this delivery opens counts as (senpi#6342); the connection's origin when absent. */
|
|
24
|
+
readonly turnOrigin?: ConnectionOrigin;
|
|
23
25
|
}
|
|
24
26
|
export type AdmitExternalMessageAnswer = {
|
|
25
27
|
readonly ok: true;
|
|
@@ -9,6 +9,10 @@ function ledgerId(deliveryId, origin) {
|
|
|
9
9
|
? `rpc:local/${deliveryId}`
|
|
10
10
|
: `device:${encodeURIComponent(origin.deviceId)}/${deliveryId}`;
|
|
11
11
|
}
|
|
12
|
+
/** The turn a delivery opens: a steer joins the running turn; anything else counts as the connection's turn origin. */
|
|
13
|
+
function deliveryTurnMark(command, peer) {
|
|
14
|
+
return command.deliverAs === "steer" ? "join" : (peer.turnOrigin ?? peer.connectionOrigin);
|
|
15
|
+
}
|
|
12
16
|
export function admitExternalMessage(session, command, peer) {
|
|
13
17
|
const chain = admitInputChain(command.chainCount, session.settingsManager);
|
|
14
18
|
if (chain.kind === "refused")
|
|
@@ -54,7 +58,7 @@ export function admitExternalMessage(session, command, peer) {
|
|
|
54
58
|
}, {
|
|
55
59
|
...(origin === undefined ? {} : { remoteOrigin: origin }),
|
|
56
60
|
...(chain.chainCount === undefined ? {} : { chainCount: chain.chainCount }),
|
|
57
|
-
turnMark: command
|
|
61
|
+
turnMark: deliveryTurnMark(command, peer),
|
|
58
62
|
});
|
|
59
63
|
return answer(result.kind, result.turn_epoch);
|
|
60
64
|
}
|
|
@@ -22,7 +22,10 @@ export function unknownCompactAdmission(host, command) {
|
|
|
22
22
|
if (!host.admissions || command.admissionId === undefined)
|
|
23
23
|
return undefined;
|
|
24
24
|
// These commands introduce client IDs; their bounded attempt index owns retry/conflict/retirement.
|
|
25
|
-
if (command.type === "open_session" ||
|
|
25
|
+
if (command.type === "open_session" ||
|
|
26
|
+
command.type === "claim_session" ||
|
|
27
|
+
command.type === "attach_session" ||
|
|
28
|
+
command.type === "subscribe_sessions")
|
|
26
29
|
return undefined;
|
|
27
30
|
// RULING-96: recovery IDs select token/lease authority, not the ordinary attempt ledger.
|
|
28
31
|
if (command.type === "get_recovery_page" || command.type === "release_recovery")
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* The authority word of a host-mode delegated connection (omo-relay-daemon#307).
|
|
3
3
|
*
|
|
4
4
|
* One `Int32Array(SharedArrayBuffer(8))` per incarnation of a delegated socket: index 0 packs
|
|
5
|
-
* `epoch <<
|
|
5
|
+
* `epoch << 4 | retired << 3 | mask` (mask bit 0 = interactive_user, bit 1 = task_parent, bit 2 = peer_agent), index 1 is
|
|
6
|
+
* the incarnation,
|
|
6
7
|
* stamped once before the buffer is shared. The host thread is the only writer, and every write is monotone within a
|
|
7
8
|
* word: mask bits are only cleared, retired is only set, the epoch only grows and changes only on a real transition.
|
|
8
9
|
* Host and worker threads read the same memory with one `Atomics.load` per command, so the load at a command's first
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* The authority word of a host-mode delegated connection (omo-relay-daemon#307).
|
|
3
3
|
*
|
|
4
4
|
* One `Int32Array(SharedArrayBuffer(8))` per incarnation of a delegated socket: index 0 packs
|
|
5
|
-
* `epoch <<
|
|
5
|
+
* `epoch << 4 | retired << 3 | mask` (mask bit 0 = interactive_user, bit 1 = task_parent, bit 2 = peer_agent), index 1 is
|
|
6
|
+
* the incarnation,
|
|
6
7
|
* stamped once before the buffer is shared. The host thread is the only writer, and every write is monotone within a
|
|
7
8
|
* word: mask bits are only cleared, retired is only set, the epoch only grows and changes only on a real transition.
|
|
8
9
|
* Host and worker threads read the same memory with one `Atomics.load` per command, so the load at a command's first
|
|
@@ -10,12 +11,13 @@
|
|
|
10
11
|
*
|
|
11
12
|
* This module has no package imports on purpose: worker-thread tests load it directly.
|
|
12
13
|
*/
|
|
13
|
-
/** The
|
|
14
|
-
const WORD_ROLES = ["interactive_user", "task_parent"];
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
/** The roles a word can carry, in bit order. */
|
|
15
|
+
const WORD_ROLES = ["interactive_user", "task_parent", "peer_agent"];
|
|
16
|
+
const MASK_BITS = 7;
|
|
17
|
+
const RETIRED_BIT = 8;
|
|
18
|
+
const EPOCH_SHIFT = 4;
|
|
19
|
+
/** The epoch field holds 28 bits; within one incarnation it never passes 4, so this bound is an invariant check. */
|
|
20
|
+
const EPOCH_LIMIT = 2 ** 28;
|
|
19
21
|
/** The largest incarnation slot [1] holds unchanged. */
|
|
20
22
|
export const INCARNATION_MAX = 0x7fffffff;
|
|
21
23
|
export function maskOfRoles(roles) {
|
|
@@ -31,7 +33,7 @@ export function rolesOfMask(mask) {
|
|
|
31
33
|
return WORD_ROLES.filter((_role, bit) => (mask & (1 << bit)) !== 0);
|
|
32
34
|
}
|
|
33
35
|
export function decodeWord(word) {
|
|
34
|
-
const mask = word &
|
|
36
|
+
const mask = word & MASK_BITS;
|
|
35
37
|
return { epoch: word >>> EPOCH_SHIFT, retired: (word & RETIRED_BIT) !== 0, mask, roles: rolesOfMask(mask) };
|
|
36
38
|
}
|
|
37
39
|
function packWord(epoch, retired, mask) {
|
|
@@ -45,7 +47,7 @@ export function createAuthority(incarnation, mask) {
|
|
|
45
47
|
throw new Error("authority_incarnation_invalid");
|
|
46
48
|
const buffer = new SharedArrayBuffer(8);
|
|
47
49
|
const view = new Int32Array(buffer);
|
|
48
|
-
view[0] = packWord(1, false, mask &
|
|
50
|
+
view[0] = packWord(1, false, mask & MASK_BITS);
|
|
49
51
|
view[1] = incarnation;
|
|
50
52
|
return buffer;
|
|
51
53
|
}
|
|
@@ -73,6 +73,8 @@ export interface RpcConnectionHandler {
|
|
|
73
73
|
* extension UI context is installed (used by tests that drive ctx.ui directly).
|
|
74
74
|
*/
|
|
75
75
|
readonly ready: Promise<void>;
|
|
76
|
+
/** Complete a prebuilt binding with the capabilities its opener supplied. */
|
|
77
|
+
setClientCapabilities(capabilities: readonly string[]): void;
|
|
76
78
|
/** Feed one inbound JSONL line (command or extension_ui_response). */
|
|
77
79
|
handleInputLine(line: string): Promise<void>;
|
|
78
80
|
/**
|
|
@@ -52,7 +52,8 @@ import { ConnectionQuestionBridge, degradeQuestion, sessionQuestionBridges } fro
|
|
|
52
52
|
import { remoteOriginDeclaration, remoteOriginField } from "./remote-origin.js";
|
|
53
53
|
import { advertisedCompactCapabilities, sessionDeclaration } from "./compact-negotiation.js";
|
|
54
54
|
import { commandAuthority } from "./command-authority.js";
|
|
55
|
-
import {
|
|
55
|
+
import { runInRecordScope } from "../../core/turn-origin.js";
|
|
56
|
+
import { recordTurnOrigin } from "./delegated-drive-origin.js";
|
|
56
57
|
import { ConnectionRoles, DELEGATION_INCARNATION_STALE, roleConnection } from "./connection-roles.js";
|
|
57
58
|
import { ACCOUNT_RESET_CAPABILITY, AUTH_KEY_VERIFY_CAPABILITY, AUTO_TITLE_SESSIONS_CAPABILITY, buildCustomUnsupportedRequest, CONTINUE_FROM_LEAF_CAPABILITY, DEFAULT_CUSTOM_EXTENSION_LABEL, EVAL_CELLS_CAPABILITY, EXTENSION_EVENTS_CAPABILITY, ENTRIES_TAIL_CAPABILITY, INTERACTIVE_USER_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY, PROVIDER_ACCOUNT_TEST_CAPABILITY, QUESTION_CAPABILITY, QUEUED_MESSAGE_REVISION_CAPABILITY, RESUME_SESSION_CAPABILITY, RETRY_FALLBACK_COMMAND_CAPABILITY, SESSION_HELD_CAPABILITY, TOOL_BARRIER_CAPABILITY, TASK_PARENT_CAPABILITY, } from "./custom-capability.js";
|
|
58
59
|
import { runAbort, runGetEffectStatus, runQueuedInputChange, runSetThinkingLevel, } from "./effect-commands.js";
|
|
@@ -72,6 +73,7 @@ import { HostSessionControl } from "./host-session-control.js";
|
|
|
72
73
|
import { createRpcLoginPromptCallbacks } from "./login-prompts.js";
|
|
73
74
|
import { answerMemoryReport } from "./memory-report-command.js";
|
|
74
75
|
import { readProjectSettings, readProjectTrust, writeProjectSetting, writeProjectTrust, } from "./project-workspace-commands.js";
|
|
76
|
+
import { readProjectFile, writeProjectFile } from "./project-file-commands.js";
|
|
75
77
|
import { protocolIdentity } from "./protocol-identity.js";
|
|
76
78
|
import { buildRpcCommandsForSession, createCommandsChangedEvent, rpcCommandListDigest } from "./rpc-command-surface.js";
|
|
77
79
|
import { rpcCommandPayloadError, rpcCommandShapeError, rpcMessageLengthError, sessionRetryFallbackError, } from "./rpc-input-validation.js";
|
|
@@ -208,6 +210,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
208
210
|
const currentConnectionId = () => roleConnection(options.clientInfo?.connectionId());
|
|
209
211
|
const hasRole = (role) => connectionRoles.has(currentConnectionId(), role);
|
|
210
212
|
const connectionOrigin = () => connectionRoles.isDelegated(currentConnectionId()) ? "delegated" : "local";
|
|
213
|
+
// senpi#6342: a turn follows this machine's own setting; only a device the forwarder did not state is the same account
|
|
214
|
+
// counts as delegated for the permission rule.
|
|
215
|
+
const turnOrigin = () => connectionOrigin() === "delegated" && !connectionRoles.sameAccount(currentConnectionId()) ? "delegated" : "local";
|
|
211
216
|
const routingSessionId = options.sessionId;
|
|
212
217
|
// True only while THIS connection's own command drives a replacement; the issuer
|
|
213
218
|
// already learns the new identity from its command response.
|
|
@@ -1008,7 +1013,6 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1008
1013
|
// Handle a single command
|
|
1009
1014
|
const handleCommand = async (command, requestContext) => {
|
|
1010
1015
|
const id = command.id;
|
|
1011
|
-
noteDelegatedRecord(command, connectionOrigin(), session.sessionManager);
|
|
1012
1016
|
switch (command.type) {
|
|
1013
1017
|
case "get_protocol_info":
|
|
1014
1018
|
return {
|
|
@@ -1046,7 +1050,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1046
1050
|
...(options.retryFallbackCommand ? [RETRY_FALLBACK_COMMAND_CAPABILITY] : []),
|
|
1047
1051
|
...(options.toolRuntime ? toolRuntimeCapabilities(options.toolRuntime) : []),
|
|
1048
1052
|
// Client flags cannot advertise a host guard this classic binding does not run, nor a tool runtime.
|
|
1049
|
-
...advertisedCompactCapabilities(options.capabilities ?? [], false).filter((capability) => capability !== SESSION_HELD_CAPABILITY &&
|
|
1053
|
+
...advertisedCompactCapabilities(options.capabilities ?? [], false).filter((capability) => capability !== SESSION_HELD_CAPABILITY &&
|
|
1054
|
+
capability !== "park_claim" &&
|
|
1055
|
+
!isHostOwnedToolRuntimeCapability(capability)),
|
|
1050
1056
|
]),
|
|
1051
1057
|
],
|
|
1052
1058
|
mode: "classic",
|
|
@@ -1054,7 +1060,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1054
1060
|
},
|
|
1055
1061
|
};
|
|
1056
1062
|
case "open_session":
|
|
1057
|
-
|
|
1063
|
+
case "park_session":
|
|
1064
|
+
case "claim_session":
|
|
1065
|
+
return error(id, command.type, "multi_session_disabled");
|
|
1058
1066
|
// =================================================================
|
|
1059
1067
|
// Prompting
|
|
1060
1068
|
// =================================================================
|
|
@@ -1065,7 +1073,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1065
1073
|
if (holdAutomaticInput(session, command, hasRole(INTERACTIVE_USER_CAPABILITY)))
|
|
1066
1074
|
return success(id, "prompt", { disposition: "handled", heldAsNotice: true });
|
|
1067
1075
|
turnRequested = true;
|
|
1068
|
-
const admission = handleClientInput(session, command, { output, promptCalls }, { interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY), connectionOrigin:
|
|
1076
|
+
const admission = handleClientInput(session, command, { output, promptCalls }, { interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY), connectionOrigin: turnOrigin() });
|
|
1069
1077
|
promptCalls.add(admission);
|
|
1070
1078
|
void admission.finally(() => promptCalls.delete(admission));
|
|
1071
1079
|
return undefined;
|
|
@@ -1135,7 +1143,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1135
1143
|
if (holdAutomaticInput(session, command, hasRole(INTERACTIVE_USER_CAPABILITY)))
|
|
1136
1144
|
return success(id, command.type, { disposition: "handled", heldAsNotice: true });
|
|
1137
1145
|
turnRequested = true;
|
|
1138
|
-
await handleClientInput(session, command, { output, promptCalls }, { interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY), connectionOrigin:
|
|
1146
|
+
await handleClientInput(session, command, { output, promptCalls }, { interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY), connectionOrigin: turnOrigin() });
|
|
1139
1147
|
return undefined;
|
|
1140
1148
|
}
|
|
1141
1149
|
case "abort":
|
|
@@ -1237,6 +1245,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1237
1245
|
const peer = {
|
|
1238
1246
|
origin: connectionRoles.originOf(currentConnectionId()),
|
|
1239
1247
|
connectionOrigin: connectionOrigin(),
|
|
1248
|
+
turnOrigin: turnOrigin(),
|
|
1240
1249
|
};
|
|
1241
1250
|
const answer = admitExternalMessage(session, command, peer);
|
|
1242
1251
|
if (!answer.ok) {
|
|
@@ -1750,6 +1759,18 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1750
1759
|
? success(id, "set_project_setting", result.data)
|
|
1751
1760
|
: error(id, "set_project_setting", result.message, result.errorCode);
|
|
1752
1761
|
}
|
|
1762
|
+
case "read_project_file": {
|
|
1763
|
+
const result = await readProjectFile(session, command.path);
|
|
1764
|
+
return result.ok
|
|
1765
|
+
? success(id, "read_project_file", result.data)
|
|
1766
|
+
: error(id, "read_project_file", result.message, result.errorCode, result.errorData);
|
|
1767
|
+
}
|
|
1768
|
+
case "write_project_file": {
|
|
1769
|
+
const result = await writeProjectFile(session, command.path, command.content, command.ifEtag);
|
|
1770
|
+
return result.ok
|
|
1771
|
+
? success(id, "write_project_file", result.data)
|
|
1772
|
+
: error(id, "write_project_file", result.message, result.errorCode, result.errorData);
|
|
1773
|
+
}
|
|
1753
1774
|
case "extension_request":
|
|
1754
1775
|
case "eval_cells.list":
|
|
1755
1776
|
case "eval_cells.peek":
|
|
@@ -1977,7 +1998,8 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1977
1998
|
return;
|
|
1978
1999
|
}
|
|
1979
2000
|
try {
|
|
1980
|
-
|
|
2001
|
+
// senpi#6342: the record's own handling, and the first run it starts, run under the record's origin.
|
|
2002
|
+
const response = await runInRecordScope(recordTurnOrigin(command, turnOrigin()), () => handleCommand(command, requestContext));
|
|
1981
2003
|
if (response) {
|
|
1982
2004
|
output(response);
|
|
1983
2005
|
await waitForRpcBackpressure();
|
|
@@ -2038,6 +2060,10 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
2038
2060
|
pendingPrompts() {
|
|
2039
2061
|
return [...promptCalls];
|
|
2040
2062
|
},
|
|
2063
|
+
setClientCapabilities(capabilities) {
|
|
2064
|
+
replaceClientCapabilities([...capabilities]);
|
|
2065
|
+
refreshGrantPresentation();
|
|
2066
|
+
},
|
|
2041
2067
|
isShutdownRequested() {
|
|
2042
2068
|
return shutdownRequested;
|
|
2043
2069
|
},
|
|
@@ -59,10 +59,17 @@ export declare class ConnectionRoles {
|
|
|
59
59
|
acceptsOrigin(connectionId: string, origin: RpcRemoteOrigin): boolean;
|
|
60
60
|
/** Records the remote device a local connection speaks for; a delegated connection's origin is never declared. */
|
|
61
61
|
declareOrigin(connectionId: string, origin: RpcRemoteOrigin): void;
|
|
62
|
+
/** Whether the forwarder stated this delegated connection's device is the host's own account (senpi#6342). */
|
|
63
|
+
sameAccount(connectionId: string | undefined): boolean;
|
|
62
64
|
/** The remote device this connection speaks for: a delegated connection's principal, else its declared origin. */
|
|
63
65
|
originOf(connectionId: string | undefined): RpcRemoteOrigin | undefined;
|
|
64
66
|
/** Whether the connection is delegated (a remote device's): on the host, retained by a worker, or carried to one. */
|
|
65
67
|
isDelegated(connectionId: string | undefined): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Whether the forwarder itself granted `role` to this connection (senpi#6305): only a host-mode delegation's live,
|
|
70
|
+
* unretired authority word counts. No client claim, legacy-mode delegation or local connection can satisfy it.
|
|
71
|
+
*/
|
|
72
|
+
grantedByForwarder(connectionId: string | undefined, role: string): boolean;
|
|
66
73
|
has(connectionId: string | undefined, role: string): boolean;
|
|
67
74
|
/** A logical detach: drops claims of earlier incarnations of a delegated socket, and everything of a local one. */
|
|
68
75
|
release(connectionId: string): void;
|
|
@@ -117,6 +117,10 @@ export class ConnectionRoles {
|
|
|
117
117
|
if (this.acceptsOrigin(connectionId, origin))
|
|
118
118
|
this.origins.set(connectionId, origin);
|
|
119
119
|
}
|
|
120
|
+
/** Whether the forwarder stated this delegated connection's device is the host's own account (senpi#6342). */
|
|
121
|
+
sameAccount(connectionId) {
|
|
122
|
+
return this.viewOf(roleConnection(connectionId))?.descriptor.principal.sameAccount === true;
|
|
123
|
+
}
|
|
120
124
|
/** The remote device this connection speaks for: a delegated connection's principal, else its declared origin. */
|
|
121
125
|
originOf(connectionId) {
|
|
122
126
|
const key = roleConnection(connectionId);
|
|
@@ -132,6 +136,17 @@ export class ConnectionRoles {
|
|
|
132
136
|
const key = roleConnection(connectionId);
|
|
133
137
|
return this.viewOf(key) !== undefined || this.carried.has(key);
|
|
134
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Whether the forwarder itself granted `role` to this connection (senpi#6305): only a host-mode delegation's live,
|
|
141
|
+
* unretired authority word counts. No client claim, legacy-mode delegation or local connection can satisfy it.
|
|
142
|
+
*/
|
|
143
|
+
grantedByForwarder(connectionId, role) {
|
|
144
|
+
const descriptor = this.viewOf(roleConnection(connectionId))?.descriptor;
|
|
145
|
+
if (descriptor?.mode !== "host" || descriptor.authority === undefined)
|
|
146
|
+
return false;
|
|
147
|
+
const state = readAuthority(descriptor.authority);
|
|
148
|
+
return !state.retired && state.roles.includes(role);
|
|
149
|
+
}
|
|
135
150
|
has(connectionId, role) {
|
|
136
151
|
const key = roleConnection(connectionId);
|
|
137
152
|
const store = commandAuthority.getStore();
|
|
@@ -63,6 +63,10 @@ export declare const DELEGATED_CONNECTION_CAPABILITY = "delegated_connection_v1"
|
|
|
63
63
|
* incarnation, `relayExec` and the `authority` receipt.
|
|
64
64
|
*/
|
|
65
65
|
export declare const DELEGATION_ROLES_CAPABILITY = "delegation_roles_v1";
|
|
66
|
+
/** A host-mode delegation may carry the forwarder-granted `peer_agent` role (senpi#6305). */
|
|
67
|
+
export declare const PEER_AGENT_ROLE_CAPABILITY = "peer_agent_role_v1";
|
|
68
|
+
/** A delegation may state `principal.sameAccount`, so that device's turns follow this host's own setting (senpi#6342). */
|
|
69
|
+
export declare const SAME_ACCOUNT_DELEGATION_CAPABILITY = "same_account_delegation_v1";
|
|
66
70
|
/**
|
|
67
71
|
* Client opt-in (D11 S3-5): the connection renders the value-free `secret_input_notice` and `grant_select_notice` of a
|
|
68
72
|
* raiser-only dialog another connection presents, and their `*_notice_settled` records. It never answers them.
|
|
@@ -115,6 +119,8 @@ export declare const AUTO_TITLE_PER_SESSION_CAPABILITY = "auto_title_per_session
|
|
|
115
119
|
* cwd, kind and context needs without opening a session. Advertised only by an in-process runtime.
|
|
116
120
|
*/
|
|
117
121
|
export declare const WARM_CAPABILITY = "warm";
|
|
122
|
+
/** HOST capability: invisible speculative sessions and single-use claim, in-process registries only. */
|
|
123
|
+
export declare const PARK_CLAIM_CAPABILITY = "park_claim";
|
|
118
124
|
/**
|
|
119
125
|
* HOST capability: this host honors `open_session.durableSessionId`, so a caller that already
|
|
120
126
|
* owns a stable record id for the conversation can CREATE the session under that id and keep
|
|
@@ -63,6 +63,10 @@ export const DELEGATED_CONNECTION_CAPABILITY = "delegated_connection_v1";
|
|
|
63
63
|
* incarnation, `relayExec` and the `authority` receipt.
|
|
64
64
|
*/
|
|
65
65
|
export const DELEGATION_ROLES_CAPABILITY = "delegation_roles_v1";
|
|
66
|
+
/** A host-mode delegation may carry the forwarder-granted `peer_agent` role (senpi#6305). */
|
|
67
|
+
export const PEER_AGENT_ROLE_CAPABILITY = "peer_agent_role_v1";
|
|
68
|
+
/** A delegation may state `principal.sameAccount`, so that device's turns follow this host's own setting (senpi#6342). */
|
|
69
|
+
export const SAME_ACCOUNT_DELEGATION_CAPABILITY = "same_account_delegation_v1";
|
|
66
70
|
/**
|
|
67
71
|
* Client opt-in (D11 S3-5): the connection renders the value-free `secret_input_notice` and `grant_select_notice` of a
|
|
68
72
|
* raiser-only dialog another connection presents, and their `*_notice_settled` records. It never answers them.
|
|
@@ -115,6 +119,8 @@ export const AUTO_TITLE_PER_SESSION_CAPABILITY = "auto_title_per_session";
|
|
|
115
119
|
* cwd, kind and context needs without opening a session. Advertised only by an in-process runtime.
|
|
116
120
|
*/
|
|
117
121
|
export const WARM_CAPABILITY = "warm";
|
|
122
|
+
/** HOST capability: invisible speculative sessions and single-use claim, in-process registries only. */
|
|
123
|
+
export const PARK_CLAIM_CAPABILITY = "park_claim";
|
|
118
124
|
/**
|
|
119
125
|
* HOST capability: this host honors `open_session.durableSessionId`, so a caller that already
|
|
120
126
|
* owns a stable record id for the conversation can CREATE the session under that id and keep
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { type ConnectionOrigin } from "../../core/turn-origin.ts";
|
|
1
|
+
import type { ConnectionOrigin } from "../../core/turn-origin.ts";
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
* by the engine's own method-class table (`drive`, and `device_admin`, which grants more),
|
|
6
|
-
* commands, so a new run starter (`continue_from_leaf`, `wake`, `resume_for_run`, ...)
|
|
3
|
+
* The origin a record's own handling runs under (senpi#6342): delegated for a cross-account record that can act on the
|
|
4
|
+
* session's work, decided by the engine's own method-class table (`drive`, and `device_admin`, which grants more),
|
|
5
|
+
* never by a hand-kept list of commands, so a new run starter (`continue_from_leaf`, `wake`, `resume_for_run`, ...)
|
|
6
|
+
* cannot slip past the rule. Any other record runs as local.
|
|
7
7
|
*/
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function recordTurnOrigin(command: object, origin: ConnectionOrigin): ConnectionOrigin;
|
|
9
9
|
//# sourceMappingURL=delegated-drive-origin.d.ts.map
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { recordDelegatedOrigin } from "../../core/turn-origin.js";
|
|
2
1
|
import { classifyRpcMethod } from "./method-classes.js";
|
|
3
2
|
const ACTING_CLASSES = new Set(["drive", "device_admin"]);
|
|
4
3
|
/**
|
|
5
|
-
*
|
|
6
|
-
* by the engine's own method-class table (`drive`, and `device_admin`, which grants more),
|
|
7
|
-
* commands, so a new run starter (`continue_from_leaf`, `wake`, `resume_for_run`, ...)
|
|
4
|
+
* The origin a record's own handling runs under (senpi#6342): delegated for a cross-account record that can act on the
|
|
5
|
+
* session's work, decided by the engine's own method-class table (`drive`, and `device_admin`, which grants more),
|
|
6
|
+
* never by a hand-kept list of commands, so a new run starter (`continue_from_leaf`, `wake`, `resume_for_run`, ...)
|
|
7
|
+
* cannot slip past the rule. Any other record runs as local.
|
|
8
8
|
*/
|
|
9
|
-
export function
|
|
9
|
+
export function recordTurnOrigin(command, origin) {
|
|
10
10
|
if (origin !== "delegated")
|
|
11
|
-
return;
|
|
11
|
+
return "local";
|
|
12
12
|
const methodClass = classifyRpcMethod(command);
|
|
13
|
-
|
|
14
|
-
recordDelegatedOrigin(sessionManager);
|
|
13
|
+
return methodClass !== undefined && ACTING_CLASSES.has(methodClass) ? "delegated" : "local";
|
|
15
14
|
}
|
|
16
15
|
//# sourceMappingURL=delegated-drive-origin.js.map
|
|
@@ -4,6 +4,8 @@ export interface Principal {
|
|
|
4
4
|
readonly deviceId: string;
|
|
5
5
|
readonly deviceName?: string;
|
|
6
6
|
readonly conn?: string;
|
|
7
|
+
/** The forwarder states this device is the host's own account (senpi#6342); fixed for the record's life. */
|
|
8
|
+
readonly sameAccount?: true;
|
|
7
9
|
}
|
|
8
10
|
export interface Declaration {
|
|
9
11
|
readonly principal: Principal;
|
|
@@ -8,7 +8,7 @@ const FORWARDABLE_CLASSES = new Set([
|
|
|
8
8
|
const MAX_PRINCIPAL_FIELD = 256;
|
|
9
9
|
const MAX_CONN_FIELD = 64;
|
|
10
10
|
/** The connection roles a host-mode declaration may carry (omo-relay-daemon#307). */
|
|
11
|
-
const DECLARABLE_ROLES = new Set(["interactive_user", "task_parent"]);
|
|
11
|
+
const DECLARABLE_ROLES = new Set(["interactive_user", "task_parent", "peer_agent"]);
|
|
12
12
|
export function parseDeclaration(record) {
|
|
13
13
|
const principal = Reflect.get(record, "principal");
|
|
14
14
|
if (typeof principal !== "object" || principal === null || Array.isArray(principal))
|
|
@@ -22,6 +22,9 @@ export function parseDeclaration(record) {
|
|
|
22
22
|
return "principal.deviceName must be 1-256 characters";
|
|
23
23
|
if (conn !== undefined && !boundedString(conn, MAX_CONN_FIELD))
|
|
24
24
|
return "principal.conn must be 1-64 characters";
|
|
25
|
+
const sameAccount = Reflect.get(principal, "sameAccount");
|
|
26
|
+
if (sameAccount !== undefined && sameAccount !== true)
|
|
27
|
+
return "principal.sameAccount must be true when present";
|
|
25
28
|
const granted = Reflect.get(record, "granted");
|
|
26
29
|
if (!Array.isArray(granted))
|
|
27
30
|
return "granted must be an array of method classes";
|
|
@@ -40,17 +43,18 @@ export function parseDeclaration(record) {
|
|
|
40
43
|
deviceId: deviceId,
|
|
41
44
|
...(deviceName === undefined ? {} : { deviceName: deviceName }),
|
|
42
45
|
...(conn === undefined ? {} : { conn: conn }),
|
|
46
|
+
...(sameAccount === true ? { sameAccount: true } : {}),
|
|
43
47
|
},
|
|
44
48
|
granted: classes,
|
|
45
49
|
};
|
|
46
50
|
}
|
|
47
51
|
export function samePrincipal(a, b) {
|
|
48
|
-
return a.deviceId === b.deviceId && a.deviceName === b.deviceName && a.conn === b.conn;
|
|
52
|
+
return (a.deviceId === b.deviceId && a.deviceName === b.deviceName && a.conn === b.conn && a.sameAccount === b.sameAccount);
|
|
49
53
|
}
|
|
50
54
|
function parseRoles(value) {
|
|
51
55
|
if (value === undefined)
|
|
52
56
|
return undefined;
|
|
53
|
-
const invalid = "roles holds each of interactive_user, task_parent at most once";
|
|
57
|
+
const invalid = "roles holds each of interactive_user, task_parent, peer_agent at most once";
|
|
54
58
|
if (!Array.isArray(value))
|
|
55
59
|
return invalid;
|
|
56
60
|
const roles = new Set();
|
|
@@ -66,6 +66,27 @@ export declare function runSetThinkingLevel(ctx: EffectCommandContext, command:
|
|
|
66
66
|
readonly reclaimed: true;
|
|
67
67
|
readonly sessionId: string;
|
|
68
68
|
};
|
|
69
|
+
} | {
|
|
70
|
+
id?: string;
|
|
71
|
+
type: "response";
|
|
72
|
+
command: "park_session";
|
|
73
|
+
success: true;
|
|
74
|
+
data: {
|
|
75
|
+
state: "parked" | "already_parked" | "full";
|
|
76
|
+
};
|
|
77
|
+
} | {
|
|
78
|
+
id?: string;
|
|
79
|
+
type: "response";
|
|
80
|
+
command: "claim_session";
|
|
81
|
+
success: true;
|
|
82
|
+
data: {
|
|
83
|
+
claimed: false;
|
|
84
|
+
} | {
|
|
85
|
+
sessionId: string;
|
|
86
|
+
state: import("./rpc-session-state-types.ts").RpcSessionState;
|
|
87
|
+
attached?: boolean;
|
|
88
|
+
presence?: import("./rpc-host-response-types.ts").RpcSessionPresence;
|
|
89
|
+
};
|
|
69
90
|
} | {
|
|
70
91
|
id?: string;
|
|
71
92
|
type: "response";
|
|
@@ -414,6 +435,12 @@ export declare function runSetThinkingLevel(ctx: EffectCommandContext, command:
|
|
|
414
435
|
command: "set_project_setting";
|
|
415
436
|
success: true;
|
|
416
437
|
data: import("./project-workspace-commands.ts").RpcProjectSettings;
|
|
438
|
+
} | {
|
|
439
|
+
id?: string;
|
|
440
|
+
type: "response";
|
|
441
|
+
command: "write_project_file";
|
|
442
|
+
success: true;
|
|
443
|
+
data: import("./project-file-commands.ts").RpcProjectFile;
|
|
417
444
|
} | {
|
|
418
445
|
id?: string;
|
|
419
446
|
type: "response";
|
|
@@ -871,6 +898,12 @@ export declare function runSetThinkingLevel(ctx: EffectCommandContext, command:
|
|
|
871
898
|
command: "get_project_settings";
|
|
872
899
|
success: true;
|
|
873
900
|
data: import("./project-workspace-commands.ts").RpcProjectSettings;
|
|
901
|
+
} | {
|
|
902
|
+
id?: string;
|
|
903
|
+
type: "response";
|
|
904
|
+
command: "read_project_file";
|
|
905
|
+
success: true;
|
|
906
|
+
data: import("./project-file-commands.ts").RpcProjectFile;
|
|
874
907
|
} | {
|
|
875
908
|
id?: string;
|
|
876
909
|
type: "response";
|
|
@@ -14,6 +14,7 @@ export declare const SET_PERMISSION_PRESET_CAPABILITY = "set_permission_preset_v
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function multiSessionHostCapabilities(options: {
|
|
16
16
|
readonly warm: boolean;
|
|
17
|
+
readonly parkClaim?: boolean;
|
|
17
18
|
readonly toolRuntime: ToolRuntimeKind;
|
|
18
19
|
readonly negotiated: readonly string[];
|
|
19
20
|
readonly mcpPresenters?: boolean;
|
|
@@ -2,7 +2,7 @@ import { compactUpdatesEnabled } from "../../core/engine-socket-flag.js";
|
|
|
2
2
|
import { isHostOwnedToolRuntimeCapability, toolRuntimeCapabilities, } from "../../cli/tool-runtime.js";
|
|
3
3
|
import { ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY, AUTO_PERMISSION_PRESET_CAPABILITY, } from "../../core/extensions/builtin/permission-system/config.js";
|
|
4
4
|
import { DURABLE_CLIENT_MESSAGE_ID_CAPABILITY } from "./client-admission-record.js";
|
|
5
|
-
import { ACCOUNT_RESET_CAPABILITY, ATTENDED_CAPABILITY, AUTH_KEY_VERIFY_CAPABILITY, AUTO_TITLE_PER_SESSION_CAPABILITY, AUTO_TITLE_SESSIONS_CAPABILITY, BROWSER_ENGINE_CAPABILITY, CONTINUE_FROM_LEAF_CAPABILITY, DELEGATED_CONNECTION_CAPABILITY, DELEGATION_ROLES_CAPABILITY, DETACH_CONNECTION_CAPABILITY, DURABLE_SESSION_ID_CAPABILITY, ENTRIES_TAIL_CAPABILITY, EVAL_CELLS_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY, MOVED_PATH_GUARD_CAPABILITY, OBSERVE_READS_CAPABILITY, PROMPT_SURFACE_CAPABILITY, PROMPT_SURFACE_CHAT_CAPABILITY, PROVIDER_ACCOUNT_TEST_CAPABILITY, QUEUED_MESSAGE_REVISION_CAPABILITY, RESUME_SESSION_CAPABILITY, RETAIN_ON_DISCONNECT_CAPABILITY, RETRY_FALLBACK_PROFILE_CAPABILITY, SESSION_CONTEXT_CAPABILITY, SESSION_ENV_CAPABILITY, SESSION_HELD_CAPABILITY, SESSION_KIND_CAPABILITY, SESSION_RELOCATION_CAPABILITY, SESSION_STATUS_CAPABILITY, TOOL_BARRIER_CAPABILITY, WARM_CAPABILITY, } from "./custom-capability.js";
|
|
5
|
+
import { ACCOUNT_RESET_CAPABILITY, ATTENDED_CAPABILITY, AUTH_KEY_VERIFY_CAPABILITY, AUTO_TITLE_PER_SESSION_CAPABILITY, AUTO_TITLE_SESSIONS_CAPABILITY, BROWSER_ENGINE_CAPABILITY, CONTINUE_FROM_LEAF_CAPABILITY, DELEGATED_CONNECTION_CAPABILITY, DELEGATION_ROLES_CAPABILITY, DETACH_CONNECTION_CAPABILITY, DURABLE_SESSION_ID_CAPABILITY, PEER_AGENT_ROLE_CAPABILITY, SAME_ACCOUNT_DELEGATION_CAPABILITY, ENTRIES_TAIL_CAPABILITY, EVAL_CELLS_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY, MOVED_PATH_GUARD_CAPABILITY, OBSERVE_READS_CAPABILITY, PROMPT_SURFACE_CAPABILITY, PROMPT_SURFACE_CHAT_CAPABILITY, PROVIDER_ACCOUNT_TEST_CAPABILITY, QUEUED_MESSAGE_REVISION_CAPABILITY, RESUME_SESSION_CAPABILITY, RETAIN_ON_DISCONNECT_CAPABILITY, RETRY_FALLBACK_PROFILE_CAPABILITY, SESSION_CONTEXT_CAPABILITY, SESSION_ENV_CAPABILITY, SESSION_HELD_CAPABILITY, SESSION_KIND_CAPABILITY, SESSION_RELOCATION_CAPABILITY, SESSION_STATUS_CAPABILITY, TOOL_BARRIER_CAPABILITY, WARM_CAPABILITY, PARK_CLAIM_CAPABILITY, } from "./custom-capability.js";
|
|
6
6
|
import { EFFECT_LEDGER_CAPABILITY } from "./effect-record.js";
|
|
7
7
|
import { SESSION_MODEL_SCOPE_CAPABILITY } from "./rpc-session-command-types.js";
|
|
8
8
|
import { STEER_WHEN_IDLE_CAPABILITY, USER_ACTIVITY_CAPABILITY } from "./rpc-types.js";
|
|
@@ -70,6 +70,10 @@ export function multiSessionHostCapabilities(options) {
|
|
|
70
70
|
DELEGATED_CONNECTION_CAPABILITY,
|
|
71
71
|
// ...and decides a host-mode connection's roles per incarnation, with receipts (omo-relay-daemon#307).
|
|
72
72
|
DELEGATION_ROLES_CAPABILITY,
|
|
73
|
+
// ...and may carry the forwarder-granted `peer_agent` role on such a connection (senpi#6305).
|
|
74
|
+
PEER_AGENT_ROLE_CAPABILITY,
|
|
75
|
+
// ...and lets the forwarder state a device is the host's own account, whose turns then ask nothing extra.
|
|
76
|
+
SAME_ACCOUNT_DELEGATION_CAPABILITY,
|
|
73
77
|
// Only a multi-session host keeps sessions loaded that a client can ask it to free.
|
|
74
78
|
UNLOAD_SESSION_CAPABILITY,
|
|
75
79
|
// Only a multi-session host owns a move ledger and the hosted-session list export checks against.
|
|
@@ -101,9 +105,11 @@ export function multiSessionHostCapabilities(options) {
|
|
|
101
105
|
AUTO_PERMISSION_PRESET_CAPABILITY,
|
|
102
106
|
// Only an in-process runtime shares the loop a warm loads into (senpi#2314).
|
|
103
107
|
...(options.warm ? [WARM_CAPABILITY] : []),
|
|
108
|
+
...(options.parkClaim ? [PARK_CLAIM_CAPABILITY] : []),
|
|
104
109
|
...toolRuntimeCapabilities(options.toolRuntime),
|
|
105
110
|
// The host alone says where tool work runs; a negotiated copy would make two answers.
|
|
106
111
|
...options.negotiated.filter((capability) => capability !== "mcp_form_presenter_v1" &&
|
|
112
|
+
capability !== PARK_CLAIM_CAPABILITY &&
|
|
107
113
|
// RULING-111 (LEAK-E): only the compact negotiation owns these names; flag off echoes them as main does.
|
|
108
114
|
(!compactUpdatesEnabled() ||
|
|
109
115
|
(capability !== "compact_message_updates_v1" && capability !== "compact_events")) &&
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type HostDaemonDirectory } from "./host-daemon-paths.ts";
|
|
2
|
-
export type EndpointInUse = "live_generation" | "live_claim" | "reachable";
|
|
2
|
+
export type EndpointInUse = "live_generation" | "live_claim" | "reachable" | "credential_unavailable";
|
|
3
3
|
export type SocketSilence = "socket_refused" | "socket_absent";
|
|
4
4
|
/**
|
|
5
5
|
* The three-part test, in the order its answers are reported: (a) no generation pidfile names a live
|
|
@@ -33,12 +33,17 @@ export async function endpointInUse(paths, socket) {
|
|
|
33
33
|
return { inUse: "live_claim" };
|
|
34
34
|
}
|
|
35
35
|
const silence = await socketSilence(socket);
|
|
36
|
+
if (silence === "credential_unavailable")
|
|
37
|
+
return { inUse: silence };
|
|
36
38
|
if (silence === undefined)
|
|
37
39
|
return { inUse: "reachable" };
|
|
38
40
|
// A successor mid-handoff listens on `<socket>.next-<gen>` before it registers anywhere.
|
|
39
41
|
const successors = (await socketSiblings(socket)).filter((name) => name.startsWith(`${basename(socket)}.next-`) && !isBindScratchName(name));
|
|
40
42
|
for (const successor of successors) {
|
|
41
|
-
|
|
43
|
+
const successorSilence = await socketSilence(join(dirname(socket), successor));
|
|
44
|
+
if (successorSilence === "credential_unavailable")
|
|
45
|
+
return { inUse: successorSilence };
|
|
46
|
+
if (successorSilence === undefined)
|
|
42
47
|
return { inUse: "reachable" };
|
|
43
48
|
}
|
|
44
49
|
return { inUse: undefined, silence };
|
|
@@ -101,10 +106,11 @@ async function recordIsLive(record) {
|
|
|
101
106
|
async function socketSilence(socket) {
|
|
102
107
|
let secret;
|
|
103
108
|
if (process.platform === "win32") {
|
|
104
|
-
// The pipe name includes the secret
|
|
109
|
+
// The pipe name includes the secret, so without a readable one nothing proves the pipe silent: a
|
|
110
|
+
// live host may still serve it under the key whose file was lost (sisyphuslabs/omo-desktop-app#4199).
|
|
105
111
|
secret = await readSocketSecret(socketSecretPath(socket)).catch(() => undefined);
|
|
106
112
|
if (secret === undefined)
|
|
107
|
-
return "
|
|
113
|
+
return "credential_unavailable";
|
|
108
114
|
}
|
|
109
115
|
return new Promise((resolveProbe) => {
|
|
110
116
|
const connection = createConnection(resolveSocketTransportAddress(socket, process.platform, secret));
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* live_generation a generation pidfile (any, the pointer's included) names a live process
|
|
15
15
|
* live_claim a session-path claim in `reservations/` has a live owner
|
|
16
16
|
* reachable the socket (or a `.next-*` successor bind) did not refuse the connection
|
|
17
|
+
* credential_unavailable win32: the socket secret cannot be read, so its pipe cannot be proven silent
|
|
17
18
|
* locked the ensure lock was not free within 2 s
|
|
18
19
|
* legacy_layout the agent dir predates layout 2; its flat files belong to a legacy host
|
|
19
20
|
* unknown_identity nothing in the directory names its socket, so its lock cannot be taken
|
|
@@ -94,7 +95,9 @@ export async function gcEndpoint(socket, dir, options) {
|
|
|
94
95
|
try {
|
|
95
96
|
await options._test?.afterLockAcquired?.(socket);
|
|
96
97
|
const evidence = await endpointInUse(hostDaemonDirectoryPaths(dir), socket);
|
|
97
|
-
if (evidence.inUse === "live_claim" ||
|
|
98
|
+
if (evidence.inUse === "live_claim" ||
|
|
99
|
+
evidence.inUse === "credential_unavailable" ||
|
|
100
|
+
(evidence.inUse !== undefined && options.staleEngine === undefined)) {
|
|
98
101
|
return { removed: false, reason: evidence.inUse };
|
|
99
102
|
}
|
|
100
103
|
if (evidence.inUse !== undefined)
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* and the connection attaches, so a client cannot hold a session while its host idles out under it.
|
|
13
13
|
* `warm` never attaches, marked or not: it opens nothing, so a host that only received it idles out
|
|
14
14
|
* on its normal deadline (senpi#2314).
|
|
15
|
+
* `park_session` likewise holds no client attachment: its speculative runtime is discarded at host exit.
|
|
16
|
+
* `claim_session` takes an ordinary opener attachment and is never observing.
|
|
15
17
|
* Hosts that predate the field ignore it (commands are parsed by `type`), so a marked read works
|
|
16
18
|
* against every generation.
|
|
17
19
|
*
|