@code-yeongyu/senpi 2026.8.30 → 2026.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +174 -2
- package/README.md +3 -0
- package/dist/core/agent-session.d.ts +28 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +161 -14
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction-execution.d.ts +14 -0
- package/dist/core/compaction/compaction-execution.d.ts.map +1 -0
- package/dist/core/compaction/compaction-execution.js +121 -0
- package/dist/core/compaction/compaction-execution.js.map +1 -0
- package/dist/core/compaction/compaction-settings.d.ts +17 -0
- package/dist/core/compaction/compaction-settings.d.ts.map +1 -0
- package/dist/core/compaction/compaction-settings.js +17 -0
- package/dist/core/compaction/compaction-settings.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +13 -26
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +7 -136
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/ideal-compaction-settings.d.ts +9 -0
- package/dist/core/compaction/ideal-compaction-settings.d.ts.map +1 -0
- package/dist/core/compaction/ideal-compaction-settings.js +7 -0
- package/dist/core/compaction/ideal-compaction-settings.js.map +1 -0
- package/dist/core/compaction-settings-access.d.ts +19 -0
- package/dist/core/compaction-settings-access.d.ts.map +1 -0
- package/dist/core/compaction-settings-access.js +10 -0
- package/dist/core/compaction-settings-access.js.map +1 -0
- package/dist/core/compaction-settings-resolver.d.ts +22 -0
- package/dist/core/compaction-settings-resolver.d.ts.map +1 -0
- package/dist/core/compaction-settings-resolver.js +46 -0
- package/dist/core/compaction-settings-resolver.js.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts +9 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js +10 -3
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +24 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js +43 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +8 -2
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts +17 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.js +64 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts +27 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.js +84 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/idle-retry.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.js +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle.js +13 -2
- package/dist/core/extensions/builtin/compaction/idle.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +152 -154
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.js +2 -0
- package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/model-selection.d.ts +14 -0
- package/dist/core/extensions/builtin/compaction/model-selection.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/model-selection.js +37 -0
- package/dist/core/extensions/builtin/compaction/model-selection.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +30 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js +74 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts +9 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js +2 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -6
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/orchestration.d.ts +46 -0
- package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js +103 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/policy.d.ts +12 -2
- package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/policy.js +52 -26
- package/dist/core/extensions/builtin/compaction/policy.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts +8 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.js +17 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.d.ts +22 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.js +16 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +23 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.js +132 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -13
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +21 -197
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts +24 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.js +25 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +27 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.js +56 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.js.map +1 -0
- package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts +5 -0
- package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts.map +1 -0
- package/dist/core/extensions/builtin/hooks/trust-state-json.js +76 -0
- package/dist/core/extensions/builtin/hooks/trust-state-json.js.map +1 -0
- package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +7 -1
- package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
- package/dist/core/extensions/builtin/hooks/trust-storage.js +60 -8
- package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
- package/dist/core/extensions/builtin/hooks/trust.d.ts +1 -2
- package/dist/core/extensions/builtin/hooks/trust.d.ts.map +1 -1
- package/dist/core/extensions/builtin/hooks/trust.js +1 -72
- package/dist/core/extensions/builtin/hooks/trust.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts +3 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +108 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.js +11 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
- package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.js +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +11 -0
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.js +18 -2
- package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
- package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ttsr/index.js +4 -0
- package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
- package/dist/core/extensions/builtin/ttsr/manager.d.ts +2 -0
- package/dist/core/extensions/builtin/ttsr/manager.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ttsr/manager.js +28 -1
- package/dist/core/extensions/builtin/ttsr/manager.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +7 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts +14 -0
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js +33 -3
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/retry-fallback/log.js +1 -1
- package/dist/core/retry-fallback/log.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js +1 -0
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-activity.d.ts +47 -0
- package/dist/core/session-activity.d.ts.map +1 -0
- package/dist/core/session-activity.js +58 -0
- package/dist/core/session-activity.js.map +1 -0
- package/dist/core/session-manager.d.ts +8 -12
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +118 -7
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-resident-store.d.ts +8 -1
- package/dist/core/session-resident-store.d.ts.map +1 -1
- package/dist/core/session-resident-store.js +12 -5
- package/dist/core/session-resident-store.js.map +1 -1
- package/dist/core/settings-manager.d.ts +8 -85
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +9 -17
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-public-types.d.ts +11 -0
- package/dist/core/settings-public-types.d.ts.map +1 -0
- package/dist/core/settings-public-types.js +2 -0
- package/dist/core/settings-public-types.js.map +1 -0
- package/dist/core/settings-shapes.d.ts +36 -0
- package/dist/core/settings-shapes.d.ts.map +1 -0
- package/dist/core/settings-shapes.js +2 -0
- package/dist/core/settings-shapes.js.map +1 -0
- package/dist/core/shared-host-policy.d.ts +6 -0
- package/dist/core/shared-host-policy.d.ts.map +1 -0
- package/dist/core/shared-host-policy.js +7 -0
- package/dist/core/shared-host-policy.js.map +1 -0
- package/dist/core/terminal-settings.d.ts +22 -0
- package/dist/core/terminal-settings.d.ts.map +1 -0
- package/dist/core/terminal-settings.js +2 -0
- package/dist/core/terminal-settings.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +4 -4
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +27 -11
- package/dist/main.js.map +1 -1
- package/dist/modes/app-server/daemon/process.d.ts +13 -2
- package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
- package/dist/modes/app-server/daemon/process.js +58 -12
- package/dist/modes/app-server/daemon/process.js.map +1 -1
- package/dist/modes/app-server/daemon.js +65 -7
- package/dist/modes/app-server/daemon.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts +84 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +435 -112
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +11 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +59 -6
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/ethos-tips.js +1 -1
- package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts +12 -5
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +180 -25
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/custom-capability.d.ts +2 -0
- package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
- package/dist/modes/rpc/custom-capability.js +2 -0
- package/dist/modes/rpc/custom-capability.js.map +1 -1
- package/dist/modes/rpc/host-ensure.d.ts +17 -0
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
- package/dist/modes/rpc/host-ensure.js +150 -23
- package/dist/modes/rpc/host-ensure.js.map +1 -1
- package/dist/modes/rpc/host-lifecycle.d.ts +54 -0
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +259 -69
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/host-watchdog.d.ts +2 -2
- package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
- package/dist/modes/rpc/host-watchdog.js +89 -21
- package/dist/modes/rpc/host-watchdog.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.d.ts +38 -0
- package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +149 -61
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/ownership-safe-lock.d.ts +14 -0
- package/dist/modes/rpc/ownership-safe-lock.d.ts.map +1 -0
- package/dist/modes/rpc/ownership-safe-lock.js +87 -0
- package/dist/modes/rpc/ownership-safe-lock.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +13 -2
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +46 -12
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +21 -3
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js +1 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-binding.d.ts +2 -1
- package/dist/modes/rpc/session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/session-binding.js +1 -0
- package/dist/modes/rpc/session-binding.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts +54 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +180 -3
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +18 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +88 -8
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +11 -1
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +25 -0
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/socket-transport.d.ts +13 -0
- package/dist/modes/rpc/socket-transport.d.ts.map +1 -0
- package/dist/modes/rpc/socket-transport.js +92 -0
- package/dist/modes/rpc/socket-transport.js.map +1 -0
- package/dist/modes/rpc/widget-line-renderer.d.ts +17 -0
- package/dist/modes/rpc/widget-line-renderer.d.ts.map +1 -0
- package/dist/modes/rpc/widget-line-renderer.js +73 -0
- package/dist/modes/rpc/widget-line-renderer.js.map +1 -0
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js +11 -2
- package/dist/utils/fs-watch.js.map +1 -1
- package/docs/app-server.md +2 -2
- package/docs/containerization.md +2 -2
- package/docs/development.md +7 -7
- package/docs/extensions.md +5 -5
- package/docs/grok-neo.md +1 -1
- package/docs/index.md +1 -1
- package/docs/packages.md +2 -2
- package/docs/quickstart.md +4 -4
- package/docs/release-guide.md +21 -21
- package/docs/rpc.md +83 -6
- package/docs/sdk.md +1 -1
- package/docs/settings.md +4 -4
- package/docs/skills.md +2 -2
- package/docs/terminal-tools.md +1 -1
- package/docs/termux.md +1 -1
- package/docs/tui.md +1 -1
- package/examples/AGENTS.md +1 -1
- package/examples/sdk/README.md +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +52 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/skill-contribution.ts +71 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +3 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/SKILL.md +44 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/breaking-changes.md +75 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/build.md +114 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/dev-tooling.md +34 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/http-networking.md +113 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/install.md +93 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/node-compat-platforms.md +36 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/performance.md +33 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/runtime-apis.md +156 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/security.md +52 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/test.md +103 -0
- package/node_modules/@earendil-works/pi-agent-core/README.md +3 -0
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/README.md +6 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +24 -7
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +7 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +316 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +23 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +24 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +20 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts +42 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js +34 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts +8 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.js +51 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.js.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts +45 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-pty/dist/screen.js +178 -55
- package/node_modules/@earendil-works/pi-pty/dist/screen.js.map +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/README.md +6 -3
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/README.md +5 -4
- package/node_modules/@earendil-works/pi-tui/native/darwin/README.md +2 -2
- package/node_modules/@earendil-works/pi-tui/native/win32/README.md +2 -2
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Always-on admission cap for tool results.
|
|
3
|
+
*
|
|
4
|
+
* Oversized tool output is the dominant driver of single-step context bursts, so it is
|
|
5
|
+
* projected to a deterministic head/tail excerpt at the entrance instead of waiting for
|
|
6
|
+
* an emergency/compaction-budget pass (see `tool-truncation.ts`). Admission is derived
|
|
7
|
+
* from the supplied text on every request; model-visible marker text is never state.
|
|
8
|
+
*/
|
|
9
|
+
import { estimateTokens } from "../../../compaction/index.js";
|
|
10
|
+
const MAX_ADMISSION_CAP_TOKENS = 50_000;
|
|
11
|
+
const MIN_ADMISSION_CAP_TOKENS = 8192;
|
|
12
|
+
const ADMISSION_CAP_FRACTION = 0.05;
|
|
13
|
+
const HEAD_BUDGET_FRACTION = 0.6;
|
|
14
|
+
const TAIL_BUDGET_FRACTION = 0.2;
|
|
15
|
+
export const TOOL_ADMISSION_MARKER_PREFIX = "[tool result projected:";
|
|
16
|
+
/** Token budget a single tool result may occupy before it is projected. */
|
|
17
|
+
export function resolveToolResultAdmissionCapTokens(contextWindow) {
|
|
18
|
+
return Math.min(MAX_ADMISSION_CAP_TOKENS, Math.max(MIN_ADMISSION_CAP_TOKENS, Math.floor(ADMISSION_CAP_FRACTION * contextWindow)));
|
|
19
|
+
}
|
|
20
|
+
function estimateTextTokens(text) {
|
|
21
|
+
return estimateTokens({ role: "user", content: text, timestamp: 0 });
|
|
22
|
+
}
|
|
23
|
+
function buildExcerpt(text, budgetChars, totalTokens) {
|
|
24
|
+
const headChars = Math.floor(budgetChars * HEAD_BUDGET_FRACTION);
|
|
25
|
+
const tailChars = Math.floor(budgetChars * TAIL_BUDGET_FRACTION);
|
|
26
|
+
const head = text.slice(0, headChars);
|
|
27
|
+
const tail = text.slice(Math.max(headChars, text.length - tailChars));
|
|
28
|
+
const keptTokens = estimateTextTokens(head) + estimateTextTokens(tail);
|
|
29
|
+
return `${head}\n${TOOL_ADMISSION_MARKER_PREFIX} kept ${keptTokens} of ~${totalTokens} tokens]\n${tail}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Cap a tool result at admission time. Under-cap text passes through untouched; over-cap
|
|
33
|
+
* text becomes a deterministic, diskless head/tail projection. Re-evaluating projected
|
|
34
|
+
* text under a smaller model window is safe because admission never trusts marker text.
|
|
35
|
+
*/
|
|
36
|
+
export function admitToolResultWithinBudget(text, budgetTokens) {
|
|
37
|
+
const totalTokens = estimateTextTokens(text);
|
|
38
|
+
if (totalTokens <= budgetTokens)
|
|
39
|
+
return { text, projected: false };
|
|
40
|
+
if (budgetTokens <= 0)
|
|
41
|
+
return { text: "", projected: true };
|
|
42
|
+
const charsPerToken = text.length / Math.max(1, totalTokens);
|
|
43
|
+
let budgetChars = Math.floor(budgetTokens * charsPerToken);
|
|
44
|
+
let excerpt = buildExcerpt(text, budgetChars, totalTokens);
|
|
45
|
+
while (estimateTextTokens(excerpt) > budgetTokens && budgetChars > 0) {
|
|
46
|
+
budgetChars = Math.floor(budgetChars * 0.8);
|
|
47
|
+
excerpt = buildExcerpt(text, budgetChars, totalTokens);
|
|
48
|
+
}
|
|
49
|
+
return estimateTextTokens(excerpt) <= budgetTokens
|
|
50
|
+
? { text: excerpt, projected: true }
|
|
51
|
+
: { text: "", projected: true };
|
|
52
|
+
}
|
|
53
|
+
export function admitToolResult(input) {
|
|
54
|
+
return admitToolResultWithinBudget(input.text, resolveToolResultAdmissionCapTokens(input.contextWindow));
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=tool-admission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-admission.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/tool-admission.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Always-on admission cap for tool results.\n *\n * Oversized tool output is the dominant driver of single-step context bursts, so it is\n * projected to a deterministic head/tail excerpt at the entrance instead of waiting for\n * an emergency/compaction-budget pass (see `tool-truncation.ts`). Admission is derived\n * from the supplied text on every request; model-visible marker text is never state.\n */\n\nimport { estimateTokens } from \"../../../compaction/index.ts\";\n\nconst MAX_ADMISSION_CAP_TOKENS = 50_000;\nconst MIN_ADMISSION_CAP_TOKENS = 8192;\nconst ADMISSION_CAP_FRACTION = 0.05;\nconst HEAD_BUDGET_FRACTION = 0.6;\nconst TAIL_BUDGET_FRACTION = 0.2;\n\nexport const TOOL_ADMISSION_MARKER_PREFIX = \"[tool result projected:\";\n\nexport interface AdmitToolResultInput {\n\treadonly text: string;\n\treadonly contextWindow: number;\n}\n\nexport interface AdmitToolResultOutput {\n\treadonly text: string;\n\treadonly projected: boolean;\n}\n\n/** Token budget a single tool result may occupy before it is projected. */\nexport function resolveToolResultAdmissionCapTokens(contextWindow: number): number {\n\treturn Math.min(\n\t\tMAX_ADMISSION_CAP_TOKENS,\n\t\tMath.max(MIN_ADMISSION_CAP_TOKENS, Math.floor(ADMISSION_CAP_FRACTION * contextWindow)),\n\t);\n}\n\nfunction estimateTextTokens(text: string): number {\n\treturn estimateTokens({ role: \"user\", content: text, timestamp: 0 });\n}\n\nfunction buildExcerpt(text: string, budgetChars: number, totalTokens: number): string {\n\tconst headChars = Math.floor(budgetChars * HEAD_BUDGET_FRACTION);\n\tconst tailChars = Math.floor(budgetChars * TAIL_BUDGET_FRACTION);\n\tconst head = text.slice(0, headChars);\n\tconst tail = text.slice(Math.max(headChars, text.length - tailChars));\n\tconst keptTokens = estimateTextTokens(head) + estimateTextTokens(tail);\n\treturn `${head}\\n${TOOL_ADMISSION_MARKER_PREFIX} kept ${keptTokens} of ~${totalTokens} tokens]\\n${tail}`;\n}\n\n/**\n * Cap a tool result at admission time. Under-cap text passes through untouched; over-cap\n * text becomes a deterministic, diskless head/tail projection. Re-evaluating projected\n * text under a smaller model window is safe because admission never trusts marker text.\n */\nexport function admitToolResultWithinBudget(text: string, budgetTokens: number): AdmitToolResultOutput {\n\tconst totalTokens = estimateTextTokens(text);\n\tif (totalTokens <= budgetTokens) return { text, projected: false };\n\tif (budgetTokens <= 0) return { text: \"\", projected: true };\n\n\tconst charsPerToken = text.length / Math.max(1, totalTokens);\n\tlet budgetChars = Math.floor(budgetTokens * charsPerToken);\n\tlet excerpt = buildExcerpt(text, budgetChars, totalTokens);\n\twhile (estimateTextTokens(excerpt) > budgetTokens && budgetChars > 0) {\n\t\tbudgetChars = Math.floor(budgetChars * 0.8);\n\t\texcerpt = buildExcerpt(text, budgetChars, totalTokens);\n\t}\n\n\treturn estimateTextTokens(excerpt) <= budgetTokens\n\t\t? { text: excerpt, projected: true }\n\t\t: { text: \"\", projected: true };\n}\n\nexport function admitToolResult(input: AdmitToolResultInput): AdmitToolResultOutput {\n\treturn admitToolResultWithinBudget(input.text, resolveToolResultAdmissionCapTokens(input.contextWindow));\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { HookTrustState } from "./types.ts";
|
|
2
|
+
export declare function emptyHookTrustState(): HookTrustState;
|
|
3
|
+
export declare function parseHookTrustStateJson(input: string | undefined): HookTrustState | undefined;
|
|
4
|
+
export declare function readHookTrustStateJson(input: string | undefined): HookTrustState;
|
|
5
|
+
//# sourceMappingURL=trust-state-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust-state-json.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-state-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,YAAY,CAAC;AAIlF,wBAAgB,mBAAmB,IAAI,cAAc,CAEpD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CAY7F;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAEhF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const HOOK_STATE_VERSION = 1;
|
|
2
|
+
export function emptyHookTrustState() {
|
|
3
|
+
return { version: HOOK_STATE_VERSION, hooks: {} };
|
|
4
|
+
}
|
|
5
|
+
export function parseHookTrustStateJson(input) {
|
|
6
|
+
if (input === undefined || input.trim() === "") {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
return parseHookTrustState(JSON.parse(input));
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
if (error instanceof SyntaxError) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function readHookTrustStateJson(input) {
|
|
20
|
+
return parseHookTrustStateJson(input) ?? emptyHookTrustState();
|
|
21
|
+
}
|
|
22
|
+
function parseHookTrustState(input) {
|
|
23
|
+
if (!isRecord(input) || input.version !== HOOK_STATE_VERSION || !isRecord(input.hooks)) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const hooks = {};
|
|
27
|
+
for (const [id, entry] of Object.entries(input.hooks)) {
|
|
28
|
+
const parsed = parseHookTrustEntry(entry);
|
|
29
|
+
if (parsed !== undefined) {
|
|
30
|
+
hooks[id] = parsed;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { version: HOOK_STATE_VERSION, hooks };
|
|
34
|
+
}
|
|
35
|
+
function parseHookTrustEntry(input) {
|
|
36
|
+
if (!isRecord(input)) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
const enabled = input.enabled;
|
|
40
|
+
const trustedHash = input.trustedHash;
|
|
41
|
+
const scope = input.scope;
|
|
42
|
+
const sourcePath = input.sourcePath;
|
|
43
|
+
const matcher = input.matcher;
|
|
44
|
+
const commandPreview = input.commandPreview;
|
|
45
|
+
const updatedAt = input.updatedAt;
|
|
46
|
+
if (typeof enabled !== "boolean" ||
|
|
47
|
+
(trustedHash !== undefined && typeof trustedHash !== "string") ||
|
|
48
|
+
!isHookSourceScope(scope) ||
|
|
49
|
+
typeof sourcePath !== "string" ||
|
|
50
|
+
(matcher !== undefined && typeof matcher !== "string") ||
|
|
51
|
+
typeof commandPreview !== "string" ||
|
|
52
|
+
typeof updatedAt !== "string") {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
enabled,
|
|
57
|
+
...(trustedHash === undefined ? {} : { trustedHash }),
|
|
58
|
+
scope,
|
|
59
|
+
sourcePath,
|
|
60
|
+
...(matcher === undefined ? {} : { matcher }),
|
|
61
|
+
commandPreview,
|
|
62
|
+
updatedAt,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function isRecord(value) {
|
|
66
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
67
|
+
}
|
|
68
|
+
function isHookSourceScope(value) {
|
|
69
|
+
return (value === "global" ||
|
|
70
|
+
value === "project" ||
|
|
71
|
+
value === "plugin" ||
|
|
72
|
+
value === "runtime" ||
|
|
73
|
+
value === "cli" ||
|
|
74
|
+
value === "managed");
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=trust-state-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust-state-json.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-state-json.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HookSourceScope, HookTrustEntry, HookTrustState } from \"./types.ts\";\n\nconst HOOK_STATE_VERSION = 1;\n\nexport function emptyHookTrustState(): HookTrustState {\n\treturn { version: HOOK_STATE_VERSION, hooks: {} };\n}\n\nexport function parseHookTrustStateJson(input: string | undefined): HookTrustState | undefined {\n\tif (input === undefined || input.trim() === \"\") {\n\t\treturn undefined;\n\t}\n\ttry {\n\t\treturn parseHookTrustState(JSON.parse(input));\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\treturn undefined;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nexport function readHookTrustStateJson(input: string | undefined): HookTrustState {\n\treturn parseHookTrustStateJson(input) ?? emptyHookTrustState();\n}\n\nfunction parseHookTrustState(input: unknown): HookTrustState | undefined {\n\tif (!isRecord(input) || input.version !== HOOK_STATE_VERSION || !isRecord(input.hooks)) {\n\t\treturn undefined;\n\t}\n\n\tconst hooks: Record<string, HookTrustEntry> = {};\n\tfor (const [id, entry] of Object.entries(input.hooks)) {\n\t\tconst parsed = parseHookTrustEntry(entry);\n\t\tif (parsed !== undefined) {\n\t\t\thooks[id] = parsed;\n\t\t}\n\t}\n\treturn { version: HOOK_STATE_VERSION, hooks };\n}\n\nfunction parseHookTrustEntry(input: unknown): HookTrustEntry | undefined {\n\tif (!isRecord(input)) {\n\t\treturn undefined;\n\t}\n\tconst enabled = input.enabled;\n\tconst trustedHash = input.trustedHash;\n\tconst scope = input.scope;\n\tconst sourcePath = input.sourcePath;\n\tconst matcher = input.matcher;\n\tconst commandPreview = input.commandPreview;\n\tconst updatedAt = input.updatedAt;\n\tif (\n\t\ttypeof enabled !== \"boolean\" ||\n\t\t(trustedHash !== undefined && typeof trustedHash !== \"string\") ||\n\t\t!isHookSourceScope(scope) ||\n\t\ttypeof sourcePath !== \"string\" ||\n\t\t(matcher !== undefined && typeof matcher !== \"string\") ||\n\t\ttypeof commandPreview !== \"string\" ||\n\t\ttypeof updatedAt !== \"string\"\n\t) {\n\t\treturn undefined;\n\t}\n\treturn {\n\t\tenabled,\n\t\t...(trustedHash === undefined ? {} : { trustedHash }),\n\t\tscope,\n\t\tsourcePath,\n\t\t...(matcher === undefined ? {} : { matcher }),\n\t\tcommandPreview,\n\t\tupdatedAt,\n\t};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isHookSourceScope(value: unknown): value is HookSourceScope {\n\treturn (\n\t\tvalue === \"global\" ||\n\t\tvalue === \"project\" ||\n\t\tvalue === \"plugin\" ||\n\t\tvalue === \"runtime\" ||\n\t\tvalue === \"cli\" ||\n\t\tvalue === \"managed\"\n\t);\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { HookTrustStorageScope } from "./trust.ts";
|
|
2
2
|
import type { HookTrustState } from "./types.ts";
|
|
3
3
|
export interface HookStateStorage {
|
|
4
4
|
read(scope: HookTrustStorageScope): HookTrustState;
|
|
@@ -8,6 +8,12 @@ export type FileHookStateStorageOptions = {
|
|
|
8
8
|
readonly agentDir?: string;
|
|
9
9
|
readonly cwd: string;
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Internal same-account application state at `<agentDir>/hooks-state.json` and
|
|
13
|
+
* `<cwd>/.senpi/hooks-state.json`. POSIX files retain their numeric mode and new
|
|
14
|
+
* files use 0600; reassigned ownership, named ACLs, and custom DACLs are outside
|
|
15
|
+
* this storage contract.
|
|
16
|
+
*/
|
|
11
17
|
export declare class FileHookStateStorage implements HookStateStorage {
|
|
12
18
|
private readonly globalStatePath;
|
|
13
19
|
private readonly projectStatePath;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trust-storage.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"trust-storage.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-storage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc,CAAC;IACnD,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc,CAAC;CAC3G;AAED,MAAM,MAAM,2BAA2B,GAAG;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAE9B,OAAO,EAAE,2BAA2B;IAMhD,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc;IAqBlD,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc;CAyB1G;AAED,qBAAa,wBAAyB,YAAW,gBAAgB;IAChE,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,YAAY,CAAyC;IAE7D,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc;IAIlD,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc;CAS1G"}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
3
|
import { dirname, join } from "node:path";
|
|
3
4
|
import lockfile from "proper-lockfile";
|
|
4
5
|
import { CONFIG_DIR_NAME, getAgentDir } from "../../../../config.js";
|
|
5
|
-
import { emptyHookTrustState, readHookTrustStateJson } from "./trust.js";
|
|
6
|
+
import { emptyHookTrustState, parseHookTrustStateJson, readHookTrustStateJson } from "./trust-state-json.js";
|
|
7
|
+
/**
|
|
8
|
+
* Internal same-account application state at `<agentDir>/hooks-state.json` and
|
|
9
|
+
* `<cwd>/.senpi/hooks-state.json`. POSIX files retain their numeric mode and new
|
|
10
|
+
* files use 0600; reassigned ownership, named ACLs, and custom DACLs are outside
|
|
11
|
+
* this storage contract.
|
|
12
|
+
*/
|
|
6
13
|
export class FileHookStateStorage {
|
|
7
14
|
constructor(options) {
|
|
8
15
|
const agentDir = options.agentDir ?? getAgentDir();
|
|
@@ -10,13 +17,44 @@ export class FileHookStateStorage {
|
|
|
10
17
|
this.projectStatePath = join(options.cwd, CONFIG_DIR_NAME, "hooks-state.json");
|
|
11
18
|
}
|
|
12
19
|
read(scope) {
|
|
13
|
-
|
|
20
|
+
const path = statePathForScope(scope, this.globalStatePath, this.projectStatePath);
|
|
21
|
+
const snapshot = parseHookTrustStateJson(existsSync(path) ? readFileSync(path, "utf-8") : undefined);
|
|
22
|
+
if (snapshot !== undefined) {
|
|
23
|
+
return snapshot;
|
|
24
|
+
}
|
|
25
|
+
let release;
|
|
26
|
+
try {
|
|
27
|
+
release = acquireHookStateLockSync(path);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (errorCode(error) === "ELOCKED") {
|
|
31
|
+
return emptyHookTrustState();
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
return runWithHookStateLockRelease(release, () => readHookTrustStateJson(existsSync(path) ? readFileSync(path, "utf-8") : undefined));
|
|
14
36
|
}
|
|
15
37
|
update(scope, updater) {
|
|
16
38
|
return withHookStateFileLock(statePathForScope(scope, this.globalStatePath, this.projectStatePath), (path) => {
|
|
17
|
-
const
|
|
39
|
+
const stateExists = existsSync(path);
|
|
40
|
+
const current = readHookTrustStateJson(stateExists ? readFileSync(path, "utf-8") : undefined);
|
|
41
|
+
const mode = stateExists ? statSync(path).mode & 0o777 : 0o600;
|
|
18
42
|
const next = updater(current);
|
|
19
|
-
|
|
43
|
+
const tempPath = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
44
|
+
try {
|
|
45
|
+
writeFileSync(tempPath, serializeHookTrustState(next), { encoding: "utf-8", mode });
|
|
46
|
+
chmodSync(tempPath, mode);
|
|
47
|
+
renameSync(tempPath, path);
|
|
48
|
+
}
|
|
49
|
+
catch (publicationError) {
|
|
50
|
+
try {
|
|
51
|
+
rmSync(tempPath, { force: true });
|
|
52
|
+
}
|
|
53
|
+
catch (cleanupError) {
|
|
54
|
+
throw new AggregateError([publicationError, cleanupError], "Failed to publish and clean up hook trust state snapshot");
|
|
55
|
+
}
|
|
56
|
+
throw publicationError;
|
|
57
|
+
}
|
|
20
58
|
return next;
|
|
21
59
|
});
|
|
22
60
|
}
|
|
@@ -92,11 +130,25 @@ function isRecord(value) {
|
|
|
92
130
|
}
|
|
93
131
|
function withHookStateFileLock(path, fn) {
|
|
94
132
|
const release = acquireHookStateLockSync(path);
|
|
133
|
+
return runWithHookStateLockRelease(release, () => fn(path));
|
|
134
|
+
}
|
|
135
|
+
function runWithHookStateLockRelease(release, operation) {
|
|
136
|
+
let result;
|
|
95
137
|
try {
|
|
96
|
-
|
|
138
|
+
result = operation();
|
|
97
139
|
}
|
|
98
|
-
|
|
99
|
-
|
|
140
|
+
catch (operationError) {
|
|
141
|
+
try {
|
|
142
|
+
release();
|
|
143
|
+
}
|
|
144
|
+
catch (releaseError) {
|
|
145
|
+
throw new AggregateError(operationError instanceof AggregateError
|
|
146
|
+
? [...operationError.errors, releaseError]
|
|
147
|
+
: [operationError, releaseError], "Hook state operation and lock release both failed");
|
|
148
|
+
}
|
|
149
|
+
throw operationError;
|
|
100
150
|
}
|
|
151
|
+
release();
|
|
152
|
+
return result;
|
|
101
153
|
}
|
|
102
154
|
//# sourceMappingURL=trust-storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trust-storage.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../../../../config.ts\";\nimport { emptyHookTrustState, type HookTrustStorageScope, readHookTrustStateJson } from \"./trust.ts\";\nimport type { HookTrustEntry, HookTrustState } from \"./types.ts\";\n\nexport interface HookStateStorage {\n\tread(scope: HookTrustStorageScope): HookTrustState;\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState;\n}\n\nexport type FileHookStateStorageOptions = {\n\treadonly agentDir?: string;\n\treadonly cwd: string;\n};\n\nexport class FileHookStateStorage implements HookStateStorage {\n\tprivate readonly globalStatePath: string;\n\tprivate readonly projectStatePath: string;\n\n\tconstructor(options: FileHookStateStorageOptions) {\n\t\tconst agentDir = options.agentDir ?? getAgentDir();\n\t\tthis.globalStatePath = join(agentDir, \"hooks-state.json\");\n\t\tthis.projectStatePath = join(options.cwd, CONFIG_DIR_NAME, \"hooks-state.json\");\n\t}\n\n\tread(scope: HookTrustStorageScope): HookTrustState {\n\t\treturn withHookStateFileLock(statePathForScope(scope, this.globalStatePath, this.projectStatePath), (path) =>\n\t\t\treadHookTrustStateJson(existsSync(path) ? readFileSync(path, \"utf-8\") : undefined),\n\t\t);\n\t}\n\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState {\n\t\treturn withHookStateFileLock(statePathForScope(scope, this.globalStatePath, this.projectStatePath), (path) => {\n\t\t\tconst current = readHookTrustStateJson(existsSync(path) ? readFileSync(path, \"utf-8\") : undefined);\n\t\t\tconst next = updater(current);\n\t\t\twriteFileSync(path, serializeHookTrustState(next), \"utf-8\");\n\t\t\treturn next;\n\t\t});\n\t}\n}\n\nexport class InMemoryHookStateStorage implements HookStateStorage {\n\tprivate globalState: HookTrustState = emptyHookTrustState();\n\tprivate projectState: HookTrustState = emptyHookTrustState();\n\n\tread(scope: HookTrustStorageScope): HookTrustState {\n\t\treturn scope === \"global\" ? this.globalState : this.projectState;\n\t}\n\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState {\n\t\tconst next = updater(this.read(scope));\n\t\tif (scope === \"global\") {\n\t\t\tthis.globalState = next;\n\t\t} else {\n\t\t\tthis.projectState = next;\n\t\t}\n\t\treturn next;\n\t}\n}\n\nfunction statePathForScope(scope: HookTrustStorageScope, globalStatePath: string, projectStatePath: string): string {\n\treturn scope === \"global\" ? globalStatePath : projectStatePath;\n}\n\nfunction serializeHookTrustState(state: HookTrustState): string {\n\tconst sortedHooks: Record<string, HookTrustEntry> = {};\n\tfor (const key of Object.keys(state.hooks).sort()) {\n\t\tconst entry = state.hooks[key];\n\t\tif (entry !== undefined) {\n\t\t\tsortedHooks[key] = entry;\n\t\t}\n\t}\n\treturn `${JSON.stringify({ version: 1, hooks: sortedHooks }, null, 2)}\\n`;\n}\n\nfunction acquireHookStateLockSync(path: string): () => void {\n\tconst stateDir = dirname(path);\n\tmkdirSync(stateDir, { recursive: true });\n\tconst maxAttempts = 10;\n\tconst delayMs = 20;\n\tlet lastError: unknown;\n\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(stateDir, { realpath: false, lockfilePath: `${path}.lock` });\n\t\t} catch (error) {\n\t\t\tconst code = errorCode(error);\n\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlastError = error;\n\t\t\tconst start = Date.now();\n\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\tDate.now();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (lastError instanceof Error) {\n\t\tthrow lastError;\n\t}\n\tthrow new Error(\"Failed to acquire hook state lock\");\n}\n\nfunction errorCode(error: unknown): string | undefined {\n\tif (!isRecord(error)) {\n\t\treturn undefined;\n\t}\n\tconst code = error.code;\n\treturn typeof code === \"string\" ? code : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withHookStateFileLock<T>(path: string, fn: (path: string) => T): T {\n\tconst release = acquireHookStateLockSync(path);\n\ttry {\n\t\treturn fn(path);\n\t} finally {\n\t\trelease();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"trust-storage.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../../../../config.ts\";\nimport type { HookTrustStorageScope } from \"./trust.ts\";\nimport { emptyHookTrustState, parseHookTrustStateJson, readHookTrustStateJson } from \"./trust-state-json.ts\";\nimport type { HookTrustEntry, HookTrustState } from \"./types.ts\";\n\nexport interface HookStateStorage {\n\tread(scope: HookTrustStorageScope): HookTrustState;\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState;\n}\n\nexport type FileHookStateStorageOptions = {\n\treadonly agentDir?: string;\n\treadonly cwd: string;\n};\n\n/**\n * Internal same-account application state at `<agentDir>/hooks-state.json` and\n * `<cwd>/.senpi/hooks-state.json`. POSIX files retain their numeric mode and new\n * files use 0600; reassigned ownership, named ACLs, and custom DACLs are outside\n * this storage contract.\n */\nexport class FileHookStateStorage implements HookStateStorage {\n\tprivate readonly globalStatePath: string;\n\tprivate readonly projectStatePath: string;\n\n\tconstructor(options: FileHookStateStorageOptions) {\n\t\tconst agentDir = options.agentDir ?? getAgentDir();\n\t\tthis.globalStatePath = join(agentDir, \"hooks-state.json\");\n\t\tthis.projectStatePath = join(options.cwd, CONFIG_DIR_NAME, \"hooks-state.json\");\n\t}\n\n\tread(scope: HookTrustStorageScope): HookTrustState {\n\t\tconst path = statePathForScope(scope, this.globalStatePath, this.projectStatePath);\n\t\tconst snapshot = parseHookTrustStateJson(existsSync(path) ? readFileSync(path, \"utf-8\") : undefined);\n\t\tif (snapshot !== undefined) {\n\t\t\treturn snapshot;\n\t\t}\n\n\t\tlet release: () => void;\n\t\ttry {\n\t\t\trelease = acquireHookStateLockSync(path);\n\t\t} catch (error) {\n\t\t\tif (errorCode(error) === \"ELOCKED\") {\n\t\t\t\treturn emptyHookTrustState();\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\treturn runWithHookStateLockRelease(release, () =>\n\t\t\treadHookTrustStateJson(existsSync(path) ? readFileSync(path, \"utf-8\") : undefined),\n\t\t);\n\t}\n\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState {\n\t\treturn withHookStateFileLock(statePathForScope(scope, this.globalStatePath, this.projectStatePath), (path) => {\n\t\t\tconst stateExists = existsSync(path);\n\t\t\tconst current = readHookTrustStateJson(stateExists ? readFileSync(path, \"utf-8\") : undefined);\n\t\t\tconst mode = stateExists ? statSync(path).mode & 0o777 : 0o600;\n\t\t\tconst next = updater(current);\n\t\t\tconst tempPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n\t\t\ttry {\n\t\t\t\twriteFileSync(tempPath, serializeHookTrustState(next), { encoding: \"utf-8\", mode });\n\t\t\t\tchmodSync(tempPath, mode);\n\t\t\t\trenameSync(tempPath, path);\n\t\t\t} catch (publicationError) {\n\t\t\t\ttry {\n\t\t\t\t\trmSync(tempPath, { force: true });\n\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\tthrow new AggregateError(\n\t\t\t\t\t\t[publicationError, cleanupError],\n\t\t\t\t\t\t\"Failed to publish and clean up hook trust state snapshot\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow publicationError;\n\t\t\t}\n\t\t\treturn next;\n\t\t});\n\t}\n}\n\nexport class InMemoryHookStateStorage implements HookStateStorage {\n\tprivate globalState: HookTrustState = emptyHookTrustState();\n\tprivate projectState: HookTrustState = emptyHookTrustState();\n\n\tread(scope: HookTrustStorageScope): HookTrustState {\n\t\treturn scope === \"global\" ? this.globalState : this.projectState;\n\t}\n\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState {\n\t\tconst next = updater(this.read(scope));\n\t\tif (scope === \"global\") {\n\t\t\tthis.globalState = next;\n\t\t} else {\n\t\t\tthis.projectState = next;\n\t\t}\n\t\treturn next;\n\t}\n}\n\nfunction statePathForScope(scope: HookTrustStorageScope, globalStatePath: string, projectStatePath: string): string {\n\treturn scope === \"global\" ? globalStatePath : projectStatePath;\n}\n\nfunction serializeHookTrustState(state: HookTrustState): string {\n\tconst sortedHooks: Record<string, HookTrustEntry> = {};\n\tfor (const key of Object.keys(state.hooks).sort()) {\n\t\tconst entry = state.hooks[key];\n\t\tif (entry !== undefined) {\n\t\t\tsortedHooks[key] = entry;\n\t\t}\n\t}\n\treturn `${JSON.stringify({ version: 1, hooks: sortedHooks }, null, 2)}\\n`;\n}\n\nfunction acquireHookStateLockSync(path: string): () => void {\n\tconst stateDir = dirname(path);\n\tmkdirSync(stateDir, { recursive: true });\n\tconst maxAttempts = 10;\n\tconst delayMs = 20;\n\tlet lastError: unknown;\n\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(stateDir, { realpath: false, lockfilePath: `${path}.lock` });\n\t\t} catch (error) {\n\t\t\tconst code = errorCode(error);\n\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlastError = error;\n\t\t\tconst start = Date.now();\n\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\tDate.now();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (lastError instanceof Error) {\n\t\tthrow lastError;\n\t}\n\tthrow new Error(\"Failed to acquire hook state lock\");\n}\n\nfunction errorCode(error: unknown): string | undefined {\n\tif (!isRecord(error)) {\n\t\treturn undefined;\n\t}\n\tconst code = error.code;\n\treturn typeof code === \"string\" ? code : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withHookStateFileLock<T>(path: string, fn: (path: string) => T): T {\n\tconst release = acquireHookStateLockSync(path);\n\treturn runWithHookStateLockRelease(release, () => fn(path));\n}\n\nfunction runWithHookStateLockRelease<T>(release: () => void, operation: () => T): T {\n\tlet result: T;\n\ttry {\n\t\tresult = operation();\n\t} catch (operationError) {\n\t\ttry {\n\t\t\trelease();\n\t\t} catch (releaseError) {\n\t\t\tthrow new AggregateError(\n\t\t\t\toperationError instanceof AggregateError\n\t\t\t\t\t? [...operationError.errors, releaseError]\n\t\t\t\t\t: [operationError, releaseError],\n\t\t\t\t\"Hook state operation and lock release both failed\",\n\t\t\t);\n\t\t}\n\t\tthrow operationError;\n\t}\n\trelease();\n\treturn result;\n}\n"]}
|
|
@@ -19,7 +19,7 @@ export type HookTrustRecord = {
|
|
|
19
19
|
readonly commandPreview: string;
|
|
20
20
|
readonly entry?: HookTrustEntry;
|
|
21
21
|
};
|
|
22
|
-
export
|
|
22
|
+
export { emptyHookTrustState, readHookTrustStateJson } from "./trust-state-json.ts";
|
|
23
23
|
export declare function hookTrustId(handler: ExecutableHookHandler): string;
|
|
24
24
|
export declare function buildHookTrustRecord(handler: ExecutableHookHandler, options?: HookTrustOptions): HookTrustRecord;
|
|
25
25
|
export declare function createHookTrustEntry(handler: ExecutableHookHandler, options?: HookTrustOptions & {
|
|
@@ -29,6 +29,5 @@ export declare function hashCommandHook(handler: ExecutableHookHandler, options?
|
|
|
29
29
|
export declare function isCommandHookTrusted(handler: ExecutableHookHandler, state: HookTrustState, options?: HookTrustOptions): boolean;
|
|
30
30
|
export declare function listHookTrustRecords(handlers: readonly ExecutableHookHandler[], state: HookTrustState, options?: HookTrustOptions): readonly HookTrustRecord[];
|
|
31
31
|
export declare function filterExecutableTrustedHooks(handlers: readonly ExecutableHookHandler[], state: HookTrustState, options?: HookTrustOptions): readonly ExecutableHookHandler[];
|
|
32
|
-
export declare function readHookTrustStateJson(input: string | undefined): HookTrustState;
|
|
33
32
|
export declare function hookTrustStorageScope(handler: ExecutableHookHandler, options: HookTrustStorageOptions): HookTrustStorageScope | undefined;
|
|
34
33
|
//# sourceMappingURL=trust.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,qBAAqB,EAErB,eAAe,EACf,cAAc,EACd,cAAc,EACd,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC;AAChD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;CAChC,CAAC;
|
|
1
|
+
{"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,qBAAqB,EAErB,eAAe,EACf,cAAc,EACd,cAAc,EACd,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC;AAChD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;CAChC,CAAC;AAUF,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpF,wBAAgB,WAAW,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAElE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAepH;AAED,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,GAAE,gBAAgB,GAAG;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9D,cAAc,CAWhB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,qBAAqB,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAkBtG;AAED,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAGT;AAED,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,SAAS,qBAAqB,EAAE,EAC1C,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,gBAAqB,GAC5B,SAAS,eAAe,EAAE,CAE5B;AAED,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,SAAS,qBAAqB,EAAE,EAC1C,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,gBAAqB,GAC5B,SAAS,qBAAqB,EAAE,CAElC;AAED,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,uBAAuB,GAC9B,qBAAqB,GAAG,SAAS,CAKnC"}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { DEFAULT_HOOK_TIMEOUT_SECONDS, isValidHookTimeoutSeconds } from "./safety.js";
|
|
3
|
-
|
|
4
|
-
export function emptyHookTrustState() {
|
|
5
|
-
return { version: HOOK_STATE_VERSION, hooks: {} };
|
|
6
|
-
}
|
|
3
|
+
export { emptyHookTrustState, readHookTrustStateJson } from "./trust-state-json.js";
|
|
7
4
|
export function hookTrustId(handler) {
|
|
8
5
|
return `hk_${sourceKeyHash(handler.source)}_${handler.event}_${handler.groupIndex}_${handler.handlerIndex}`;
|
|
9
6
|
}
|
|
@@ -64,20 +61,6 @@ export function listHookTrustRecords(handlers, state, options = {}) {
|
|
|
64
61
|
export function filterExecutableTrustedHooks(handlers, state, options = {}) {
|
|
65
62
|
return handlers.filter((handler) => buildStatefulHookTrustRecord(handler, state, options).executable);
|
|
66
63
|
}
|
|
67
|
-
export function readHookTrustStateJson(input) {
|
|
68
|
-
if (input === undefined || input.trim() === "") {
|
|
69
|
-
return emptyHookTrustState();
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
return parseHookTrustState(JSON.parse(input));
|
|
73
|
-
}
|
|
74
|
-
catch (error) {
|
|
75
|
-
if (error instanceof Error) {
|
|
76
|
-
return emptyHookTrustState();
|
|
77
|
-
}
|
|
78
|
-
return emptyHookTrustState();
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
64
|
export function hookTrustStorageScope(handler, options) {
|
|
82
65
|
if (handler.source.scope === "project") {
|
|
83
66
|
return options.projectTrusted ? "project" : undefined;
|
|
@@ -97,49 +80,6 @@ function buildStatefulHookTrustRecord(handler, state, options) {
|
|
|
97
80
|
...(entry === undefined ? {} : { entry }),
|
|
98
81
|
};
|
|
99
82
|
}
|
|
100
|
-
function parseHookTrustState(input) {
|
|
101
|
-
if (!isRecord(input) || input.version !== HOOK_STATE_VERSION || !isRecord(input.hooks)) {
|
|
102
|
-
return emptyHookTrustState();
|
|
103
|
-
}
|
|
104
|
-
const hooks = {};
|
|
105
|
-
for (const [id, entry] of Object.entries(input.hooks)) {
|
|
106
|
-
const parsed = parseHookTrustEntry(entry);
|
|
107
|
-
if (parsed !== undefined) {
|
|
108
|
-
hooks[id] = parsed;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return { version: HOOK_STATE_VERSION, hooks };
|
|
112
|
-
}
|
|
113
|
-
function parseHookTrustEntry(input) {
|
|
114
|
-
if (!isRecord(input)) {
|
|
115
|
-
return undefined;
|
|
116
|
-
}
|
|
117
|
-
const enabled = input.enabled;
|
|
118
|
-
const trustedHash = input.trustedHash;
|
|
119
|
-
const scope = input.scope;
|
|
120
|
-
const sourcePath = input.sourcePath;
|
|
121
|
-
const matcher = input.matcher;
|
|
122
|
-
const commandPreview = input.commandPreview;
|
|
123
|
-
const updatedAt = input.updatedAt;
|
|
124
|
-
if (typeof enabled !== "boolean" ||
|
|
125
|
-
(trustedHash !== undefined && typeof trustedHash !== "string") ||
|
|
126
|
-
!isHookSourceScope(scope) ||
|
|
127
|
-
typeof sourcePath !== "string" ||
|
|
128
|
-
(matcher !== undefined && typeof matcher !== "string") ||
|
|
129
|
-
typeof commandPreview !== "string" ||
|
|
130
|
-
typeof updatedAt !== "string") {
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
enabled,
|
|
135
|
-
...(trustedHash === undefined ? {} : { trustedHash }),
|
|
136
|
-
scope,
|
|
137
|
-
sourcePath,
|
|
138
|
-
...(matcher === undefined ? {} : { matcher }),
|
|
139
|
-
commandPreview,
|
|
140
|
-
updatedAt,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
83
|
function selectedCommand(handler, platform) {
|
|
144
84
|
if (platform === "win32" && handler.config.commandWindows !== undefined) {
|
|
145
85
|
return handler.config.commandWindows;
|
|
@@ -177,18 +117,7 @@ function canonicalJson(value) {
|
|
|
177
117
|
}
|
|
178
118
|
return result;
|
|
179
119
|
}
|
|
180
|
-
function isRecord(value) {
|
|
181
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
182
|
-
}
|
|
183
120
|
function isJsonRecord(value) {
|
|
184
121
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
185
122
|
}
|
|
186
|
-
function isHookSourceScope(value) {
|
|
187
|
-
return (value === "global" ||
|
|
188
|
-
value === "project" ||
|
|
189
|
-
value === "plugin" ||
|
|
190
|
-
value === "runtime" ||
|
|
191
|
-
value === "cli" ||
|
|
192
|
-
value === "managed");
|
|
193
|
-
}
|
|
194
123
|
//# sourceMappingURL=trust.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trust.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { DEFAULT_HOOK_TIMEOUT_SECONDS, isValidHookTimeoutSeconds } from \"./safety.ts\";\nimport type {\n\tExecutableHookHandler,\n\tHookSourceMetadata,\n\tHookSourceScope,\n\tHookTrustEntry,\n\tHookTrustState,\n} from \"./types.ts\";\n\nexport type HookTrustPlatform = NodeJS.Platform;\nexport type HookTrustStorageScope = \"global\" | \"project\";\n\nexport type HookTrustOptions = {\n\treadonly platform?: HookTrustPlatform;\n};\n\nexport type HookTrustStorageOptions = {\n\treadonly projectTrusted: boolean;\n};\n\nexport type HookTrustRecord = {\n\treadonly id: string;\n\treadonly currentHash: string;\n\treadonly enabled: boolean;\n\treadonly trusted: boolean;\n\treadonly executable: boolean;\n\treadonly scope: HookSourceScope;\n\treadonly sourcePath: string;\n\treadonly matcher?: string;\n\treadonly commandPreview: string;\n\treadonly entry?: HookTrustEntry;\n};\n\ntype JsonValue =\n\t| null\n\t| boolean\n\t| number\n\t| string\n\t| readonly JsonValue[]\n\t| { readonly [key: string]: JsonValue | undefined };\n\nconst HOOK_STATE_VERSION = 1;\n\nexport function emptyHookTrustState(): HookTrustState {\n\treturn { version: HOOK_STATE_VERSION, hooks: {} };\n}\n\nexport function hookTrustId(handler: ExecutableHookHandler): string {\n\treturn `hk_${sourceKeyHash(handler.source)}_${handler.event}_${handler.groupIndex}_${handler.handlerIndex}`;\n}\n\nexport function buildHookTrustRecord(handler: ExecutableHookHandler, options: HookTrustOptions = {}): HookTrustRecord {\n\tconst id = hookTrustId(handler);\n\tconst currentHash = hashCommandHook(handler, options);\n\tconst commandPreview = selectedCommand(handler, options.platform ?? process.platform);\n\treturn {\n\t\tid,\n\t\tcurrentHash,\n\t\tenabled: true,\n\t\ttrusted: false,\n\t\texecutable: false,\n\t\tscope: handler.source.scope,\n\t\tsourcePath: handler.source.sourcePath,\n\t\t...(handler.matcher === undefined ? {} : { matcher: handler.matcher }),\n\t\tcommandPreview,\n\t};\n}\n\nexport function createHookTrustEntry(\n\thandler: ExecutableHookHandler,\n\toptions: HookTrustOptions & { readonly updatedAt?: string } = {},\n): HookTrustEntry {\n\tconst commandPreview = selectedCommand(handler, options.platform ?? process.platform);\n\treturn {\n\t\tenabled: true,\n\t\ttrustedHash: hashCommandHook(handler, options),\n\t\tscope: handler.source.scope,\n\t\tsourcePath: handler.source.sourcePath,\n\t\t...(handler.matcher === undefined ? {} : { matcher: handler.matcher }),\n\t\tcommandPreview,\n\t\tupdatedAt: options.updatedAt ?? new Date().toISOString(),\n\t};\n}\n\nexport function hashCommandHook(handler: ExecutableHookHandler, options: HookTrustOptions = {}): string {\n\tconst platform = options.platform ?? process.platform;\n\tconst hook: { [key: string]: JsonValue | undefined } = {\n\t\tasync: false,\n\t\tcommand: handler.config.command,\n\t\tcommandWindows: handler.config.commandWindows,\n\t\tplatformCommand: selectedCommand(handler, platform),\n\t\tstatusMessage: handler.config.statusMessage,\n\t\ttimeout: normalizedTimeout(handler.config.timeout),\n\t\ttype: \"command\",\n\t};\n\tconst identity: { [key: string]: JsonValue | undefined } = {\n\t\tevent: handler.event,\n\t\thook,\n\t\tmatcher: handler.matcher,\n\t\tsourceKeyHash: sourceKeyHash(handler.source),\n\t};\n\treturn `sha256:${sha256Hex(JSON.stringify(canonicalJson(identity)))}`;\n}\n\nexport function isCommandHookTrusted(\n\thandler: ExecutableHookHandler,\n\tstate: HookTrustState,\n\toptions: HookTrustOptions = {},\n): boolean {\n\tconst record = buildStatefulHookTrustRecord(handler, state, options);\n\treturn record.executable;\n}\n\nexport function listHookTrustRecords(\n\thandlers: readonly ExecutableHookHandler[],\n\tstate: HookTrustState,\n\toptions: HookTrustOptions = {},\n): readonly HookTrustRecord[] {\n\treturn handlers.map((handler) => buildStatefulHookTrustRecord(handler, state, options));\n}\n\nexport function filterExecutableTrustedHooks(\n\thandlers: readonly ExecutableHookHandler[],\n\tstate: HookTrustState,\n\toptions: HookTrustOptions = {},\n): readonly ExecutableHookHandler[] {\n\treturn handlers.filter((handler) => buildStatefulHookTrustRecord(handler, state, options).executable);\n}\n\nexport function readHookTrustStateJson(input: string | undefined): HookTrustState {\n\tif (input === undefined || input.trim() === \"\") {\n\t\treturn emptyHookTrustState();\n\t}\n\ttry {\n\t\treturn parseHookTrustState(JSON.parse(input));\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\treturn emptyHookTrustState();\n\t\t}\n\t\treturn emptyHookTrustState();\n\t}\n}\n\nexport function hookTrustStorageScope(\n\thandler: ExecutableHookHandler,\n\toptions: HookTrustStorageOptions,\n): HookTrustStorageScope | undefined {\n\tif (handler.source.scope === \"project\") {\n\t\treturn options.projectTrusted ? \"project\" : undefined;\n\t}\n\treturn \"global\";\n}\n\nfunction buildStatefulHookTrustRecord(\n\thandler: ExecutableHookHandler,\n\tstate: HookTrustState,\n\toptions: HookTrustOptions,\n): HookTrustRecord {\n\tconst base = buildHookTrustRecord(handler, options);\n\tconst entry = state.hooks[base.id];\n\tconst enabled = entry?.enabled ?? true;\n\tconst trusted = entry?.trustedHash === base.currentHash;\n\treturn {\n\t\t...base,\n\t\tenabled,\n\t\ttrusted,\n\t\texecutable: enabled && trusted,\n\t\t...(entry === undefined ? {} : { entry }),\n\t};\n}\n\nfunction parseHookTrustState(input: unknown): HookTrustState {\n\tif (!isRecord(input) || input.version !== HOOK_STATE_VERSION || !isRecord(input.hooks)) {\n\t\treturn emptyHookTrustState();\n\t}\n\n\tconst hooks: Record<string, HookTrustEntry> = {};\n\tfor (const [id, entry] of Object.entries(input.hooks)) {\n\t\tconst parsed = parseHookTrustEntry(entry);\n\t\tif (parsed !== undefined) {\n\t\t\thooks[id] = parsed;\n\t\t}\n\t}\n\treturn { version: HOOK_STATE_VERSION, hooks };\n}\n\nfunction parseHookTrustEntry(input: unknown): HookTrustEntry | undefined {\n\tif (!isRecord(input)) {\n\t\treturn undefined;\n\t}\n\tconst enabled = input.enabled;\n\tconst trustedHash = input.trustedHash;\n\tconst scope = input.scope;\n\tconst sourcePath = input.sourcePath;\n\tconst matcher = input.matcher;\n\tconst commandPreview = input.commandPreview;\n\tconst updatedAt = input.updatedAt;\n\tif (\n\t\ttypeof enabled !== \"boolean\" ||\n\t\t(trustedHash !== undefined && typeof trustedHash !== \"string\") ||\n\t\t!isHookSourceScope(scope) ||\n\t\ttypeof sourcePath !== \"string\" ||\n\t\t(matcher !== undefined && typeof matcher !== \"string\") ||\n\t\ttypeof commandPreview !== \"string\" ||\n\t\ttypeof updatedAt !== \"string\"\n\t) {\n\t\treturn undefined;\n\t}\n\treturn {\n\t\tenabled,\n\t\t...(trustedHash === undefined ? {} : { trustedHash }),\n\t\tscope,\n\t\tsourcePath,\n\t\t...(matcher === undefined ? {} : { matcher }),\n\t\tcommandPreview,\n\t\tupdatedAt,\n\t};\n}\n\nfunction selectedCommand(handler: ExecutableHookHandler, platform: HookTrustPlatform): string {\n\tif (platform === \"win32\" && handler.config.commandWindows !== undefined) {\n\t\treturn handler.config.commandWindows;\n\t}\n\treturn handler.config.command;\n}\n\nfunction normalizedTimeout(timeout: number | undefined): number {\n\tif (timeout === undefined) {\n\t\treturn DEFAULT_HOOK_TIMEOUT_SECONDS;\n\t}\n\tif (!isValidHookTimeoutSeconds(timeout)) {\n\t\tthrow new Error(\"Invalid command hook timeout reached trust hashing.\");\n\t}\n\treturn timeout;\n}\n\nfunction sourceKeyHash(source: HookSourceMetadata): string {\n\treturn sha256Hex(\n\t\t[source.scope, source.sourcePath, source.pluginRoot ?? \"\", source.manifestPath ?? \"\"].join(\"\\0\"),\n\t).slice(0, 12);\n}\n\nfunction sha256Hex(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction canonicalJson(value: JsonValue): JsonValue {\n\tif (Array.isArray(value)) {\n\t\treturn value.map(canonicalJson);\n\t}\n\tif (!isJsonRecord(value)) {\n\t\treturn value;\n\t}\n\tconst result: { [key: string]: JsonValue } = {};\n\tfor (const key of Object.keys(value).sort()) {\n\t\tconst child = value[key];\n\t\tif (child !== undefined) {\n\t\t\tresult[key] = canonicalJson(child);\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isJsonRecord(value: JsonValue): value is { readonly [key: string]: JsonValue | undefined } {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isHookSourceScope(value: unknown): value is HookSourceScope {\n\treturn (\n\t\tvalue === \"global\" ||\n\t\tvalue === \"project\" ||\n\t\tvalue === \"plugin\" ||\n\t\tvalue === \"runtime\" ||\n\t\tvalue === \"cli\" ||\n\t\tvalue === \"managed\"\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"trust.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { DEFAULT_HOOK_TIMEOUT_SECONDS, isValidHookTimeoutSeconds } from \"./safety.ts\";\nimport type {\n\tExecutableHookHandler,\n\tHookSourceMetadata,\n\tHookSourceScope,\n\tHookTrustEntry,\n\tHookTrustState,\n} from \"./types.ts\";\n\nexport type HookTrustPlatform = NodeJS.Platform;\nexport type HookTrustStorageScope = \"global\" | \"project\";\n\nexport type HookTrustOptions = {\n\treadonly platform?: HookTrustPlatform;\n};\n\nexport type HookTrustStorageOptions = {\n\treadonly projectTrusted: boolean;\n};\n\nexport type HookTrustRecord = {\n\treadonly id: string;\n\treadonly currentHash: string;\n\treadonly enabled: boolean;\n\treadonly trusted: boolean;\n\treadonly executable: boolean;\n\treadonly scope: HookSourceScope;\n\treadonly sourcePath: string;\n\treadonly matcher?: string;\n\treadonly commandPreview: string;\n\treadonly entry?: HookTrustEntry;\n};\n\ntype JsonValue =\n\t| null\n\t| boolean\n\t| number\n\t| string\n\t| readonly JsonValue[]\n\t| { readonly [key: string]: JsonValue | undefined };\n\nexport { emptyHookTrustState, readHookTrustStateJson } from \"./trust-state-json.ts\";\n\nexport function hookTrustId(handler: ExecutableHookHandler): string {\n\treturn `hk_${sourceKeyHash(handler.source)}_${handler.event}_${handler.groupIndex}_${handler.handlerIndex}`;\n}\n\nexport function buildHookTrustRecord(handler: ExecutableHookHandler, options: HookTrustOptions = {}): HookTrustRecord {\n\tconst id = hookTrustId(handler);\n\tconst currentHash = hashCommandHook(handler, options);\n\tconst commandPreview = selectedCommand(handler, options.platform ?? process.platform);\n\treturn {\n\t\tid,\n\t\tcurrentHash,\n\t\tenabled: true,\n\t\ttrusted: false,\n\t\texecutable: false,\n\t\tscope: handler.source.scope,\n\t\tsourcePath: handler.source.sourcePath,\n\t\t...(handler.matcher === undefined ? {} : { matcher: handler.matcher }),\n\t\tcommandPreview,\n\t};\n}\n\nexport function createHookTrustEntry(\n\thandler: ExecutableHookHandler,\n\toptions: HookTrustOptions & { readonly updatedAt?: string } = {},\n): HookTrustEntry {\n\tconst commandPreview = selectedCommand(handler, options.platform ?? process.platform);\n\treturn {\n\t\tenabled: true,\n\t\ttrustedHash: hashCommandHook(handler, options),\n\t\tscope: handler.source.scope,\n\t\tsourcePath: handler.source.sourcePath,\n\t\t...(handler.matcher === undefined ? {} : { matcher: handler.matcher }),\n\t\tcommandPreview,\n\t\tupdatedAt: options.updatedAt ?? new Date().toISOString(),\n\t};\n}\n\nexport function hashCommandHook(handler: ExecutableHookHandler, options: HookTrustOptions = {}): string {\n\tconst platform = options.platform ?? process.platform;\n\tconst hook: { [key: string]: JsonValue | undefined } = {\n\t\tasync: false,\n\t\tcommand: handler.config.command,\n\t\tcommandWindows: handler.config.commandWindows,\n\t\tplatformCommand: selectedCommand(handler, platform),\n\t\tstatusMessage: handler.config.statusMessage,\n\t\ttimeout: normalizedTimeout(handler.config.timeout),\n\t\ttype: \"command\",\n\t};\n\tconst identity: { [key: string]: JsonValue | undefined } = {\n\t\tevent: handler.event,\n\t\thook,\n\t\tmatcher: handler.matcher,\n\t\tsourceKeyHash: sourceKeyHash(handler.source),\n\t};\n\treturn `sha256:${sha256Hex(JSON.stringify(canonicalJson(identity)))}`;\n}\n\nexport function isCommandHookTrusted(\n\thandler: ExecutableHookHandler,\n\tstate: HookTrustState,\n\toptions: HookTrustOptions = {},\n): boolean {\n\tconst record = buildStatefulHookTrustRecord(handler, state, options);\n\treturn record.executable;\n}\n\nexport function listHookTrustRecords(\n\thandlers: readonly ExecutableHookHandler[],\n\tstate: HookTrustState,\n\toptions: HookTrustOptions = {},\n): readonly HookTrustRecord[] {\n\treturn handlers.map((handler) => buildStatefulHookTrustRecord(handler, state, options));\n}\n\nexport function filterExecutableTrustedHooks(\n\thandlers: readonly ExecutableHookHandler[],\n\tstate: HookTrustState,\n\toptions: HookTrustOptions = {},\n): readonly ExecutableHookHandler[] {\n\treturn handlers.filter((handler) => buildStatefulHookTrustRecord(handler, state, options).executable);\n}\n\nexport function hookTrustStorageScope(\n\thandler: ExecutableHookHandler,\n\toptions: HookTrustStorageOptions,\n): HookTrustStorageScope | undefined {\n\tif (handler.source.scope === \"project\") {\n\t\treturn options.projectTrusted ? \"project\" : undefined;\n\t}\n\treturn \"global\";\n}\n\nfunction buildStatefulHookTrustRecord(\n\thandler: ExecutableHookHandler,\n\tstate: HookTrustState,\n\toptions: HookTrustOptions,\n): HookTrustRecord {\n\tconst base = buildHookTrustRecord(handler, options);\n\tconst entry = state.hooks[base.id];\n\tconst enabled = entry?.enabled ?? true;\n\tconst trusted = entry?.trustedHash === base.currentHash;\n\treturn {\n\t\t...base,\n\t\tenabled,\n\t\ttrusted,\n\t\texecutable: enabled && trusted,\n\t\t...(entry === undefined ? {} : { entry }),\n\t};\n}\n\nfunction selectedCommand(handler: ExecutableHookHandler, platform: HookTrustPlatform): string {\n\tif (platform === \"win32\" && handler.config.commandWindows !== undefined) {\n\t\treturn handler.config.commandWindows;\n\t}\n\treturn handler.config.command;\n}\n\nfunction normalizedTimeout(timeout: number | undefined): number {\n\tif (timeout === undefined) {\n\t\treturn DEFAULT_HOOK_TIMEOUT_SECONDS;\n\t}\n\tif (!isValidHookTimeoutSeconds(timeout)) {\n\t\tthrow new Error(\"Invalid command hook timeout reached trust hashing.\");\n\t}\n\treturn timeout;\n}\n\nfunction sourceKeyHash(source: HookSourceMetadata): string {\n\treturn sha256Hex(\n\t\t[source.scope, source.sourcePath, source.pluginRoot ?? \"\", source.manifestPath ?? \"\"].join(\"\\0\"),\n\t).slice(0, 12);\n}\n\nfunction sha256Hex(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction canonicalJson(value: JsonValue): JsonValue {\n\tif (Array.isArray(value)) {\n\t\treturn value.map(canonicalJson);\n\t}\n\tif (!isJsonRecord(value)) {\n\t\treturn value;\n\t}\n\tconst result: { [key: string]: JsonValue } = {};\n\tfor (const key of Object.keys(value).sort()) {\n\t\tconst child = value[key];\n\t\tif (child !== undefined) {\n\t\t\tresult[key] = canonicalJson(child);\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction isJsonRecord(value: JsonValue): value is { readonly [key: string]: JsonValue | undefined } {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-fable-5-1.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5-1.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAyElH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAMzF"}
|