@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
|
@@ -1,21 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolved-value registry shared by every copy of this module in one JavaScript realm (omo#12965).
|
|
3
|
+
*
|
|
4
|
+
* A process can evaluate this module more than once (the bundle's shared chunk, its self-contained session-worker
|
|
5
|
+
* entry, and the SDK graph an in-process child loads), so the values are not kept in a module-local set: the first
|
|
6
|
+
* copy pins a frozen registry on `globalThis` under `SLOT_KEY` (non-writable, non-configurable, non-enumerable) and
|
|
7
|
+
* every later copy adopts it. The backing `Set` lives only in the installing copy's closure; the registry offers no
|
|
8
|
+
* delete, clear or setter, so in-realm code cannot remove a value, replace the slot or turn redaction off. Any
|
|
9
|
+
* in-realm code can `add` a string, which can only over-redact. This is a stopgap until one engine instance serves
|
|
10
|
+
* the whole process; other realms (workers, `vm` contexts, child processes) keep their own registry.
|
|
11
|
+
*
|
|
12
|
+
* Compatibility contract, permanent: the key string never changes. The v1 members `version` (1), `add(value)`,
|
|
13
|
+
* `size` (an accessor reporting the live count) and `values()` (a fresh array) are never removed or repurposed; a
|
|
14
|
+
* later contract keeps writing through this same slot and only adds members, and adopters ignore members they do not
|
|
15
|
+
* know. A copy adopts only a slot pinned the way `pin` pins it, frozen, with those four members; anything else (a
|
|
16
|
+
* slot planted before the first copy loaded, an accessor, another version) makes the import throw
|
|
17
|
+
* `ConfigReferenceRedactionSlotError`, because a copy running with a private set is the leak this registry removes.
|
|
18
|
+
*/
|
|
19
|
+
const SLOT_KEY_NAME = "@code-yeongyu/senpi/config-reference-redaction/v1";
|
|
20
|
+
const SLOT_KEY = Symbol.for(SLOT_KEY_NAME);
|
|
1
21
|
const MIN_REDACTED_LENGTH = 4;
|
|
2
|
-
|
|
3
|
-
|
|
22
|
+
/** The largest `$file` reference value (`config-reference-file.ts`); longer strings are never remembered. */
|
|
23
|
+
const MAX_REMEMBERED_LENGTH = 65_536;
|
|
24
|
+
class ConfigReferenceRedactionSlotError extends Error {
|
|
25
|
+
constructor(cause) {
|
|
26
|
+
super(`The process-wide redaction registry ${SLOT_KEY_NAME} was not installed by senpi or is incompatible; restart the process.`, cause === undefined ? undefined : { cause });
|
|
27
|
+
this.name = "ConfigReferenceRedactionSlotError";
|
|
28
|
+
this.code = "SENPI_REDACTION_SLOT_INCOMPATIBLE";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function createRegistry() {
|
|
32
|
+
const values = new Set();
|
|
33
|
+
return Object.freeze({
|
|
34
|
+
version: 1,
|
|
35
|
+
add(value) {
|
|
36
|
+
if (typeof value !== "string" || value.length < MIN_REDACTED_LENGTH || value.length > MAX_REMEMBERED_LENGTH)
|
|
37
|
+
return;
|
|
38
|
+
values.add(value);
|
|
39
|
+
},
|
|
40
|
+
get size() {
|
|
41
|
+
return values.size;
|
|
42
|
+
},
|
|
43
|
+
values: () => [...values],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function isFrozenV1Registry(value) {
|
|
47
|
+
return (typeof value === "object" &&
|
|
48
|
+
value !== null &&
|
|
49
|
+
Object.isFrozen(value) &&
|
|
50
|
+
Reflect.get(value, "version") === 1 &&
|
|
51
|
+
typeof Reflect.get(value, "add") === "function" &&
|
|
52
|
+
typeof Reflect.get(value, "values") === "function" &&
|
|
53
|
+
typeof Reflect.get(value, "size") === "number");
|
|
54
|
+
}
|
|
55
|
+
function pin(registry) {
|
|
56
|
+
try {
|
|
57
|
+
Object.defineProperty(globalThis, SLOT_KEY, {
|
|
58
|
+
value: registry,
|
|
59
|
+
writable: false,
|
|
60
|
+
configurable: false,
|
|
61
|
+
enumerable: false,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw new ConfigReferenceRedactionSlotError(error);
|
|
66
|
+
}
|
|
67
|
+
return registry;
|
|
68
|
+
}
|
|
69
|
+
function sharedRegistry() {
|
|
70
|
+
const slot = Reflect.getOwnPropertyDescriptor(globalThis, SLOT_KEY);
|
|
71
|
+
if (slot === undefined)
|
|
72
|
+
return pin(createRegistry());
|
|
73
|
+
const value = slot.value;
|
|
74
|
+
if (slot.writable !== false || slot.configurable !== false || !isFrozenV1Registry(value)) {
|
|
75
|
+
throw new ConfigReferenceRedactionSlotError();
|
|
76
|
+
}
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
const registry = sharedRegistry();
|
|
80
|
+
let redactionForms = [];
|
|
81
|
+
let formsSize = 0;
|
|
4
82
|
/** Every value a reference resolves to is kept for the process lifetime, including rotated ones: no cap, no eviction. */
|
|
5
83
|
export function rememberResolvedReferenceValue(value) {
|
|
6
|
-
|
|
7
|
-
return;
|
|
8
|
-
resolvedValues.add(value);
|
|
9
|
-
redactionForms = undefined;
|
|
84
|
+
registry.add(value);
|
|
10
85
|
}
|
|
11
86
|
function encodings(value) {
|
|
12
87
|
const form = new URLSearchParams([["", value]]).toString().slice(1);
|
|
13
88
|
return [value, JSON.stringify(value).slice(1, -1), encodeURIComponent(value), encodeURI(value), form];
|
|
14
89
|
}
|
|
90
|
+
/** The registry is append-only, so a changed size is the only way its content can change. */
|
|
15
91
|
function forms() {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
92
|
+
const size = registry.size;
|
|
93
|
+
if (size !== formsSize) {
|
|
94
|
+
redactionForms = [...new Set(registry.values().flatMap(encodings))]
|
|
95
|
+
.filter((form) => form.length >= MIN_REDACTED_LENGTH)
|
|
96
|
+
.sort((left, right) => right.length - left.length);
|
|
97
|
+
formsSize = size;
|
|
98
|
+
}
|
|
19
99
|
return redactionForms;
|
|
20
100
|
}
|
|
21
101
|
/** Replaces every resolved reference value, raw or encoded, before text reaches a sink outside the process. */
|
|
@@ -134,7 +214,7 @@ function isProtocolValue(key, value) {
|
|
|
134
214
|
return Object.hasOwn(PROTOCOL_VALUES, key) && PROTOCOL_VALUES[key]?.has(value) === true;
|
|
135
215
|
}
|
|
136
216
|
export function redactResolvedReferenceData(value) {
|
|
137
|
-
if (
|
|
217
|
+
if (registry.size === 0)
|
|
138
218
|
return value;
|
|
139
219
|
const copies = new WeakMap();
|
|
140
220
|
const pending = [];
|
|
@@ -16,6 +16,16 @@ export type ContextFiles = ContextFile[] & {
|
|
|
16
16
|
export interface ContextFileLimits {
|
|
17
17
|
maxBytesPerFile?: number;
|
|
18
18
|
maxTotalBytes?: number;
|
|
19
|
+
/**
|
|
20
|
+
* The global (user-scope) context file to load instead of the agent-dir probe (senpi#5567).
|
|
21
|
+
* Honored from the user's own settings only (`SettingsManager.getGlobalContextFilePath`); a
|
|
22
|
+
* project's settings never set it. A leading `~` is expanded; a relative path resolves against
|
|
23
|
+
* the agent dir, like other paths in global settings; a directory runs the same candidate probe
|
|
24
|
+
* as the agent dir. Unset or blank keeps the agent-dir file. A path that is set but missing,
|
|
25
|
+
* unreadable, a special file, or a directory with no candidate falls back to the agent-dir probe
|
|
26
|
+
* and reports one warning diagnostic instead of erroring.
|
|
27
|
+
*/
|
|
28
|
+
globalPath?: string;
|
|
19
29
|
}
|
|
20
30
|
export declare const DEFAULT_CONTEXT_FILE_MAX_BYTES: number;
|
|
21
31
|
export declare const DEFAULT_CONTEXT_FILES_MAX_TOTAL_BYTES: number;
|
|
@@ -29,6 +29,47 @@ function loadContextFileFromDir(dir) {
|
|
|
29
29
|
}
|
|
30
30
|
return null;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* The global user-scope context file (senpi#5567). `contextFiles.globalPath` names a file (or a
|
|
34
|
+
* directory to probe for the usual candidates) to load in place of the agent-dir file. Precedence
|
|
35
|
+
* is defined and never errors: a blank or unset path keeps the agent-dir probe silently; a
|
|
36
|
+
* configured target that is missing, unreadable, a special file, or a directory with no candidates
|
|
37
|
+
* falls back to the agent-dir probe and returns one warning naming the configured path.
|
|
38
|
+
*/
|
|
39
|
+
function loadGlobalContextFile(agentDir, globalPath) {
|
|
40
|
+
const explicit = typeof globalPath === "string" ? globalPath.trim() : "";
|
|
41
|
+
if (explicit === "")
|
|
42
|
+
return { file: loadContextFileFromDir(agentDir) };
|
|
43
|
+
const resolved = resolvePath(explicit, agentDir);
|
|
44
|
+
const fallBack = (problem) => ({
|
|
45
|
+
file: loadContextFileFromDir(agentDir),
|
|
46
|
+
diagnostic: {
|
|
47
|
+
type: "warning",
|
|
48
|
+
path: resolved,
|
|
49
|
+
message: `contextFiles.globalPath ${problem}; using the global context file from ${agentDir} instead.`,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
let stats;
|
|
53
|
+
try {
|
|
54
|
+
stats = statSync(resolved);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const code = error.code;
|
|
58
|
+
return fallBack(code === "ENOENT" || code === "ENOTDIR" ? "does not exist" : `could not be read (${String(error)})`);
|
|
59
|
+
}
|
|
60
|
+
if (stats.isDirectory()) {
|
|
61
|
+
const file = loadContextFileFromDir(resolved);
|
|
62
|
+
return file ? { file } : fallBack("is a directory with no AGENTS.md or CLAUDE.md");
|
|
63
|
+
}
|
|
64
|
+
if (!stats.isFile())
|
|
65
|
+
return fallBack("is not a regular file or directory");
|
|
66
|
+
try {
|
|
67
|
+
return { file: { path: resolved, content: stripBom(readFileSync(resolved, "utf-8")) } };
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return fallBack(`could not be read (${String(error)})`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
32
73
|
/**
|
|
33
74
|
* The main repo's context file that a nested linked worktree's own copy shadows: both
|
|
34
75
|
* occupy the same logical repository scope, so loading both applies that context twice. Returns
|
|
@@ -142,21 +183,22 @@ function applyContextFileLimits(files, limits) {
|
|
|
142
183
|
}
|
|
143
184
|
return Object.assign(kept, { diagnostics });
|
|
144
185
|
}
|
|
145
|
-
/** Compares directories by their real path, ignoring case where the filesystem does (Windows). */
|
|
146
|
-
function
|
|
147
|
-
const real = canonicalizePath(resolvePath(
|
|
186
|
+
/** Compares files and directories by their real path, ignoring case where the filesystem does (Windows). */
|
|
187
|
+
function pathKey(path) {
|
|
188
|
+
const real = canonicalizePath(resolvePath(path));
|
|
148
189
|
return process.platform === "win32" ? real.toLowerCase() : real;
|
|
149
190
|
}
|
|
150
191
|
export function loadProjectContextFiles(options) {
|
|
151
192
|
const resolvedCwd = resolvePath(options.cwd);
|
|
152
193
|
const resolvedAgentDir = resolvePath(options.agentDir);
|
|
153
|
-
const homeKey =
|
|
194
|
+
const homeKey = pathKey(options.homeDir ?? homedir());
|
|
154
195
|
const contextFiles = [];
|
|
196
|
+
// Real-path keys: a symlinked ancestor file that points at an already loaded file is the same file.
|
|
155
197
|
const seenPaths = new Set();
|
|
156
|
-
const globalContext =
|
|
157
|
-
if (globalContext) {
|
|
158
|
-
contextFiles.push({ ...globalContext, scope: "user" });
|
|
159
|
-
seenPaths.add(globalContext.path);
|
|
198
|
+
const globalContext = loadGlobalContextFile(resolvedAgentDir, options.globalPath);
|
|
199
|
+
if (globalContext.file) {
|
|
200
|
+
contextFiles.push({ ...globalContext.file, scope: "user" });
|
|
201
|
+
seenPaths.add(pathKey(globalContext.file.path));
|
|
160
202
|
}
|
|
161
203
|
const ancestorContextFiles = [];
|
|
162
204
|
const shadowedContextFile = findShadowedContextFile(resolvedCwd);
|
|
@@ -164,9 +206,10 @@ export function loadProjectContextFiles(options) {
|
|
|
164
206
|
while (true) {
|
|
165
207
|
const contextFile = loadContextFileFromDir(currentDir);
|
|
166
208
|
const isShadowed = shadowedContextFile !== undefined && canonicalizePath(contextFile?.path ?? "") === shadowedContextFile;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
209
|
+
const contextFileKey = contextFile ? pathKey(contextFile.path) : undefined;
|
|
210
|
+
if (contextFile && contextFileKey !== undefined && !isShadowed && !seenPaths.has(contextFileKey)) {
|
|
211
|
+
ancestorContextFiles.unshift(pathKey(currentDir) === homeKey ? { ...contextFile, scope: "user" } : contextFile);
|
|
212
|
+
seenPaths.add(contextFileKey);
|
|
170
213
|
}
|
|
171
214
|
const parentDir = dirname(currentDir);
|
|
172
215
|
if (parentDir === currentDir)
|
|
@@ -174,6 +217,9 @@ export function loadProjectContextFiles(options) {
|
|
|
174
217
|
currentDir = parentDir;
|
|
175
218
|
}
|
|
176
219
|
contextFiles.push(...ancestorContextFiles);
|
|
177
|
-
|
|
220
|
+
const limited = applyContextFileLimits(contextFiles, options);
|
|
221
|
+
if (globalContext.diagnostic)
|
|
222
|
+
limited.diagnostics.unshift(globalContext.diagnostic);
|
|
223
|
+
return limited;
|
|
178
224
|
}
|
|
179
225
|
//# sourceMappingURL=context-files.js.map
|
|
@@ -53,6 +53,8 @@ export type CredentialAccountCheck = {
|
|
|
53
53
|
readonly model: string;
|
|
54
54
|
readonly outcome: "ok" | "failed";
|
|
55
55
|
readonly reason?: string;
|
|
56
|
+
readonly message?: string;
|
|
57
|
+
readonly status?: number;
|
|
56
58
|
readonly at: number;
|
|
57
59
|
};
|
|
58
60
|
export declare function assertValidAccountName(name: string): void;
|
|
@@ -38,7 +38,16 @@ function storedCheck(slot) {
|
|
|
38
38
|
if (model === undefined || at === undefined || (outcome !== "ok" && outcome !== "failed"))
|
|
39
39
|
return undefined;
|
|
40
40
|
const reason = stringField(check, "reason");
|
|
41
|
-
|
|
41
|
+
const message = stringField(check, "message");
|
|
42
|
+
const status = numberField(check, "status");
|
|
43
|
+
return {
|
|
44
|
+
model,
|
|
45
|
+
outcome,
|
|
46
|
+
...(reason === undefined ? {} : { reason }),
|
|
47
|
+
...(message === undefined ? {} : { message }),
|
|
48
|
+
...(status === undefined ? {} : { status }),
|
|
49
|
+
at,
|
|
50
|
+
};
|
|
42
51
|
}
|
|
43
52
|
/** The listing fields of a stored `claude-cli` slot, read defensively: auth.json is a trust boundary. */
|
|
44
53
|
function claudeCliSlotFields(slot) {
|
|
@@ -24,7 +24,7 @@ const ROUTE_RULES = {
|
|
|
24
24
|
full: `Route by true intent, not surface form:
|
|
25
25
|
- Information asks (explain, look into, investigate): read the code, report the answer or findings - no edits, no fixes yet.
|
|
26
26
|
- Judgment asks (what do you think, review) and open-ended changes (refactor, improve, clean up): assess and propose, then wait for confirmation.
|
|
27
|
-
- Change asks (implement, add, fix this error): build, or diagnose and fix
|
|
27
|
+
- Change asks (implement, add, fix this error): build, or diagnose and fix at the cause, at exactly the asked scope - what fully satisfies an open-ended goal and nothing beyond it; name an ambiguity and resolve it from context when possible.
|
|
28
28
|
|
|
29
29
|
Deliver the task at the scope asked - never quietly narrow, widen, or swap it. Make routine judgment calls yourself; ask only when different readings of the request would lead to materially different work.
|
|
30
30
|
|
|
@@ -32,7 +32,7 @@ Derive intent from the latest user turn alone: a new direction drops the stale p
|
|
|
32
32
|
diet: `Route by true intent, not surface form:
|
|
33
33
|
- Information ask (explain, look into, investigate): read code, report answer/findings; no edits, no fixes yet.
|
|
34
34
|
- Judgment ask (what do you think, review) / open-ended change (refactor, improve, clean up): assess, propose, wait for confirmation.
|
|
35
|
-
- Change ask (implement, add, fix this error): build, or diagnose +
|
|
35
|
+
- Change ask (implement, add, fix this error): build, or diagnose + fix at the cause, exactly at asked scope = what fully satisfies an open-ended goal, nothing beyond; name ambiguity, resolve from context when possible.
|
|
36
36
|
|
|
37
37
|
Deliver at asked scope; never quietly narrow, widen, swap. Routine calls: decide yourself; ask only when readings diverge into materially different work.
|
|
38
38
|
|
|
@@ -4,7 +4,7 @@ export function buildStyleSection(options = {}) {
|
|
|
4
4
|
if (options.sharedSections === "full") {
|
|
5
5
|
return `## Style
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
This codebase is yours: what it's for and how it's built are your call, and you'll keep building on it. Change it the way its owner would: build on the code that already does the job instead of adding a parallel copy, fit new behavior into the structure that is there, and leave no duplicate or dead code behind. A defect in the code you are changing is yours to fix now; one elsewhere goes in your summary as a follow-up. No helpers or abstractions for hypothetical needs, no defensive checks inside trusted code. Trust framework guarantees; validate only at system boundaries. Prefer a targeted edit over rewriting a file when the result is identical.
|
|
8
8
|
|
|
9
9
|
Act, then report. Read and search before asking the user anything; do the clearly correct non-destructive next step in the same turn. Permission-begging ("Shall I?") is prohibited. Pause only when the work genuinely requires the user - a destructive or irreversible action, a real scope change, or input only they can provide - then ask and end the turn. Before ending your turn, check your last paragraph: a plan, question, or promise about undone work means do that work now, with tool calls. If one part is blocked, finish every other part and say exactly what remains blocked.
|
|
10
10
|
|
|
@@ -16,7 +16,7 @@ Do not stop, summarize, or suggest a new session on account of context limits: t
|
|
|
16
16
|
}
|
|
17
17
|
return `## Style
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
This codebase is yours: what it's for and how it's built are your call, and you'll keep building on it. Change it as its owner would: build on the code that already does the job, not a parallel copy; fit new behavior into the structure that is there; leave no duplicate or dead code behind. Defect in the code you are changing -> fix it now; elsewhere -> follow-up in your summary. No helpers/abstractions for hypothetical needs, no defensive checks in trusted code. Trust framework guarantees; validate at system boundaries only. Targeted edit over file rewrite when result identical.
|
|
20
20
|
|
|
21
21
|
Act, then report. Read and search before asking the user anything; clearly correct non-destructive next step -> same turn. Permission-begging ("Shall I?") prohibited. Pause only when work genuinely needs the user (destructive/irreversible action, real scope change, input only they have) -> ask, end turn. Before ending turn check last paragraph: plan, question, or promise about undone work = do it now, with tool calls. One part blocked -> finish the rest, state exactly what remains blocked.
|
|
22
22
|
|
|
@@ -69,7 +69,7 @@ Tier the scope, never the rigor.
|
|
|
69
69
|
|
|
70
70
|
${buildTestDisciplineSection("full")}
|
|
71
71
|
|
|
72
|
-
"Should pass" is not verification - run the validator. Before reporting progress, audit each claim against a tool result from this session: ${FULL_CLAIM_AUDIT[terminalOrApp(options.surface ?? "terminal")]} Fix
|
|
72
|
+
"Should pass" is not verification - run the validator. Before reporting progress, audit each claim against a tool result from this session: ${FULL_CLAIM_AUDIT[terminalOrApp(options.surface ?? "terminal")]} Fix failures your change caused and any that sit in the code you changed; note other pre-existing failures separately.`;
|
|
73
73
|
}
|
|
74
74
|
return `## Verification
|
|
75
75
|
|
|
@@ -81,6 +81,6 @@ Tier the scope, never the rigor.
|
|
|
81
81
|
|
|
82
82
|
${buildTestDisciplineSection()}
|
|
83
83
|
|
|
84
|
-
Before reporting progress: audit each claim against a tool result from this session; ${CLAIM_AUDIT[terminalOrApp(options.surface ?? "terminal")]} Fix
|
|
84
|
+
Before reporting progress: audit each claim against a tool result from this session; ${CLAIM_AUDIT[terminalOrApp(options.surface ?? "terminal")]} Fix failures your change caused and any that sit in the code you changed; note other pre-existing failures separately.`;
|
|
85
85
|
}
|
|
86
86
|
//# sourceMappingURL=verification.js.map
|
|
@@ -168,11 +168,24 @@ export interface HookModelRequest {
|
|
|
168
168
|
readonly claim: SignedPlacementClaim;
|
|
169
169
|
readonly input: HookModelRequestInput;
|
|
170
170
|
}
|
|
171
|
+
/** A user hook's failure on the hand: reported with the reply, as a fused session reports it, never thrown. */
|
|
172
|
+
export interface HookFailure {
|
|
173
|
+
readonly extensionPath: string;
|
|
174
|
+
readonly event: string;
|
|
175
|
+
readonly error: string;
|
|
176
|
+
}
|
|
171
177
|
export interface HookModelRequestReply {
|
|
172
178
|
readonly t: "hook.model_request.reply";
|
|
173
179
|
readonly sessionId: string;
|
|
174
180
|
readonly stepId: string;
|
|
175
181
|
readonly output: HookModelRequestInput;
|
|
182
|
+
/** The hooks that failed; `output` is what the others produced. Absent: none failed. */
|
|
183
|
+
readonly errors?: readonly HookFailure[];
|
|
184
|
+
/** The messages and notices the hooks sent during the call, as on every loop-hook reply (S33). Absent: none. */
|
|
185
|
+
readonly sent?: readonly WireJson[];
|
|
186
|
+
readonly notices?: readonly WireJson[];
|
|
187
|
+
/** Late messages and notices the hand dropped past its per-session bound. Absent: none. */
|
|
188
|
+
readonly droppedLate?: number;
|
|
176
189
|
}
|
|
177
190
|
export interface HandSessionAdvertisement {
|
|
178
191
|
readonly t: "hand.session.advertise";
|
|
@@ -12,7 +12,7 @@ import { accountDirFor, claudeCliSharedRoot, ensureAccountDir } from "./claude-c
|
|
|
12
12
|
import { buildClaudeCliEnvironment } from "./claude-cli-environment.js";
|
|
13
13
|
import { profileChanged, verifyClaudeCliInitialization } from "./claude-cli-token-source.js";
|
|
14
14
|
import { writeConfigDirCredential } from "./config-dir-credentials.js";
|
|
15
|
-
import { asksLegacyLongContext, CLAUDE_CODE_DEFAULT_CONTEXT_WINDOW } from "./context-window.js";
|
|
15
|
+
import { asksLegacyLongContext, CLAUDE_CODE_DEFAULT_CONTEXT_WINDOW, claudeCodeMaxContextTokens, } from "./context-window.js";
|
|
16
16
|
import { isExtraUsageExhausted } from "./errors.js";
|
|
17
17
|
import { runFailover } from "./failover.js";
|
|
18
18
|
import { logContinuityEvent } from "./session-observability.js";
|
|
@@ -153,7 +153,8 @@ export async function* queryWithAuthLane(input) {
|
|
|
153
153
|
options.model = options.model?.replace(/\[1m\]$/, "");
|
|
154
154
|
options.env = {
|
|
155
155
|
...options.env,
|
|
156
|
-
|
|
156
|
+
// Claude Code then refuses only past the 200k window itself; the prompt-plus-output check below keeps the fit.
|
|
157
|
+
CLAUDE_CODE_MAX_CONTEXT_TOKENS: String(claudeCodeMaxContextTokens(CLAUDE_CODE_DEFAULT_CONTEXT_WINDOW, outputReserveTokens)),
|
|
157
158
|
// Reserve and request the same output budget, not the model catalog's ceiling.
|
|
158
159
|
CLAUDE_CODE_MAX_OUTPUT_TOKENS: String(outputReserveTokens),
|
|
159
160
|
};
|
|
@@ -61,7 +61,9 @@ export async function testClaudeCliAccount(input) {
|
|
|
61
61
|
return stored;
|
|
62
62
|
return {
|
|
63
63
|
...credential,
|
|
64
|
-
accounts: (credential.accounts ?? []).map((slot) => slot.name === input.name
|
|
64
|
+
accounts: (credential.accounts ?? []).map((slot) => slot.name === input.name && slot.store === "claude-cli" && slot.dirId === before.dirId
|
|
65
|
+
? checkedSlot(slot, check)
|
|
66
|
+
: slot),
|
|
65
67
|
};
|
|
66
68
|
});
|
|
67
69
|
return check;
|
|
@@ -4,6 +4,8 @@ export type DefaultModelSelection = {
|
|
|
4
4
|
readonly provider?: string;
|
|
5
5
|
readonly model?: string;
|
|
6
6
|
};
|
|
7
|
+
/** auth.json keeps the redacted provider message for the UI; a proxy's HTML error page must not bloat it. */
|
|
8
|
+
export declare const STORED_CHECK_MESSAGE_MAX_CHARS = 2000;
|
|
7
9
|
/**
|
|
8
10
|
* The model the sign-in connection test runs on: the default model when the default provider is this one, else the
|
|
9
11
|
* provider's own default (`defaultModelPerProvider`), so the test exercises the model the user's turns will use.
|
|
@@ -21,7 +23,7 @@ export type ClaudeCliConnectionTestInput = {
|
|
|
21
23
|
};
|
|
22
24
|
/**
|
|
23
25
|
* One "Reply with OK" turn on the named account, pinned with account fallback off, no tools, no setting sources and
|
|
24
|
-
* no persisted session. The outcome
|
|
26
|
+
* no persisted session. The outcome uses the turn classifiers and retains the provider status and redacted message.
|
|
25
27
|
*/
|
|
26
28
|
export declare function runClaudeCliConnectionTest(input: ClaudeCliConnectionTestInput): Promise<ClaudeCliAccountCheck>;
|
|
27
29
|
//# sourceMappingURL=claude-cli-connection-test.d.ts.map
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import { defaultModelPerProvider } from "../../../model-resolver.js";
|
|
2
|
+
import { redactSecrets } from "../../../sensitive-output.js";
|
|
2
3
|
import { ANTHROPIC_SUBSCRIPTION_PROVIDER_ID } from "./account-management.js";
|
|
3
4
|
import { queryWithAuthLane } from "./auth-lane.js";
|
|
4
|
-
import { classifySdkError, sdkAssistantFailure, sdkResultFailure } from "./errors.js";
|
|
5
|
+
import { classifySdkError, errorText, sdkAssistantFailure, sdkResultFailure } from "./errors.js";
|
|
5
6
|
import { refusalError } from "./refusal.js";
|
|
6
7
|
import { getSdkBoundary, loadClaudeAgentSdk } from "./sdk-boundary.js";
|
|
7
8
|
const CONNECTION_TEST_PROMPT = "Reply with OK";
|
|
8
9
|
const CONNECTION_TEST_TIMEOUT_MS = 60_000;
|
|
10
|
+
/** auth.json keeps the redacted provider message for the UI; a proxy's HTML error page must not bloat it. */
|
|
11
|
+
export const STORED_CHECK_MESSAGE_MAX_CHARS = 2_000;
|
|
12
|
+
function storedMessage(error) {
|
|
13
|
+
const message = redactSecrets(errorText(error));
|
|
14
|
+
if (message.length <= STORED_CHECK_MESSAGE_MAX_CHARS)
|
|
15
|
+
return message;
|
|
16
|
+
let end = STORED_CHECK_MESSAGE_MAX_CHARS - 1;
|
|
17
|
+
// Never end on the first half of a surrogate pair.
|
|
18
|
+
const last = message.charCodeAt(end - 1);
|
|
19
|
+
if (last >= 0xd800 && last <= 0xdbff)
|
|
20
|
+
end -= 1;
|
|
21
|
+
return `${message.slice(0, end)}…`;
|
|
22
|
+
}
|
|
9
23
|
/**
|
|
10
24
|
* The model the sign-in connection test runs on: the default model when the default provider is this one, else the
|
|
11
25
|
* provider's own default (`defaultModelPerProvider`), so the test exercises the model the user's turns will use.
|
|
@@ -20,7 +34,7 @@ export function connectionTestModel(defaults) {
|
|
|
20
34
|
}
|
|
21
35
|
/**
|
|
22
36
|
* One "Reply with OK" turn on the named account, pinned with account fallback off, no tools, no setting sources and
|
|
23
|
-
* no persisted session. The outcome
|
|
37
|
+
* no persisted session. The outcome uses the turn classifiers and retains the provider status and redacted message.
|
|
24
38
|
*/
|
|
25
39
|
export async function runClaudeCliConnectionTest(input) {
|
|
26
40
|
const now = input.now ?? Date.now;
|
|
@@ -29,12 +43,27 @@ export async function runClaudeCliConnectionTest(input) {
|
|
|
29
43
|
let handle;
|
|
30
44
|
const closeOnAbort = () => handle?.close();
|
|
31
45
|
signal.addEventListener("abort", closeOnAbort, { once: true });
|
|
32
|
-
const finish = (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
const finish = (failure) => {
|
|
47
|
+
if (failure === undefined)
|
|
48
|
+
return { model: input.model, outcome: "ok", at: now() };
|
|
49
|
+
const { reason, error } = failure;
|
|
50
|
+
const status = failure.providerStatus ??
|
|
51
|
+
(error !== null && typeof error === "object" && "status" in error ? error.status : undefined);
|
|
52
|
+
return {
|
|
53
|
+
model: input.model,
|
|
54
|
+
outcome: "failed",
|
|
55
|
+
reason,
|
|
56
|
+
message: storedMessage(error),
|
|
57
|
+
...(typeof status === "number" ? { status } : {}),
|
|
58
|
+
at: now(),
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
// The deadline and the caller's cancel win over whatever the SDK reports after close().
|
|
62
|
+
const abortedCheck = () => deadline.aborted
|
|
63
|
+
? finish({ reason: "timeout", error: "Connection test timed out." })
|
|
64
|
+
: input.signal?.aborted
|
|
65
|
+
? finish({ reason: "cancelled", error: "Connection test was cancelled." })
|
|
66
|
+
: undefined;
|
|
38
67
|
try {
|
|
39
68
|
await loadClaudeAgentSdk();
|
|
40
69
|
const messages = queryWithAuthLane({
|
|
@@ -69,18 +98,20 @@ export async function runClaudeCliConnectionTest(input) {
|
|
|
69
98
|
? sdkResultFailure(message)
|
|
70
99
|
: undefined);
|
|
71
100
|
if (failure)
|
|
72
|
-
|
|
101
|
+
return (abortedCheck() ??
|
|
102
|
+
finish({
|
|
103
|
+
reason: classifySdkError(failure).kind,
|
|
104
|
+
error: failure,
|
|
105
|
+
providerStatus: message.type === "result" && "api_error_status" in message ? message.api_error_status : undefined,
|
|
106
|
+
}));
|
|
73
107
|
if (message.type === "result")
|
|
74
|
-
return finish(
|
|
108
|
+
return finish();
|
|
75
109
|
}
|
|
76
|
-
return
|
|
110
|
+
return (abortedCheck() ??
|
|
111
|
+
finish({ reason: "no_result", error: "Claude Code ended the connection test without a result." }));
|
|
77
112
|
}
|
|
78
113
|
catch (error) {
|
|
79
|
-
|
|
80
|
-
return finish("failed", "timeout");
|
|
81
|
-
if (input.signal?.aborted)
|
|
82
|
-
return finish("failed", "cancelled");
|
|
83
|
-
return finish("failed", classifySdkError(error).kind);
|
|
114
|
+
return abortedCheck() ?? finish({ reason: classifySdkError(error).kind, error });
|
|
84
115
|
}
|
|
85
116
|
finally {
|
|
86
117
|
signal.removeEventListener("abort", closeOnAbort);
|
|
@@ -6,7 +6,7 @@ import type { ClaudeCliProfile } from "./claude-cli-auth-status.ts";
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function signedInSlot(previous: AccountSlot | undefined, name: string, dirId: string, profile: ClaudeCliProfile, at: number): ClaudeCliAccountSlot;
|
|
8
8
|
export declare function withSlot(credential: AnthropicSubscriptionCredential, slot: AccountSlot): AnthropicSubscriptionCredential;
|
|
9
|
-
export declare function withCheck(credential: AnthropicSubscriptionCredential, name: string, check: ClaudeCliAccountCheck): AnthropicSubscriptionCredential;
|
|
9
|
+
export declare function withCheck(credential: AnthropicSubscriptionCredential, name: string, check: ClaudeCliAccountCheck, dirId: string): AnthropicSubscriptionCredential;
|
|
10
10
|
/**
|
|
11
11
|
* The accounts with this login taken back. Only a slot that still points at this login's dir is touched: a new
|
|
12
12
|
* account's slot is removed. For a re-login the login-bound fields always return to their previous values; every
|
|
@@ -27,10 +27,12 @@ export function withSlot(credential, slot) {
|
|
|
27
27
|
? { ...credential, accounts: accounts.map((candidate) => (candidate.name === slot.name ? slot : candidate)) }
|
|
28
28
|
: { ...credential, accounts: [...accounts, slot] };
|
|
29
29
|
}
|
|
30
|
-
export function withCheck(credential, name, check) {
|
|
30
|
+
export function withCheck(credential, name, check, dirId) {
|
|
31
31
|
return {
|
|
32
32
|
...credential,
|
|
33
|
-
accounts: (credential.accounts ?? []).map((candidate) => candidate.name === name && candidate.store === "claude-cli"
|
|
33
|
+
accounts: (credential.accounts ?? []).map((candidate) => candidate.name === name && candidate.store === "claude-cli" && candidate.dirId === dirId
|
|
34
|
+
? { ...candidate, check }
|
|
35
|
+
: candidate),
|
|
34
36
|
};
|
|
35
37
|
}
|
|
36
38
|
/**
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ResolveSettingsOptions, ResolvedSettings, SettingSource } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { type AnthropicSubscriptionProviderSettings } from "./settings.ts";
|
|
3
|
+
export type ClaudeSettingsEnvResolver = (options: ResolveSettingsOptions) => Promise<ResolvedSettings>;
|
|
4
|
+
/**
|
|
5
|
+
* Read the effective `env` block Claude Code will apply from the settings files a query loads (senpi#2988 item 4).
|
|
6
|
+
* Uses the SDK's own settings merge engine, so the files, lookup rules and precedence are the CLI's, not a re-read.
|
|
7
|
+
* Returns undefined when no loaded settings file sets an `env` block, or when the merge fails — the caller then pins
|
|
8
|
+
* as if no settings lifetime existed, instead of failing the turn.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveClaudeSettingsEnv(input: {
|
|
11
|
+
cwd: string;
|
|
12
|
+
settingSources: SettingSource[];
|
|
13
|
+
}, resolveSettings?: ClaudeSettingsEnvResolver): Promise<Readonly<Record<string, string>> | undefined>;
|
|
14
|
+
/**
|
|
15
|
+
* The settings env for one stream's queries. An explicit `settingSources` list applies to every lane; otherwise only
|
|
16
|
+
* a preset-append ambient attempt loads user/project settings (the same rule `buildAnthropicSubscriptionQueryOptions`
|
|
17
|
+
* uses), so anything else resolves to nothing and no merge runs.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveQuerySettingsEnv(cwd: string, providerSettings: AnthropicSubscriptionProviderSettings): Promise<Readonly<Record<string, string>> | undefined>;
|
|
20
|
+
//# sourceMappingURL=claude-settings-env.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { loadedClaudeAgentSdk } from "./sdk-boundary.lazy.js";
|
|
2
|
+
import { resolveSystemPromptMode } from "./settings.js";
|
|
3
|
+
async function defaultResolveSettings(options) {
|
|
4
|
+
const sdk = loadedClaudeAgentSdk();
|
|
5
|
+
if (!sdk) {
|
|
6
|
+
throw new Error(`Claude Agent SDK was not preloaded before 'resolveSettings'. ` +
|
|
7
|
+
`Await loadClaudeAgentSdk() on the entry path before reaching the SDK boundary.`);
|
|
8
|
+
}
|
|
9
|
+
return sdk.resolveSettings(options);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Read the effective `env` block Claude Code will apply from the settings files a query loads (senpi#2988 item 4).
|
|
13
|
+
* Uses the SDK's own settings merge engine, so the files, lookup rules and precedence are the CLI's, not a re-read.
|
|
14
|
+
* Returns undefined when no loaded settings file sets an `env` block, or when the merge fails — the caller then pins
|
|
15
|
+
* as if no settings lifetime existed, instead of failing the turn.
|
|
16
|
+
*/
|
|
17
|
+
export async function resolveClaudeSettingsEnv(input, resolveSettings = defaultResolveSettings) {
|
|
18
|
+
try {
|
|
19
|
+
const resolved = await resolveSettings({ cwd: input.cwd, settingSources: input.settingSources });
|
|
20
|
+
const env = resolved.effective.env;
|
|
21
|
+
return env !== undefined && Object.keys(env).length > 0 ? env : undefined;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The settings env for one stream's queries. An explicit `settingSources` list applies to every lane; otherwise only
|
|
29
|
+
* a preset-append ambient attempt loads user/project settings (the same rule `buildAnthropicSubscriptionQueryOptions`
|
|
30
|
+
* uses), so anything else resolves to nothing and no merge runs.
|
|
31
|
+
*/
|
|
32
|
+
export async function resolveQuerySettingsEnv(cwd, providerSettings) {
|
|
33
|
+
const settingSources = providerSettings.settingSources ??
|
|
34
|
+
(resolveSystemPromptMode(providerSettings).mode === "preset-append" ? ["user", "project"] : []);
|
|
35
|
+
if (settingSources.length === 0)
|
|
36
|
+
return undefined;
|
|
37
|
+
return resolveClaudeSettingsEnv({ cwd, settingSources });
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=claude-settings-env.js.map
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
2
2
|
/** Claude Code's default window when a request does not ask for the long context. */
|
|
3
3
|
export declare const CLAUDE_CODE_DEFAULT_CONTEXT_WINDOW = 200000;
|
|
4
|
+
/**
|
|
5
|
+
* The `CLAUDE_CODE_MAX_CONTEXT_TOKENS` that makes Claude Code accept a conversation up to `window`.
|
|
6
|
+
*
|
|
7
|
+
* With `DISABLE_COMPACT` set, Claude Code takes that variable as the model's window, then refuses a
|
|
8
|
+
* request on its own, with no API call, once the conversation passes the window minus its output reserve
|
|
9
|
+
* (the request's output budget, capped at 20k) minus a 3k buffer. Handing it the bare planned window put
|
|
10
|
+
* that limit 23k below the window senpi compacts against, so every turn between the two failed in
|
|
11
|
+
* milliseconds with "Prompt is too long", and so did the summarization request of the recovery
|
|
12
|
+
* compaction. senpi keeps its own output reserve below `window`, so the variable carries the window plus
|
|
13
|
+
* Claude Code's reserve and Claude Code's limit lands on `window` itself.
|
|
14
|
+
*
|
|
15
|
+
* `outputTokens` is the output budget Claude Code reserves for the request. Without an explicit
|
|
16
|
+
* `CLAUDE_CODE_MAX_OUTPUT_TOKENS` it is the model's own default, which is at least the cap for every
|
|
17
|
+
* Claude model, so the cap is the default here; a larger addition only lets a request reach the API's own
|
|
18
|
+
* window check, whose error senpi's overflow recovery already parses.
|
|
19
|
+
*/
|
|
20
|
+
export declare function claudeCodeMaxContextTokens(window: number, outputTokens?: number): number;
|
|
4
21
|
/**
|
|
5
22
|
* Models whose 1M window is reachable only through Claude Code's `[1m]` opt-in, which sends the legacy
|
|
6
23
|
* `context-1m-2025-08-07` beta that a subscription without extra usage refuses. These are the rows of
|