@code-yeongyu/senpi 2026.7.29-6 → 2026.7.30-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 +107 -0
- package/README.md +3 -0
- package/dist/bun-global-launcher.d.ts +7 -0
- package/dist/bun-global-launcher.d.ts.map +1 -0
- package/dist/bun-global-launcher.js +21 -0
- package/dist/bun-global-launcher.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -6
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +10 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +62 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +1 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +1 -0
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/builtin/btw/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/btw/index.js +1 -0
- package/dist/core/extensions/builtin/btw/index.js.map +1 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/auth-lane.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/auth-lane.js +10 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/auth-lane.js.map +1 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/errors.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/errors.js +14 -0
- package/dist/core/extensions/builtin/claude-agent-sdk/errors.js.map +1 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/options.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/options.js +2 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/options.js.map +1 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/tools.d.ts +3 -0
- package/dist/core/extensions/builtin/claude-agent-sdk/tools.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-agent-sdk/tools.js +19 -0
- package/dist/core/extensions/builtin/claude-agent-sdk/tools.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle.d.ts +16 -0
- package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/idle.js +21 -0
- package/dist/core/extensions/builtin/compaction/idle.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +18 -1
- 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.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts +1 -2
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.js +1 -8
- package/dist/core/extensions/builtin/config-reload/watch-engine.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts +15 -0
- package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts.map +1 -0
- package/dist/core/extensions/builtin/config-reload/watch-event-source.js +114 -0
- package/dist/core/extensions/builtin/config-reload/watch-event-source.js.map +1 -0
- package/dist/core/extensions/builtin/goal/continuation.d.ts +2 -0
- package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/continuation.js +12 -0
- package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +4 -1
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.js +22 -18
- package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/prompt.js +2 -1
- package/dist/core/extensions/builtin/goal/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.js +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/apply.d.ts +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/apply.d.ts.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/apply.js +67 -66
- package/dist/core/extensions/builtin/gpt-apply-patch/apply.js.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/recovery.d.ts +4 -0
- package/dist/core/extensions/builtin/gpt-apply-patch/recovery.d.ts.map +1 -0
- package/dist/core/extensions/builtin/gpt-apply-patch/recovery.js +35 -0
- package/dist/core/extensions/builtin/gpt-apply-patch/recovery.js.map +1 -0
- package/dist/core/extensions/builtin/gpt-apply-patch/tool.d.ts.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/tool.js +0 -5
- package/dist/core/extensions/builtin/gpt-apply-patch/tool.js.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts +2 -0
- package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/types.js.map +1 -1
- package/dist/core/extensions/builtin/rules/rules/project-root.d.ts.map +1 -1
- package/dist/core/extensions/builtin/rules/rules/project-root.js +8 -1
- package/dist/core/extensions/builtin/rules/rules/project-root.js.map +1 -1
- package/dist/core/extensions/builtin/service-tier.d.ts.map +1 -1
- package/dist/core/extensions/builtin/service-tier.js +20 -1
- package/dist/core/extensions/builtin/service-tier.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/normalize.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/normalize.js +14 -3
- package/dist/core/extensions/builtin/todotools/normalize.js.map +1 -1
- package/dist/core/high-reasoning-warning.d.ts +10 -0
- package/dist/core/high-reasoning-warning.d.ts.map +1 -0
- package/dist/core/high-reasoning-warning.js +28 -0
- package/dist/core/high-reasoning-warning.js.map +1 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +3 -11
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +23 -1
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/session-log.d.ts +12 -0
- package/dist/core/session-log.d.ts.map +1 -0
- package/dist/core/session-log.js +101 -0
- package/dist/core/session-log.js.map +1 -0
- package/dist/core/settings-manager.d.ts +2 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +1 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/modes/interactive/compaction-queue-transfer.d.ts +6 -0
- package/dist/modes/interactive/compaction-queue-transfer.d.ts.map +1 -1
- package/dist/modes/interactive/compaction-queue-transfer.js +1 -1
- package/dist/modes/interactive/compaction-queue-transfer.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +10 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +70 -7
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/risky-main-model-warning.d.ts +5 -0
- package/dist/modes/interactive/risky-main-model-warning.d.ts.map +1 -0
- package/dist/modes/interactive/risky-main-model-warning.js +8 -0
- package/dist/modes/interactive/risky-main-model-warning.js.map +1 -0
- package/dist/modes/interactive/tips/catalog/subagent-tips.d.ts.map +1 -1
- package/dist/modes/interactive/tips/catalog/subagent-tips.js +30 -0
- package/dist/modes/interactive/tips/catalog/subagent-tips.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +6 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +22 -2
- package/dist/utils/version-check.js.map +1 -1
- package/docs/docs.json +4 -0
- package/docs/quickstart.md +3 -0
- package/docs/release-guide.md +636 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +2 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts +4 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js +106 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.d.ts +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.js +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.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/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/dist/tool-call-middleware/index.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +13 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/recovery-stream.js +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/recovery-stream.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery-stream.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery-stream.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery-stream.js +29 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery-stream.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery.js +82 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/kimi-xtml/thinking-recovery.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js +1 -12
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts +7 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js +9 -3
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js +5 -3
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.js +1 -12
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.d.ts +5 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.d.ts.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.js +17 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.js.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.d.ts +9 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.js +10 -4
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts +21 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js +239 -41
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.js +25 -6
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.d.ts +32 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.d.ts.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.js +64 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.js.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.d.ts +5 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.js +10 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js +2 -13
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.d.ts +7 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js +9 -3
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js +5 -3
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js +2 -13
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.d.ts +5 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.d.ts.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.js +13 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.js.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.d.ts +9 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js +10 -4
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts +21 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js +239 -41
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js +25 -6
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.d.ts +32 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.d.ts.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js +57 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.d.ts +5 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js +9 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/package.json +4 -3
- package/node_modules/brace-expansion/README.md +12 -0
- package/node_modules/brace-expansion/dist/commonjs/index.d.ts +2 -0
- package/node_modules/brace-expansion/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/brace-expansion/dist/commonjs/index.js +138 -86
- package/node_modules/brace-expansion/dist/commonjs/index.js.map +1 -1
- package/node_modules/brace-expansion/dist/esm/index.d.ts +2 -0
- package/node_modules/brace-expansion/dist/esm/index.d.ts.map +1 -1
- package/node_modules/brace-expansion/dist/esm/index.js +137 -85
- package/node_modules/brace-expansion/dist/esm/index.js.map +1 -1
- package/node_modules/brace-expansion/package.json +2 -2
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,iBAAiB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAC1C,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC5B,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,SAAS;IACT,YAAY;IACZ,WAAW;IACX,QAAQ;IACR,cAAc;IACd,aAAa;IACb,cAAc;IACd,eAAe;IACf,WAAW;IACX,cAAc;IACd,OAAO;IACP,YAAY;CACZ,CAAC,CAAC;AACH,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,mBAAmB;IACnB,yBAAyB;IACzB,kBAAkB;IAClB,eAAe;IACf,sBAAsB;IACtB,UAAU;IACV,cAAc;IACd,mBAAmB;IACnB,oBAAoB;IACpB,iBAAiB;IACjB,qBAAqB;IACrB,gBAAgB;CAChB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/log.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, mkdirSync, openSync, renameSync, statSync, writeSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nconst DEFAULT_MAX_BYTES = 5 * 1024 * 1024;\nconst ALLOWED_KEYS = new Set([\n\t\"origin\",\n\t\"reason\",\n\t\"route\",\n\t\"variant\",\n\t\"generation\",\n\t\"requestId\",\n\t\"tokens\",\n\t\"tokensBefore\",\n\t\"savedTokens\",\n\t\"savingsRatio\",\n\t\"contextWindow\",\n\t\"threshold\",\n\t\"remainingSec\",\n\t\"count\",\n\t\"durationMs\",\n]);\nconst DEBUG_PREFIX = \"[senpi-compaction]\";\nconst EVENTS = new Set([\n\t\"speculative_started\",\n\t\"speculative_applied\",\n\t\"speculative_stale\",\n\t\"speculative_invalidated\",\n\t\"blocking_started\",\n\t\"warm_consumed\",\n\t\"core_route_generated\",\n\t\"skip_cap\",\n\t\"skip_breaker\",\n\t\"threshold_trigger\",\n\t\"hard_limit_trigger\",\n\t\"emergency_prune\",\n\t\"ineffective_counted\",\n\t\"summary_failed\",\n]);\n\nexport type CompactionLoggerEvent =\n\t| \"speculative_started\"\n\t| \"speculative_applied\"\n\t| \"speculative_stale\"\n\t| \"speculative_invalidated\"\n\t| \"blocking_started\"\n\t| \"warm_consumed\"\n\t| \"core_route_generated\"\n\t| \"skip_cap\"\n\t| \"skip_breaker\"\n\t| \"threshold_trigger\"\n\t| \"hard_limit_trigger\"\n\t| \"emergency_prune\"\n\t| \"ineffective_counted\"\n\t| \"idle_trigger\"\n\t| \"summary_failed\";\n\nexport interface CompactionLoggerData {\n\torigin?: string;\n\treason?: string;\n\troute?: string;\n\tvariant?: string;\n\tgeneration?: number;\n\trequestId?: string;\n\ttokens?: number;\n\ttokensBefore?: number;\n\tsavedTokens?: number;\n\tsavingsRatio?: number;\n\tcontextWindow?: number;\n\tthreshold?: number;\n\tremainingSec?: number;\n\tcount?: number;\n\tdurationMs?: number;\n}\n\nexport interface CompactionLogger {\n\tdebug(event: CompactionLoggerEvent, data?: CompactionLoggerData): void;\n\tinfo(event: CompactionLoggerEvent, data?: CompactionLoggerData): void;\n}\n\nexport interface CompactionLoggerOptions {\n\tsink?: (line: string) => void;\n\tmirrorToStderr?: boolean;\n\tmaxBytes?: number;\n}\n\nexport function createCompactionLogger(\n\tagentDir: string | undefined,\n\toptions: CompactionLoggerOptions = {},\n): CompactionLogger {\n\tif (typeof agentDir !== \"string\" || agentDir.length === 0) {\n\t\treturn { debug: () => {}, info: () => {} };\n\t}\n\tconst filePath = join(agentDir, \"logs\", \"compaction.log\");\n\tconst maxBytes = validMaxBytes(options.maxBytes);\n\tlet reportedFailure = false;\n\n\tfunction log(level: \"debug\" | \"info\", event: CompactionLoggerEvent, data?: CompactionLoggerData): void {\n\t\ttry {\n\t\t\tif (!EVENTS.has(event)) return;\n\t\t\tconst line = formatLine(level, event, data);\n\t\t\twriteLine(filePath, line, maxBytes, options.sink);\n\t\t\tif (options.mirrorToStderr ?? process.env.SENPI_COMPACTION_DEBUG === \"1\") {\n\t\t\t\tconsole.error(DEBUG_PREFIX, line);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (!reportedFailure) {\n\t\t\t\treportedFailure = true;\n\t\t\t\tconsole.error(\"Unable to write compaction log\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tdebug: (event, data) => log(\"debug\", event, data),\n\t\tinfo: (event, data) => log(\"info\", event, data),\n\t};\n}\n\nfunction validMaxBytes(value: number | undefined): number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0 ? Math.floor(value) : DEFAULT_MAX_BYTES;\n}\n\nfunction formatLine(level: \"debug\" | \"info\", event: CompactionLoggerEvent, data?: CompactionLoggerData): string {\n\tconst entry: Record<string, unknown> = { ts: new Date().toISOString(), level, event };\n\tif (data) {\n\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\tif (!ALLOWED_KEYS.has(key)) continue;\n\t\t\tconst safeValue = safeValueOf(value, new WeakSet<object>());\n\t\t\tif (safeValue !== undefined) entry[key] = safeValue;\n\t\t}\n\t}\n\treturn JSON.stringify(entry);\n}\n\nfunction writeLine(filePath: string, line: string, maxBytes: number, sink?: (line: string) => void): void {\n\tconst text = `${line}\\n`;\n\tif (sink) sink(line);\n\tmkdirSync(dirname(filePath), { recursive: true, mode: 0o700 });\n\tif (needsRotate(filePath, Buffer.byteLength(text), maxBytes)) {\n\t\tconst rotated = `${filePath}.1`;\n\t\trenameSync(filePath, rotated);\n\t}\n\tconst fd = openSync(filePath, \"a\", 0o600);\n\ttry {\n\t\twriteSync(fd, text);\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n}\n\nfunction needsRotate(filePath: string, incomingBytes: number, maxBytes: number): boolean {\n\ttry {\n\t\treturn statSync(filePath).size + incomingBytes > maxBytes;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction safeValueOf(value: unknown, seen: WeakSet<object>): unknown {\n\tif (value === undefined) return undefined;\n\tif (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" || value === null)\n\t\treturn value;\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (typeof value === \"symbol\" || typeof value === \"function\") return String(value);\n\tif (typeof value !== \"object\") return String(value);\n\tif (seen.has(value)) return \"[Circular]\";\n\tseen.add(value);\n\tif (Array.isArray(value)) return value.map((item) => safeValueOf(item, seen));\n\tconst out: Record<string, unknown> = {};\n\tfor (const [key, item] of Object.entries(value)) {\n\t\tif (ALLOWED_KEYS.has(key)) {\n\t\t\tconst safe = safeValueOf(item, seen);\n\t\t\tif (safe !== undefined) out[key] = safe;\n\t\t}\n\t}\n\treturn out;\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { createFsWatchEventSource } from "./watch-event-source.ts";
|
|
1
2
|
export type WatchTarget = {
|
|
2
3
|
readonly id: string;
|
|
3
4
|
readonly kind: "dir" | "dir-recursive";
|
|
@@ -38,6 +39,4 @@ export declare class ConfigReloadWatchEngine {
|
|
|
38
39
|
close(): void;
|
|
39
40
|
getBaselineSnapshot(): ReadonlyMap<string, string>;
|
|
40
41
|
}
|
|
41
|
-
/** Production event source. Tests inject a deterministic source instead. */
|
|
42
|
-
export declare function createFsWatchEventSource(onError?: (error: unknown, path: string) => void): WatchEventSource;
|
|
43
42
|
//# sourceMappingURL=watch-engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch-engine.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"watch-engine.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-engine.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,eAAe,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;AAEtF,MAAM,MAAM,gBAAgB,GAAG,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,KACrC,MAAM,IAAI,CAAC;AAEhB,MAAM,MAAM,UAAU,GAAG;IACxB,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IACjF,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;CACzD,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACxB,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC5C,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC7C,CAAC;AAqBF;;;GAGG;AACH,qBAAa,uBAAuB;;IAanC,YAAY,OAAO,EAAE,8BAA8B,EAgClD;IAED,KAAK,IAAI,IAAI,CAgBZ;IAED,mBAAmB,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAQjD;CAkOD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
3
3
|
import { basename, isAbsolute, join, normalize, resolve, sep } from "node:path";
|
|
4
|
-
|
|
4
|
+
export { createFsWatchEventSource } from "./watch-event-source.js";
|
|
5
5
|
const DEFAULT_DEBOUNCE_MS = 200;
|
|
6
6
|
const DEFAULT_CLOCK = {
|
|
7
7
|
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
@@ -272,13 +272,6 @@ export class ConfigReloadWatchEngine {
|
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
|
-
/** Production event source. Tests inject a deterministic source instead. */
|
|
276
|
-
export function createFsWatchEventSource(onError = () => { }) {
|
|
277
|
-
return (path, listener, options) => {
|
|
278
|
-
const watcher = watchWithErrorHandler(path, listener, () => onError(new Error(`fs.watch failed for ${path}`), path), { recursive: options?.recursive ?? false });
|
|
279
|
-
return () => watcher?.close();
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
275
|
function hashFile(path) {
|
|
283
276
|
return createHash("sha256").update(readFileSync(path)).digest("hex");
|
|
284
277
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch-engine.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-engine.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { lstatSync, readdirSync, readFileSync, type Stats } from \"node:fs\";\nimport { basename, isAbsolute, join, normalize, resolve, sep } from \"node:path\";\nimport { watchWithErrorHandler } from \"../../../../utils/fs-watch.ts\";\n\nexport type WatchTarget = {\n\treadonly id: string;\n\treadonly kind: \"dir\" | \"dir-recursive\";\n\treadonly path: string;\n\treadonly allowList?: readonly string[];\n\treadonly filter?: (relPath: string) => boolean;\n};\n\nexport type WatchEventListener = (eventType: string, filename: string | null) => void;\n\nexport type WatchEventSource = (\n\tpath: string,\n\tlistener: WatchEventListener,\n\toptions?: { readonly recursive: boolean },\n) => () => void;\n\nexport type WatchClock = {\n\tsetTimeout(callback: () => void, delayMs: number): ReturnType<typeof setTimeout>;\n\tclearTimeout(timer: ReturnType<typeof setTimeout>): void;\n};\n\nexport type RealChange = {\n\treadonly changedPaths: readonly string[];\n\treadonly created: readonly string[];\n\treadonly deleted: readonly string[];\n};\n\nexport type ConfigReloadWatchEngineOptions = {\n\treadonly targets: readonly WatchTarget[];\n\treadonly subscribe: WatchEventSource;\n\treadonly onRealChange: (change: RealChange) => void;\n\treadonly onError?: (error: unknown, path: string) => void;\n\treadonly debounceMs?: number;\n\treadonly clock?: WatchClock;\n\t/** Test seam. Production callers use SHA-256 of file bytes. */\n\treadonly hashFile?: (path: string) => string;\n};\n\ntype TargetState = {\n\treadonly target: ResolvedWatchTarget;\n\treadonly hashes: Map<string, string>;\n\treadonly allowedDirectories: Set<string>;\n};\n\ntype ResolvedWatchTarget = Omit<WatchTarget, \"path\"> & { readonly path: string };\n\ntype ScanResult = {\n\treadonly hashes: Map<string, string>;\n\treadonly allowedDirectories: Set<string>;\n};\n\nconst DEFAULT_DEBOUNCE_MS = 200;\nconst DEFAULT_CLOCK: WatchClock = {\n\tsetTimeout: (callback, delayMs) => setTimeout(callback, delayMs),\n\tclearTimeout: (timer) => clearTimeout(timer),\n};\n\n/**\n * Hash-gates filesystem events. Targets are directories by design: watching a\n * file directly breaks when editors atomically rename a replacement over it.\n */\nexport class ConfigReloadWatchEngine {\n\treadonly #states: TargetState[];\n\treadonly #unsubscribes: (() => void)[] = [];\n\treadonly #subscribe: WatchEventSource;\n\treadonly #onRealChange: (change: RealChange) => void;\n\treadonly #onError: (error: unknown, path: string) => void;\n\treadonly #hashFile: (path: string) => string;\n\treadonly #clock: WatchClock;\n\treadonly #debounceMs: number;\n\treadonly #pending = new Map<TargetState, Set<string> | null>();\n\t#timer: ReturnType<typeof setTimeout> | undefined;\n\t#closed = false;\n\n\tconstructor(options: ConfigReloadWatchEngineOptions) {\n\t\tthis.#subscribe = options.subscribe;\n\t\tthis.#onRealChange = options.onRealChange;\n\t\tthis.#onError = options.onError ?? (() => {});\n\t\tthis.#hashFile = options.hashFile ?? hashFile;\n\t\tthis.#clock = options.clock ?? DEFAULT_CLOCK;\n\t\tthis.#debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\t\tthis.#states = options.targets.map((target) => {\n\t\t\tconst resolvedTarget = { ...target, path: resolve(target.path) };\n\t\t\tconst scan = this.#scan(resolvedTarget);\n\t\t\treturn {\n\t\t\t\ttarget: resolvedTarget,\n\t\t\t\thashes: scan.hashes,\n\t\t\t\tallowedDirectories: scan.allowedDirectories,\n\t\t\t};\n\t\t});\n\n\t\tfor (const state of this.#states) {\n\t\t\ttry {\n\t\t\t\tthis.#unsubscribes.push(\n\t\t\t\t\tthis.#subscribe(\n\t\t\t\t\t\tstate.target.path,\n\t\t\t\t\t\t(eventType, filename) => {\n\t\t\t\t\t\t\tthis.#onEvent(state, eventType, filename);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ recursive: state.target.kind === \"dir-recursive\" },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, state.target.path);\n\t\t\t}\n\t\t}\n\t}\n\n\tclose(): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#closed = true;\n\t\tif (this.#timer) {\n\t\t\tthis.#clock.clearTimeout(this.#timer);\n\t\t\tthis.#timer = undefined;\n\t\t}\n\t\tfor (const unsubscribe of this.#unsubscribes.splice(0)) {\n\t\t\ttry {\n\t\t\t\tunsubscribe();\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, \"watch subscription\");\n\t\t\t}\n\t\t}\n\t}\n\n\tgetBaselineSnapshot(): ReadonlyMap<string, string> {\n\t\tconst snapshot = new Map<string, string>();\n\t\tfor (const state of this.#states) {\n\t\t\tfor (const [path, hash] of state.hashes) {\n\t\t\t\tsnapshot.set(path, hash);\n\t\t\t}\n\t\t}\n\t\treturn snapshot;\n\t}\n\n\t#onEvent(state: TargetState, _eventType: string, filename: string | null): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tif (filename === null) {\n\t\t\tthis.#pending.set(state, null);\n\t\t} else if (this.#pending.get(state) !== null) {\n\t\t\tconst affected = this.#pending.get(state) ?? new Set<string>();\n\t\t\tconst relPath = normalizeRelativePath(filename);\n\t\t\tif (relPath && this.#matches(state.target, relPath)) {\n\t\t\t\taffected.add(relPath);\n\t\t\t\tthis.#pending.set(state, affected);\n\t\t\t}\n\t\t}\n\t\tthis.#schedule();\n\t}\n\n\t#schedule(): void {\n\t\tif (this.#timer) {\n\t\t\tthis.#clock.clearTimeout(this.#timer);\n\t\t}\n\t\tthis.#timer = this.#clock.setTimeout(() => {\n\t\t\tthis.#timer = undefined;\n\t\t\tthis.#evaluatePending();\n\t\t}, this.#debounceMs);\n\t}\n\n\t#evaluatePending(): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tconst changes = new Map<string, { created: boolean; deleted: boolean }>();\n\t\tfor (const [state, affected] of this.#pending) {\n\t\t\tthis.#evaluateState(state, affected, changes);\n\t\t}\n\t\tthis.#pending.clear();\n\t\tif (changes.size > 0) {\n\t\t\tconst changedPaths = [...changes.keys()].sort();\n\t\t\tthis.#onRealChange({\n\t\t\t\tchangedPaths,\n\t\t\t\tcreated: changedPaths.filter((path) => changes.get(path)?.created),\n\t\t\t\tdeleted: changedPaths.filter((path) => changes.get(path)?.deleted),\n\t\t\t});\n\t\t}\n\t}\n\n\t#evaluateState(\n\t\tstate: TargetState,\n\t\taffected: Set<string> | null,\n\t\tchanges: Map<string, { created: boolean; deleted: boolean }>,\n\t): void {\n\t\tconst previousHashes = new Map(state.hashes);\n\t\tconst previousDirectories = new Set(state.allowedDirectories);\n\t\tconst next = affected === null ? this.#scan(state.target) : this.#scanAffected(state.target, affected, state);\n\n\t\tif (affected === null) {\n\t\t\tstate.hashes.clear();\n\t\t\tfor (const [path, hash] of next.hashes) {\n\t\t\t\tstate.hashes.set(path, hash);\n\t\t\t}\n\t\t\tstate.allowedDirectories.clear();\n\t\t\tfor (const path of next.allowedDirectories) {\n\t\t\t\tstate.allowedDirectories.add(path);\n\t\t\t}\n\t\t\tthis.#compare(previousHashes, previousDirectories, state.hashes, state.allowedDirectories, changes);\n\t\t\treturn;\n\t\t}\n\n\t\tconst prefixes = [...affected].map((relPath) => join(state.target.path, relPath));\n\t\tfor (const path of [...state.hashes.keys()]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.hashes.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const path of [...state.allowedDirectories]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.allowedDirectories.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const [path, hash] of next.hashes) {\n\t\t\tstate.hashes.set(path, hash);\n\t\t}\n\t\tfor (const path of next.allowedDirectories) {\n\t\t\tstate.allowedDirectories.add(path);\n\t\t}\n\t\tthis.#compare(previousHashes, previousDirectories, state.hashes, state.allowedDirectories, changes);\n\t}\n\n\t#scanAffected(target: ResolvedWatchTarget, affected: Set<string>, state: TargetState): ScanResult {\n\t\tconst result: ScanResult = { hashes: new Map(), allowedDirectories: new Set() };\n\t\tfor (const relPath of affected) {\n\t\t\tconst absolutePath = join(target.path, relPath);\n\t\t\tthis.#scanPath(target, absolutePath, relPath, result, state);\n\t\t}\n\t\treturn result;\n\t}\n\n\t#scan(target: ResolvedWatchTarget): ScanResult {\n\t\tconst result: ScanResult = { hashes: new Map(), allowedDirectories: new Set() };\n\t\tthis.#scanPath(target, target.path, \"\", result);\n\t\treturn result;\n\t}\n\n\t#scanPath(\n\t\ttarget: ResolvedWatchTarget,\n\t\tabsolutePath: string,\n\t\trelPath: string,\n\t\tresult: ScanResult,\n\t\tstate?: TargetState,\n\t): void {\n\t\tif (relPath && !this.#matches(target, relPath)) {\n\t\t\treturn;\n\t\t}\n\t\tlet entry: Stats;\n\t\ttry {\n\t\t\tentry = lstatSync(absolutePath);\n\t\t} catch (error) {\n\t\t\tif (state && !isMissing(error)) {\n\t\t\t\tthis.#reportError(error, absolutePath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (entry.isSymbolicLink()) {\n\t\t\treturn;\n\t\t}\n\t\tif (entry.isFile()) {\n\t\t\ttry {\n\t\t\t\tresult.hashes.set(absolutePath, this.#hashFile(absolutePath));\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, absolutePath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!entry.isDirectory()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst dotDirectory = relPath !== \"\" && basename(relPath).startsWith(\".\");\n\t\tconst explicitlyAllowedDirectory = relPath !== \"\" && this.#isExplicitlyAllowedDirectory(target, relPath);\n\t\tif (explicitlyAllowedDirectory) {\n\t\t\tresult.allowedDirectories.add(absolutePath);\n\t\t}\n\t\tif (relPath && target.kind === \"dir\") {\n\t\t\treturn;\n\t\t}\n\t\tif (dotDirectory && !explicitlyAllowedDirectory) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tfor (const child of readdirSync(absolutePath, { withFileTypes: true })) {\n\t\t\t\tif (child.isSymbolicLink() || child.name === \"node_modules\" || child.name === \".git\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst childRelPath = relPath ? join(relPath, child.name) : child.name;\n\t\t\t\tif (\n\t\t\t\t\tchild.isDirectory() &&\n\t\t\t\t\tchild.name.startsWith(\".\") &&\n\t\t\t\t\t!this.#isExplicitlyAllowedDirectory(target, childRelPath)\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.#scanPath(target, join(absolutePath, child.name), childRelPath, result, state);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.#reportError(error, absolutePath);\n\t\t}\n\t}\n\n\t#compare(\n\t\tpreviousHashes: ReadonlyMap<string, string>,\n\t\tpreviousDirectories: ReadonlySet<string>,\n\t\tnextHashes: ReadonlyMap<string, string>,\n\t\tnextDirectories: ReadonlySet<string>,\n\t\tchanges: Map<string, { created: boolean; deleted: boolean }>,\n\t): void {\n\t\tfor (const [path, hash] of nextHashes) {\n\t\t\tconst oldHash = previousHashes.get(path);\n\t\t\tif (oldHash !== hash) {\n\t\t\t\tchanges.set(path, { created: oldHash === undefined, deleted: false });\n\t\t\t}\n\t\t}\n\t\tfor (const path of previousHashes.keys()) {\n\t\t\tif (!nextHashes.has(path)) {\n\t\t\t\tchanges.set(path, { created: false, deleted: true });\n\t\t\t}\n\t\t}\n\t\tfor (const path of nextDirectories) {\n\t\t\tif (!previousDirectories.has(path)) {\n\t\t\t\tchanges.set(path, { created: true, deleted: false });\n\t\t\t}\n\t\t}\n\t\tfor (const path of previousDirectories) {\n\t\t\tif (!nextDirectories.has(path)) {\n\t\t\t\tchanges.set(path, { created: false, deleted: true });\n\t\t\t}\n\t\t}\n\t}\n\n\t#matches(target: ResolvedWatchTarget, relPath: string): boolean {\n\t\tif (!target.kind.includes(\"recursive\") && relPath.includes(sep)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (\n\t\t\ttarget.allowList &&\n\t\t\t!target.allowList.some((allowed) => relPath === allowed || relPath.startsWith(`${allowed}${sep}`))\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn target.filter?.(relPath) ?? true;\n\t}\n\n\t#isExplicitlyAllowedDirectory(target: ResolvedWatchTarget, relPath: string): boolean {\n\t\treturn (\n\t\t\ttarget.allowList?.some((allowed) => relPath === allowed || relPath.startsWith(`${allowed}${sep}`)) ?? false\n\t\t);\n\t}\n\n\t#reportError(error: unknown, path: string): void {\n\t\ttry {\n\t\t\tthis.#onError(error, path);\n\t\t} catch {\n\t\t\t// Error reporting must not take down the watcher.\n\t\t}\n\t}\n}\n\n/** Production event source. Tests inject a deterministic source instead. */\nexport function createFsWatchEventSource(onError: (error: unknown, path: string) => void = () => {}): WatchEventSource {\n\treturn (path, listener, options) => {\n\t\tconst watcher = watchWithErrorHandler(\n\t\t\tpath,\n\t\t\tlistener,\n\t\t\t() => onError(new Error(`fs.watch failed for ${path}`), path),\n\t\t\t{ recursive: options?.recursive ?? false },\n\t\t);\n\t\treturn () => watcher?.close();\n\t};\n}\n\nfunction hashFile(path: string): string {\n\treturn createHash(\"sha256\").update(readFileSync(path)).digest(\"hex\");\n}\n\nfunction normalizeRelativePath(filename: string): string | undefined {\n\tif (isAbsolute(filename)) {\n\t\treturn undefined;\n\t}\n\tconst normalized = normalize(filename);\n\treturn normalized === \".\" || normalized === \"..\" || normalized.startsWith(`..${sep}`) ? undefined : normalized;\n}\n\nfunction isWithin(path: string, prefix: string): boolean {\n\treturn path === prefix || path.startsWith(`${prefix}${sep}`);\n}\n\nfunction isMissing(error: unknown): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"watch-engine.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-engine.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { lstatSync, readdirSync, readFileSync, type Stats } from \"node:fs\";\nimport { basename, isAbsolute, join, normalize, resolve, sep } from \"node:path\";\n\nexport { createFsWatchEventSource } from \"./watch-event-source.ts\";\n\nexport type WatchTarget = {\n\treadonly id: string;\n\treadonly kind: \"dir\" | \"dir-recursive\";\n\treadonly path: string;\n\treadonly allowList?: readonly string[];\n\treadonly filter?: (relPath: string) => boolean;\n};\n\nexport type WatchEventListener = (eventType: string, filename: string | null) => void;\n\nexport type WatchEventSource = (\n\tpath: string,\n\tlistener: WatchEventListener,\n\toptions?: { readonly recursive: boolean },\n) => () => void;\n\nexport type WatchClock = {\n\tsetTimeout(callback: () => void, delayMs: number): ReturnType<typeof setTimeout>;\n\tclearTimeout(timer: ReturnType<typeof setTimeout>): void;\n};\n\nexport type RealChange = {\n\treadonly changedPaths: readonly string[];\n\treadonly created: readonly string[];\n\treadonly deleted: readonly string[];\n};\n\nexport type ConfigReloadWatchEngineOptions = {\n\treadonly targets: readonly WatchTarget[];\n\treadonly subscribe: WatchEventSource;\n\treadonly onRealChange: (change: RealChange) => void;\n\treadonly onError?: (error: unknown, path: string) => void;\n\treadonly debounceMs?: number;\n\treadonly clock?: WatchClock;\n\t/** Test seam. Production callers use SHA-256 of file bytes. */\n\treadonly hashFile?: (path: string) => string;\n};\n\ntype TargetState = {\n\treadonly target: ResolvedWatchTarget;\n\treadonly hashes: Map<string, string>;\n\treadonly allowedDirectories: Set<string>;\n};\n\ntype ResolvedWatchTarget = Omit<WatchTarget, \"path\"> & { readonly path: string };\n\ntype ScanResult = {\n\treadonly hashes: Map<string, string>;\n\treadonly allowedDirectories: Set<string>;\n};\n\nconst DEFAULT_DEBOUNCE_MS = 200;\nconst DEFAULT_CLOCK: WatchClock = {\n\tsetTimeout: (callback, delayMs) => setTimeout(callback, delayMs),\n\tclearTimeout: (timer) => clearTimeout(timer),\n};\n\n/**\n * Hash-gates filesystem events. Targets are directories by design: watching a\n * file directly breaks when editors atomically rename a replacement over it.\n */\nexport class ConfigReloadWatchEngine {\n\treadonly #states: TargetState[];\n\treadonly #unsubscribes: (() => void)[] = [];\n\treadonly #subscribe: WatchEventSource;\n\treadonly #onRealChange: (change: RealChange) => void;\n\treadonly #onError: (error: unknown, path: string) => void;\n\treadonly #hashFile: (path: string) => string;\n\treadonly #clock: WatchClock;\n\treadonly #debounceMs: number;\n\treadonly #pending = new Map<TargetState, Set<string> | null>();\n\t#timer: ReturnType<typeof setTimeout> | undefined;\n\t#closed = false;\n\n\tconstructor(options: ConfigReloadWatchEngineOptions) {\n\t\tthis.#subscribe = options.subscribe;\n\t\tthis.#onRealChange = options.onRealChange;\n\t\tthis.#onError = options.onError ?? (() => {});\n\t\tthis.#hashFile = options.hashFile ?? hashFile;\n\t\tthis.#clock = options.clock ?? DEFAULT_CLOCK;\n\t\tthis.#debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\t\tthis.#states = options.targets.map((target) => {\n\t\t\tconst resolvedTarget = { ...target, path: resolve(target.path) };\n\t\t\tconst scan = this.#scan(resolvedTarget);\n\t\t\treturn {\n\t\t\t\ttarget: resolvedTarget,\n\t\t\t\thashes: scan.hashes,\n\t\t\t\tallowedDirectories: scan.allowedDirectories,\n\t\t\t};\n\t\t});\n\n\t\tfor (const state of this.#states) {\n\t\t\ttry {\n\t\t\t\tthis.#unsubscribes.push(\n\t\t\t\t\tthis.#subscribe(\n\t\t\t\t\t\tstate.target.path,\n\t\t\t\t\t\t(eventType, filename) => {\n\t\t\t\t\t\t\tthis.#onEvent(state, eventType, filename);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ recursive: state.target.kind === \"dir-recursive\" },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, state.target.path);\n\t\t\t}\n\t\t}\n\t}\n\n\tclose(): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#closed = true;\n\t\tif (this.#timer) {\n\t\t\tthis.#clock.clearTimeout(this.#timer);\n\t\t\tthis.#timer = undefined;\n\t\t}\n\t\tfor (const unsubscribe of this.#unsubscribes.splice(0)) {\n\t\t\ttry {\n\t\t\t\tunsubscribe();\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, \"watch subscription\");\n\t\t\t}\n\t\t}\n\t}\n\n\tgetBaselineSnapshot(): ReadonlyMap<string, string> {\n\t\tconst snapshot = new Map<string, string>();\n\t\tfor (const state of this.#states) {\n\t\t\tfor (const [path, hash] of state.hashes) {\n\t\t\t\tsnapshot.set(path, hash);\n\t\t\t}\n\t\t}\n\t\treturn snapshot;\n\t}\n\n\t#onEvent(state: TargetState, _eventType: string, filename: string | null): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tif (filename === null) {\n\t\t\tthis.#pending.set(state, null);\n\t\t} else if (this.#pending.get(state) !== null) {\n\t\t\tconst affected = this.#pending.get(state) ?? new Set<string>();\n\t\t\tconst relPath = normalizeRelativePath(filename);\n\t\t\tif (relPath && this.#matches(state.target, relPath)) {\n\t\t\t\taffected.add(relPath);\n\t\t\t\tthis.#pending.set(state, affected);\n\t\t\t}\n\t\t}\n\t\tthis.#schedule();\n\t}\n\n\t#schedule(): void {\n\t\tif (this.#timer) {\n\t\t\tthis.#clock.clearTimeout(this.#timer);\n\t\t}\n\t\tthis.#timer = this.#clock.setTimeout(() => {\n\t\t\tthis.#timer = undefined;\n\t\t\tthis.#evaluatePending();\n\t\t}, this.#debounceMs);\n\t}\n\n\t#evaluatePending(): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tconst changes = new Map<string, { created: boolean; deleted: boolean }>();\n\t\tfor (const [state, affected] of this.#pending) {\n\t\t\tthis.#evaluateState(state, affected, changes);\n\t\t}\n\t\tthis.#pending.clear();\n\t\tif (changes.size > 0) {\n\t\t\tconst changedPaths = [...changes.keys()].sort();\n\t\t\tthis.#onRealChange({\n\t\t\t\tchangedPaths,\n\t\t\t\tcreated: changedPaths.filter((path) => changes.get(path)?.created),\n\t\t\t\tdeleted: changedPaths.filter((path) => changes.get(path)?.deleted),\n\t\t\t});\n\t\t}\n\t}\n\n\t#evaluateState(\n\t\tstate: TargetState,\n\t\taffected: Set<string> | null,\n\t\tchanges: Map<string, { created: boolean; deleted: boolean }>,\n\t): void {\n\t\tconst previousHashes = new Map(state.hashes);\n\t\tconst previousDirectories = new Set(state.allowedDirectories);\n\t\tconst next = affected === null ? this.#scan(state.target) : this.#scanAffected(state.target, affected, state);\n\n\t\tif (affected === null) {\n\t\t\tstate.hashes.clear();\n\t\t\tfor (const [path, hash] of next.hashes) {\n\t\t\t\tstate.hashes.set(path, hash);\n\t\t\t}\n\t\t\tstate.allowedDirectories.clear();\n\t\t\tfor (const path of next.allowedDirectories) {\n\t\t\t\tstate.allowedDirectories.add(path);\n\t\t\t}\n\t\t\tthis.#compare(previousHashes, previousDirectories, state.hashes, state.allowedDirectories, changes);\n\t\t\treturn;\n\t\t}\n\n\t\tconst prefixes = [...affected].map((relPath) => join(state.target.path, relPath));\n\t\tfor (const path of [...state.hashes.keys()]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.hashes.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const path of [...state.allowedDirectories]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.allowedDirectories.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const [path, hash] of next.hashes) {\n\t\t\tstate.hashes.set(path, hash);\n\t\t}\n\t\tfor (const path of next.allowedDirectories) {\n\t\t\tstate.allowedDirectories.add(path);\n\t\t}\n\t\tthis.#compare(previousHashes, previousDirectories, state.hashes, state.allowedDirectories, changes);\n\t}\n\n\t#scanAffected(target: ResolvedWatchTarget, affected: Set<string>, state: TargetState): ScanResult {\n\t\tconst result: ScanResult = { hashes: new Map(), allowedDirectories: new Set() };\n\t\tfor (const relPath of affected) {\n\t\t\tconst absolutePath = join(target.path, relPath);\n\t\t\tthis.#scanPath(target, absolutePath, relPath, result, state);\n\t\t}\n\t\treturn result;\n\t}\n\n\t#scan(target: ResolvedWatchTarget): ScanResult {\n\t\tconst result: ScanResult = { hashes: new Map(), allowedDirectories: new Set() };\n\t\tthis.#scanPath(target, target.path, \"\", result);\n\t\treturn result;\n\t}\n\n\t#scanPath(\n\t\ttarget: ResolvedWatchTarget,\n\t\tabsolutePath: string,\n\t\trelPath: string,\n\t\tresult: ScanResult,\n\t\tstate?: TargetState,\n\t): void {\n\t\tif (relPath && !this.#matches(target, relPath)) {\n\t\t\treturn;\n\t\t}\n\t\tlet entry: Stats;\n\t\ttry {\n\t\t\tentry = lstatSync(absolutePath);\n\t\t} catch (error) {\n\t\t\tif (state && !isMissing(error)) {\n\t\t\t\tthis.#reportError(error, absolutePath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (entry.isSymbolicLink()) {\n\t\t\treturn;\n\t\t}\n\t\tif (entry.isFile()) {\n\t\t\ttry {\n\t\t\t\tresult.hashes.set(absolutePath, this.#hashFile(absolutePath));\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, absolutePath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!entry.isDirectory()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst dotDirectory = relPath !== \"\" && basename(relPath).startsWith(\".\");\n\t\tconst explicitlyAllowedDirectory = relPath !== \"\" && this.#isExplicitlyAllowedDirectory(target, relPath);\n\t\tif (explicitlyAllowedDirectory) {\n\t\t\tresult.allowedDirectories.add(absolutePath);\n\t\t}\n\t\tif (relPath && target.kind === \"dir\") {\n\t\t\treturn;\n\t\t}\n\t\tif (dotDirectory && !explicitlyAllowedDirectory) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tfor (const child of readdirSync(absolutePath, { withFileTypes: true })) {\n\t\t\t\tif (child.isSymbolicLink() || child.name === \"node_modules\" || child.name === \".git\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst childRelPath = relPath ? join(relPath, child.name) : child.name;\n\t\t\t\tif (\n\t\t\t\t\tchild.isDirectory() &&\n\t\t\t\t\tchild.name.startsWith(\".\") &&\n\t\t\t\t\t!this.#isExplicitlyAllowedDirectory(target, childRelPath)\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.#scanPath(target, join(absolutePath, child.name), childRelPath, result, state);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.#reportError(error, absolutePath);\n\t\t}\n\t}\n\n\t#compare(\n\t\tpreviousHashes: ReadonlyMap<string, string>,\n\t\tpreviousDirectories: ReadonlySet<string>,\n\t\tnextHashes: ReadonlyMap<string, string>,\n\t\tnextDirectories: ReadonlySet<string>,\n\t\tchanges: Map<string, { created: boolean; deleted: boolean }>,\n\t): void {\n\t\tfor (const [path, hash] of nextHashes) {\n\t\t\tconst oldHash = previousHashes.get(path);\n\t\t\tif (oldHash !== hash) {\n\t\t\t\tchanges.set(path, { created: oldHash === undefined, deleted: false });\n\t\t\t}\n\t\t}\n\t\tfor (const path of previousHashes.keys()) {\n\t\t\tif (!nextHashes.has(path)) {\n\t\t\t\tchanges.set(path, { created: false, deleted: true });\n\t\t\t}\n\t\t}\n\t\tfor (const path of nextDirectories) {\n\t\t\tif (!previousDirectories.has(path)) {\n\t\t\t\tchanges.set(path, { created: true, deleted: false });\n\t\t\t}\n\t\t}\n\t\tfor (const path of previousDirectories) {\n\t\t\tif (!nextDirectories.has(path)) {\n\t\t\t\tchanges.set(path, { created: false, deleted: true });\n\t\t\t}\n\t\t}\n\t}\n\n\t#matches(target: ResolvedWatchTarget, relPath: string): boolean {\n\t\tif (!target.kind.includes(\"recursive\") && relPath.includes(sep)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (\n\t\t\ttarget.allowList &&\n\t\t\t!target.allowList.some((allowed) => relPath === allowed || relPath.startsWith(`${allowed}${sep}`))\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn target.filter?.(relPath) ?? true;\n\t}\n\n\t#isExplicitlyAllowedDirectory(target: ResolvedWatchTarget, relPath: string): boolean {\n\t\treturn (\n\t\t\ttarget.allowList?.some((allowed) => relPath === allowed || relPath.startsWith(`${allowed}${sep}`)) ?? false\n\t\t);\n\t}\n\n\t#reportError(error: unknown, path: string): void {\n\t\ttry {\n\t\t\tthis.#onError(error, path);\n\t\t} catch {\n\t\t\t// Error reporting must not take down the watcher.\n\t\t}\n\t}\n}\n\nfunction hashFile(path: string): string {\n\treturn createHash(\"sha256\").update(readFileSync(path)).digest(\"hex\");\n}\n\nfunction normalizeRelativePath(filename: string): string | undefined {\n\tif (isAbsolute(filename)) {\n\t\treturn undefined;\n\t}\n\tconst normalized = normalize(filename);\n\treturn normalized === \".\" || normalized === \"..\" || normalized.startsWith(`..${sep}`) ? undefined : normalized;\n}\n\nfunction isWithin(path: string, prefix: string): boolean {\n\treturn path === prefix || path.startsWith(`${prefix}${sep}`);\n}\n\nfunction isMissing(error: unknown): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { WatchEventSource } from "./watch-engine.ts";
|
|
2
|
+
export interface RecursiveWatchWorker {
|
|
3
|
+
on(event: "message", listener: (message: unknown) => void): this;
|
|
4
|
+
on(event: "error", listener: (error: Error) => void): this;
|
|
5
|
+
postMessage(message: unknown): void;
|
|
6
|
+
terminate(): Promise<number>;
|
|
7
|
+
}
|
|
8
|
+
export type RecursiveWatchWorkerFactory = () => RecursiveWatchWorker;
|
|
9
|
+
export type FsWatchEventSourceOptions = {
|
|
10
|
+
readonly platform?: NodeJS.Platform;
|
|
11
|
+
readonly createRecursiveWorker?: RecursiveWatchWorkerFactory;
|
|
12
|
+
};
|
|
13
|
+
/** Production event source. Linux recursive setup runs off the interactive main thread. */
|
|
14
|
+
export declare function createFsWatchEventSource(onError?: (error: unknown, path: string) => void, options?: FsWatchEventSourceOptions): WatchEventSource;
|
|
15
|
+
//# sourceMappingURL=watch-event-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch-event-source.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-event-source.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE9E,MAAM,WAAW,oBAAoB;IACpC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACjE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3D,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,MAAM,2BAA2B,GAAG,MAAM,oBAAoB,CAAC;AAErE,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACpC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,2BAA2B,CAAC;CAC7D,CAAC;AAsEF,2FAA2F;AAC3F,wBAAgB,wBAAwB,CACvC,OAAO,GAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAe,EAC1D,OAAO,GAAE,yBAA8B,GACrC,gBAAgB,CAkDlB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Worker } from "node:worker_threads";
|
|
2
|
+
import { watchWithErrorHandler } from "../../../../utils/fs-watch.js";
|
|
3
|
+
const RECURSIVE_WATCH_WORKER_SOURCE = `
|
|
4
|
+
const { watch } = require("node:fs");
|
|
5
|
+
const { parentPort } = require("node:worker_threads");
|
|
6
|
+
|
|
7
|
+
if (!parentPort) throw new Error("Recursive watch worker requires a parent port");
|
|
8
|
+
|
|
9
|
+
const watchers = new Map();
|
|
10
|
+
parentPort.on("message", (message) => {
|
|
11
|
+
if (message.kind === "unwatch") {
|
|
12
|
+
watchers.get(message.id)?.close();
|
|
13
|
+
watchers.delete(message.id);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (message.kind !== "watch") return;
|
|
17
|
+
try {
|
|
18
|
+
const watcher = watch(
|
|
19
|
+
message.path,
|
|
20
|
+
{ recursive: true, encoding: "utf8" },
|
|
21
|
+
(eventType, filename) => {
|
|
22
|
+
parentPort.postMessage({
|
|
23
|
+
kind: "event",
|
|
24
|
+
id: message.id,
|
|
25
|
+
eventType,
|
|
26
|
+
filename: typeof filename === "string" ? filename : null,
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
watcher.on("error", (error) => {
|
|
31
|
+
parentPort.postMessage({
|
|
32
|
+
kind: "error",
|
|
33
|
+
id: message.id,
|
|
34
|
+
message: error instanceof Error ? error.message : String(error),
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
watchers.set(message.id, watcher);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
parentPort.postMessage({
|
|
40
|
+
kind: "error",
|
|
41
|
+
id: message.id,
|
|
42
|
+
message: error instanceof Error ? error.message : String(error),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
`;
|
|
47
|
+
function createRecursiveWatchWorker() {
|
|
48
|
+
return new Worker(RECURSIVE_WATCH_WORKER_SOURCE, {
|
|
49
|
+
eval: true,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function isRecursiveWatchMessage(message) {
|
|
53
|
+
if (typeof message !== "object" || message === null || !("kind" in message))
|
|
54
|
+
return false;
|
|
55
|
+
if (!("id" in message) || typeof message.id !== "number")
|
|
56
|
+
return false;
|
|
57
|
+
if (message.kind === "error")
|
|
58
|
+
return "message" in message && typeof message.message === "string";
|
|
59
|
+
return (message.kind === "event" &&
|
|
60
|
+
"eventType" in message &&
|
|
61
|
+
typeof message.eventType === "string" &&
|
|
62
|
+
"filename" in message &&
|
|
63
|
+
(message.filename === null || typeof message.filename === "string"));
|
|
64
|
+
}
|
|
65
|
+
/** Production event source. Linux recursive setup runs off the interactive main thread. */
|
|
66
|
+
export function createFsWatchEventSource(onError = () => { }, options = {}) {
|
|
67
|
+
const recursiveSubscriptions = new Map();
|
|
68
|
+
let recursiveWorker;
|
|
69
|
+
let nextSubscriptionId = 1;
|
|
70
|
+
const ensureRecursiveWorker = () => {
|
|
71
|
+
if (recursiveWorker)
|
|
72
|
+
return recursiveWorker;
|
|
73
|
+
const worker = (options.createRecursiveWorker ?? createRecursiveWatchWorker)();
|
|
74
|
+
worker.on("message", (message) => {
|
|
75
|
+
if (!isRecursiveWatchMessage(message))
|
|
76
|
+
return;
|
|
77
|
+
const subscription = recursiveSubscriptions.get(message.id);
|
|
78
|
+
if (!subscription)
|
|
79
|
+
return;
|
|
80
|
+
if (message.kind === "event") {
|
|
81
|
+
subscription.listener(message.eventType, message.filename);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
onError(new Error(message.message), subscription.path);
|
|
85
|
+
});
|
|
86
|
+
worker.on("error", (error) => {
|
|
87
|
+
for (const subscription of recursiveSubscriptions.values())
|
|
88
|
+
onError(error, subscription.path);
|
|
89
|
+
});
|
|
90
|
+
recursiveWorker = worker;
|
|
91
|
+
return worker;
|
|
92
|
+
};
|
|
93
|
+
return (path, listener, watchOptions) => {
|
|
94
|
+
if ((options.platform ?? process.platform) === "linux" && watchOptions?.recursive) {
|
|
95
|
+
const id = nextSubscriptionId++;
|
|
96
|
+
const worker = ensureRecursiveWorker();
|
|
97
|
+
recursiveSubscriptions.set(id, { path, listener });
|
|
98
|
+
worker.postMessage({ kind: "watch", id, path });
|
|
99
|
+
return () => {
|
|
100
|
+
if (!recursiveSubscriptions.delete(id))
|
|
101
|
+
return;
|
|
102
|
+
if (recursiveSubscriptions.size > 0) {
|
|
103
|
+
worker.postMessage({ kind: "unwatch", id });
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
recursiveWorker = undefined;
|
|
107
|
+
void worker.terminate().catch((error) => onError(error, path));
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const watcher = watchWithErrorHandler(path, listener, () => onError(new Error(`fs.watch failed for ${path}`), path), { recursive: watchOptions?.recursive ?? false });
|
|
111
|
+
return () => watcher?.close();
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=watch-event-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch-event-source.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-event-source.ts"],"names":[],"mappings":"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","sourcesContent":["import { Worker } from \"node:worker_threads\";\nimport { watchWithErrorHandler } from \"../../../../utils/fs-watch.ts\";\nimport type { WatchEventListener, WatchEventSource } from \"./watch-engine.ts\";\n\nexport interface RecursiveWatchWorker {\n\ton(event: \"message\", listener: (message: unknown) => void): this;\n\ton(event: \"error\", listener: (error: Error) => void): this;\n\tpostMessage(message: unknown): void;\n\tterminate(): Promise<number>;\n}\n\nexport type RecursiveWatchWorkerFactory = () => RecursiveWatchWorker;\n\nexport type FsWatchEventSourceOptions = {\n\treadonly platform?: NodeJS.Platform;\n\treadonly createRecursiveWorker?: RecursiveWatchWorkerFactory;\n};\n\ntype RecursiveWatchMessage =\n\t| { readonly kind: \"event\"; readonly id: number; readonly eventType: string; readonly filename: string | null }\n\t| { readonly kind: \"error\"; readonly id: number; readonly message: string };\n\nconst RECURSIVE_WATCH_WORKER_SOURCE = `\nconst { watch } = require(\"node:fs\");\nconst { parentPort } = require(\"node:worker_threads\");\n\nif (!parentPort) throw new Error(\"Recursive watch worker requires a parent port\");\n\nconst watchers = new Map();\nparentPort.on(\"message\", (message) => {\n\tif (message.kind === \"unwatch\") {\n\t\twatchers.get(message.id)?.close();\n\t\twatchers.delete(message.id);\n\t\treturn;\n\t}\n\tif (message.kind !== \"watch\") return;\n\ttry {\n\t\tconst watcher = watch(\n\t\t\tmessage.path,\n\t\t\t{ recursive: true, encoding: \"utf8\" },\n\t\t\t(eventType, filename) => {\n\t\t\t\tparentPort.postMessage({\n\t\t\t\t\tkind: \"event\",\n\t\t\t\t\tid: message.id,\n\t\t\t\t\teventType,\n\t\t\t\t\tfilename: typeof filename === \"string\" ? filename : null,\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t\twatcher.on(\"error\", (error) => {\n\t\t\tparentPort.postMessage({\n\t\t\t\tkind: \"error\",\n\t\t\t\tid: message.id,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t});\n\t\t});\n\t\twatchers.set(message.id, watcher);\n\t} catch (error) {\n\t\tparentPort.postMessage({\n\t\t\tkind: \"error\",\n\t\t\tid: message.id,\n\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t});\n\t}\n});\n`;\n\nfunction createRecursiveWatchWorker(): RecursiveWatchWorker {\n\treturn new Worker(RECURSIVE_WATCH_WORKER_SOURCE, {\n\t\teval: true,\n\t});\n}\n\nfunction isRecursiveWatchMessage(message: unknown): message is RecursiveWatchMessage {\n\tif (typeof message !== \"object\" || message === null || !(\"kind\" in message)) return false;\n\tif (!(\"id\" in message) || typeof message.id !== \"number\") return false;\n\tif (message.kind === \"error\") return \"message\" in message && typeof message.message === \"string\";\n\treturn (\n\t\tmessage.kind === \"event\" &&\n\t\t\"eventType\" in message &&\n\t\ttypeof message.eventType === \"string\" &&\n\t\t\"filename\" in message &&\n\t\t(message.filename === null || typeof message.filename === \"string\")\n\t);\n}\n\n/** Production event source. Linux recursive setup runs off the interactive main thread. */\nexport function createFsWatchEventSource(\n\tonError: (error: unknown, path: string) => void = () => {},\n\toptions: FsWatchEventSourceOptions = {},\n): WatchEventSource {\n\tconst recursiveSubscriptions = new Map<number, { readonly path: string; readonly listener: WatchEventListener }>();\n\tlet recursiveWorker: RecursiveWatchWorker | undefined;\n\tlet nextSubscriptionId = 1;\n\n\tconst ensureRecursiveWorker = (): RecursiveWatchWorker => {\n\t\tif (recursiveWorker) return recursiveWorker;\n\t\tconst worker = (options.createRecursiveWorker ?? createRecursiveWatchWorker)();\n\t\tworker.on(\"message\", (message) => {\n\t\t\tif (!isRecursiveWatchMessage(message)) return;\n\t\t\tconst subscription = recursiveSubscriptions.get(message.id);\n\t\t\tif (!subscription) return;\n\t\t\tif (message.kind === \"event\") {\n\t\t\t\tsubscription.listener(message.eventType, message.filename);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tonError(new Error(message.message), subscription.path);\n\t\t});\n\t\tworker.on(\"error\", (error) => {\n\t\t\tfor (const subscription of recursiveSubscriptions.values()) onError(error, subscription.path);\n\t\t});\n\t\trecursiveWorker = worker;\n\t\treturn worker;\n\t};\n\n\treturn (path, listener, watchOptions) => {\n\t\tif ((options.platform ?? process.platform) === \"linux\" && watchOptions?.recursive) {\n\t\t\tconst id = nextSubscriptionId++;\n\t\t\tconst worker = ensureRecursiveWorker();\n\t\t\trecursiveSubscriptions.set(id, { path, listener });\n\t\t\tworker.postMessage({ kind: \"watch\", id, path });\n\t\t\treturn () => {\n\t\t\t\tif (!recursiveSubscriptions.delete(id)) return;\n\t\t\t\tif (recursiveSubscriptions.size > 0) {\n\t\t\t\t\tworker.postMessage({ kind: \"unwatch\", id });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\trecursiveWorker = undefined;\n\t\t\t\tvoid worker.terminate().catch((error: unknown) => onError(error, path));\n\t\t\t};\n\t\t}\n\n\t\tconst watcher = watchWithErrorHandler(\n\t\t\tpath,\n\t\t\tlistener,\n\t\t\t() => onError(new Error(`fs.watch failed for ${path}`), path),\n\t\t\t{ recursive: watchOptions?.recursive ?? false },\n\t\t);\n\t\treturn () => watcher?.close();\n\t};\n}\n"]}
|
|
@@ -44,5 +44,7 @@ export declare function hashAssistantText(text: string): string;
|
|
|
44
44
|
* Deliberately excludes goal.updatedAt because usage accounting updates it after every agent turn.
|
|
45
45
|
*/
|
|
46
46
|
export declare function buildGoalContinuationSignature(goal: Pick<Goal, "id">, openTodos: number, totalTodos: number, lastAssistantTextHash: string): string;
|
|
47
|
+
export declare function hasGoalContinuationProgress(input: Pick<GoalContinuationInput, "lastContinuationSignature" | "currentSignature">): boolean;
|
|
48
|
+
export declare function continuationTurnUsedTools(messages: readonly AgentMessage[]): boolean;
|
|
47
49
|
export {};
|
|
48
50
|
//# sourceMappingURL=continuation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"continuation.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/continuation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,KAAK,qBAAqB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC;AAG1E,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAC/C,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,gBAAgB,GAAG,WAAW,GAAG,cAAc,CAAC;AAEjG,MAAM,MAAM,qBAAqB,GAAG;IACnC,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,qBAAqB,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACzE,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,yBAAyB,EAAE,MAAM,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,4BAA4B,EAAE,SAAS,MAAM,EAAE,CAAC;IACzD,QAAQ,CAAC,0BAA0B,EAAE,MAAM,CAAC;IAC5C,QAAQ,CAAC,yBAAyB,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAChC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GACtE;IACA,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,GAAG,eAAe,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,YAAY,GAAG,kBAAkB,CAAC;CACxG,CAAC;AAEL,wBAAgB,mCAAmC,CAClD,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,MAAM,EAAE,OAAO,EACf,kBAAkB,EAAE,OAAO,GACzB,IAAI,IAAI,IAAI,CAEd;AAED,wBAAgB,wCAAwC,CACvD,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,kBAAkB,EAAE,OAAO,EAC3B,QAAQ,EAAE,SAAS,YAAY,EAAE,GAC/B,IAAI,IAAI,IAAI,CAEd;AAmCD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,qBAAqB,GAAG,uBAAuB,CAuB9F;AAED,yFAAyF;AACzF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQtD;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC7C,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EACtB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,qBAAqB,EAAE,MAAM,GAC3B,MAAM,CAER"}
|
|
1
|
+
{"version":3,"file":"continuation.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/continuation.ts"],"names":[],"mappings":"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"}
|
|
@@ -86,6 +86,18 @@ export function hashAssistantText(text) {
|
|
|
86
86
|
export function buildGoalContinuationSignature(goal, openTodos, totalTodos, lastAssistantTextHash) {
|
|
87
87
|
return `${goal.id}:${openTodos}/${totalTodos}:${lastAssistantTextHash}`;
|
|
88
88
|
}
|
|
89
|
+
export function hasGoalContinuationProgress(input) {
|
|
90
|
+
return (input.lastContinuationSignature !== undefined &&
|
|
91
|
+
input.currentSignature !== undefined &&
|
|
92
|
+
input.lastContinuationSignature !== input.currentSignature);
|
|
93
|
+
}
|
|
94
|
+
export function continuationTurnUsedTools(messages) {
|
|
95
|
+
return messages.some((message) => {
|
|
96
|
+
if (message?.role === "toolResult")
|
|
97
|
+
return true;
|
|
98
|
+
return message?.role === "assistant" && message.content.some((content) => content.type === "toolCall");
|
|
99
|
+
});
|
|
100
|
+
}
|
|
89
101
|
function isEligibleForGoalContinuation(input) {
|
|
90
102
|
if (input.goal?.status !== "active" || input.hasPendingMessages)
|
|
91
103
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"continuation.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/continuation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Goal } from \"./types.ts\";\n\ntype AssistantAgentMessage = Extract<AgentMessage, { role: \"assistant\" }>;\ntype ToolResultAgentMessage = Extract<AgentMessage, { role: \"toolResult\" }>;\n\nexport const GOAL_CONTINUATION_CAP = 8;\nexport const GOAL_STALL_TOOLLESS_THRESHOLD = 3;\nexport const GOAL_REPETITION_HASH_STREAK = 3;\nexport const GOAL_LENGTH_RECOVERY_LIMIT = 1;\nexport const GOAL_USER_GRACE_DELAY_MS = 60_000;\n\nexport type GoalContinuationPath = \"immediate\" | \"monitorDelayed\" | \"userGrace\" | \"sessionStart\";\n\nexport type GoalContinuationInput = {\n\treadonly goal: Goal | null;\n\treadonly isIdle: boolean;\n\treadonly hasPendingMessages: boolean;\n\treadonly path: GoalContinuationPath;\n\treadonly lastStopReason: AssistantAgentMessage[\"stopReason\"] | undefined;\n\treadonly consecutiveContinuations: number;\n\treadonly lastContinuationSignature: string | undefined;\n\treadonly currentSignature: string | undefined;\n\treadonly consecutiveLengthRecoveries: number;\n\treadonly recentNormalizedOutputHashes: readonly string[];\n\treadonly toollessContinuationStreak: number;\n\treadonly endedTurnWasUserInitiated: boolean;\n\treadonly continuationPending: boolean;\n};\n\nexport type GoalContinuationVerdict =\n\t| { kind: \"continue\"; prompt: \"full\" | \"minimal\"; stallNotice: boolean }\n\t| {\n\t\t\tkind: \"deny\";\n\t\t\treason: \"not-eligible\" | \"single-flight\" | \"cap\" | \"stale\" | \"grace\" | \"repetition\" | \"length-exhausted\";\n\t };\n\nexport function shouldQueueGoalContinuationWhenIdle(\n\tgoal: Goal | null,\n\tisIdle: boolean,\n\thasPendingMessages: boolean,\n): goal is Goal {\n\treturn goal?.status === \"active\" && isIdle && !hasPendingMessages;\n}\n\nexport function shouldQueueGoalContinuationAfterAgentEnd(\n\tgoal: Goal | null,\n\thasPendingMessages: boolean,\n\tmessages: readonly AgentMessage[],\n): goal is Goal {\n\treturn goal?.status === \"active\" && !hasPendingMessages && didAgentEndCleanly(messages);\n}\n\nfunction didAgentEndCleanly(messages: readonly AgentMessage[]): boolean {\n\tconst lastAssistantIndex = findLastAssistantMessageIndex(messages);\n\tif (lastAssistantIndex === undefined) return false;\n\n\tconst lastAssistant = messages[lastAssistantIndex];\n\tif (lastAssistant?.role !== \"assistant\" || !isContinuableStopReason(lastAssistant.stopReason)) return false;\n\n\tfor (let index = lastAssistantIndex + 1; index < messages.length; index++) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"toolResult\" && isAbortedToolResult(message)) return false;\n\t}\n\treturn true;\n}\n\nfunction findLastAssistantMessageIndex(messages: readonly AgentMessage[]): number | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") {\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction isContinuableStopReason(stopReason: AssistantAgentMessage[\"stopReason\"]): boolean {\n\treturn stopReason === \"stop\" || stopReason === \"length\";\n}\n\nfunction isAbortedToolResult(message: ToolResultAgentMessage): boolean {\n\tif (!message.isError) return false;\n\treturn message.content.some((content) => content.type === \"text\" && /\\babort(?:ed)?\\b/i.test(content.text));\n}\n\nexport function evaluateGoalContinuation(input: GoalContinuationInput): GoalContinuationVerdict {\n\tif (!isEligibleForGoalContinuation(input)) return { kind: \"deny\", reason: \"not-eligible\" };\n\tif (input.continuationPending) return { kind: \"deny\", reason: \"single-flight\" };\n\tif (hasRepeatedNormalizedOutputHash(input.recentNormalizedOutputHashes))\n\t\treturn { kind: \"deny\", reason: \"repetition\" };\n\tif (isContinuationCapPath(input.path) && input.consecutiveContinuations >= GOAL_CONTINUATION_CAP) {\n\t\treturn { kind: \"deny\", reason: \"cap\" };\n\t}\n\tif (\n\t\t(input.path === \"immediate\" || input.path === \"userGrace\") &&\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.lastContinuationSignature === input.currentSignature\n\t) {\n\t\treturn { kind: \"deny\", reason: \"stale\" };\n\t}\n\tif (input.path === \"immediate\" && input.endedTurnWasUserInitiated) return { kind: \"deny\", reason: \"grace\" };\n\tif (input.lastStopReason === \"length\") {\n\t\tif (input.consecutiveLengthRecoveries >= GOAL_LENGTH_RECOVERY_LIMIT) {\n\t\t\treturn { kind: \"deny\", reason: \"length-exhausted\" };\n\t\t}\n\t\treturn { kind: \"continue\", prompt: \"minimal\", stallNotice: shouldShowStallNotice(input) };\n\t}\n\treturn { kind: \"continue\", prompt: \"full\", stallNotice: shouldShowStallNotice(input) };\n}\n\n/** Produces a stable, whitespace-insensitive representation for repetition detection. */\nexport function normalizeAssistantText(text: string): string {\n\treturn text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\n/** Hashes normalized assistant text with the deterministic 32-bit FNV-1a algorithm. */\nexport function hashAssistantText(text: string): string {\n\tconst normalized = normalizeAssistantText(text);\n\tlet hash = 0x811c9dc5;\n\tfor (let index = 0; index < normalized.length; index++) {\n\t\thash ^= normalized.charCodeAt(index);\n\t\thash = Math.imul(hash, 0x01000193);\n\t}\n\treturn (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Identifies the observable goal progress for stale-continuation admission.\n * Deliberately excludes goal.updatedAt because usage accounting updates it after every agent turn.\n */\nexport function buildGoalContinuationSignature(\n\tgoal: Pick<Goal, \"id\">,\n\topenTodos: number,\n\ttotalTodos: number,\n\tlastAssistantTextHash: string,\n): string {\n\treturn `${goal.id}:${openTodos}/${totalTodos}:${lastAssistantTextHash}`;\n}\n\nfunction isEligibleForGoalContinuation(input: GoalContinuationInput): boolean {\n\tif (input.goal?.status !== \"active\" || input.hasPendingMessages) return false;\n\tif (input.path === \"immediate\") {\n\t\treturn input.lastStopReason !== undefined && isContinuableStopReason(input.lastStopReason);\n\t}\n\treturn input.isIdle;\n}\n\nfunction isContinuationCapPath(path: GoalContinuationPath): boolean {\n\treturn path === \"immediate\" || path === \"userGrace\" || path === \"sessionStart\";\n}\n\nfunction hasRepeatedNormalizedOutputHash(hashes: readonly string[]): boolean {\n\tconst latestHash = hashes.at(-1);\n\tif (latestHash === undefined) return false;\n\n\tlet streak = 0;\n\tfor (let index = hashes.length - 1; index >= 0 && hashes[index] === latestHash; index--) {\n\t\tstreak += 1;\n\t}\n\treturn streak >= GOAL_REPETITION_HASH_STREAK;\n}\n\nfunction shouldShowStallNotice(input: GoalContinuationInput): boolean {\n\treturn input.toollessContinuationStreak >= GOAL_STALL_TOOLLESS_THRESHOLD;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"continuation.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/continuation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Goal } from \"./types.ts\";\n\ntype AssistantAgentMessage = Extract<AgentMessage, { role: \"assistant\" }>;\ntype ToolResultAgentMessage = Extract<AgentMessage, { role: \"toolResult\" }>;\n\nexport const GOAL_CONTINUATION_CAP = 8;\nexport const GOAL_STALL_TOOLLESS_THRESHOLD = 3;\nexport const GOAL_REPETITION_HASH_STREAK = 3;\nexport const GOAL_LENGTH_RECOVERY_LIMIT = 1;\nexport const GOAL_USER_GRACE_DELAY_MS = 60_000;\n\nexport type GoalContinuationPath = \"immediate\" | \"monitorDelayed\" | \"userGrace\" | \"sessionStart\";\n\nexport type GoalContinuationInput = {\n\treadonly goal: Goal | null;\n\treadonly isIdle: boolean;\n\treadonly hasPendingMessages: boolean;\n\treadonly path: GoalContinuationPath;\n\treadonly lastStopReason: AssistantAgentMessage[\"stopReason\"] | undefined;\n\treadonly consecutiveContinuations: number;\n\treadonly lastContinuationSignature: string | undefined;\n\treadonly currentSignature: string | undefined;\n\treadonly consecutiveLengthRecoveries: number;\n\treadonly recentNormalizedOutputHashes: readonly string[];\n\treadonly toollessContinuationStreak: number;\n\treadonly endedTurnWasUserInitiated: boolean;\n\treadonly continuationPending: boolean;\n};\n\nexport type GoalContinuationVerdict =\n\t| { kind: \"continue\"; prompt: \"full\" | \"minimal\"; stallNotice: boolean }\n\t| {\n\t\t\tkind: \"deny\";\n\t\t\treason: \"not-eligible\" | \"single-flight\" | \"cap\" | \"stale\" | \"grace\" | \"repetition\" | \"length-exhausted\";\n\t };\n\nexport function shouldQueueGoalContinuationWhenIdle(\n\tgoal: Goal | null,\n\tisIdle: boolean,\n\thasPendingMessages: boolean,\n): goal is Goal {\n\treturn goal?.status === \"active\" && isIdle && !hasPendingMessages;\n}\n\nexport function shouldQueueGoalContinuationAfterAgentEnd(\n\tgoal: Goal | null,\n\thasPendingMessages: boolean,\n\tmessages: readonly AgentMessage[],\n): goal is Goal {\n\treturn goal?.status === \"active\" && !hasPendingMessages && didAgentEndCleanly(messages);\n}\n\nfunction didAgentEndCleanly(messages: readonly AgentMessage[]): boolean {\n\tconst lastAssistantIndex = findLastAssistantMessageIndex(messages);\n\tif (lastAssistantIndex === undefined) return false;\n\n\tconst lastAssistant = messages[lastAssistantIndex];\n\tif (lastAssistant?.role !== \"assistant\" || !isContinuableStopReason(lastAssistant.stopReason)) return false;\n\n\tfor (let index = lastAssistantIndex + 1; index < messages.length; index++) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"toolResult\" && isAbortedToolResult(message)) return false;\n\t}\n\treturn true;\n}\n\nfunction findLastAssistantMessageIndex(messages: readonly AgentMessage[]): number | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") {\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction isContinuableStopReason(stopReason: AssistantAgentMessage[\"stopReason\"]): boolean {\n\treturn stopReason === \"stop\" || stopReason === \"length\";\n}\n\nfunction isAbortedToolResult(message: ToolResultAgentMessage): boolean {\n\tif (!message.isError) return false;\n\treturn message.content.some((content) => content.type === \"text\" && /\\babort(?:ed)?\\b/i.test(content.text));\n}\n\nexport function evaluateGoalContinuation(input: GoalContinuationInput): GoalContinuationVerdict {\n\tif (!isEligibleForGoalContinuation(input)) return { kind: \"deny\", reason: \"not-eligible\" };\n\tif (input.continuationPending) return { kind: \"deny\", reason: \"single-flight\" };\n\tif (hasRepeatedNormalizedOutputHash(input.recentNormalizedOutputHashes))\n\t\treturn { kind: \"deny\", reason: \"repetition\" };\n\tif (isContinuationCapPath(input.path) && input.consecutiveContinuations >= GOAL_CONTINUATION_CAP) {\n\t\treturn { kind: \"deny\", reason: \"cap\" };\n\t}\n\tif (\n\t\t(input.path === \"immediate\" || input.path === \"userGrace\") &&\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.lastContinuationSignature === input.currentSignature\n\t) {\n\t\treturn { kind: \"deny\", reason: \"stale\" };\n\t}\n\tif (input.path === \"immediate\" && input.endedTurnWasUserInitiated) return { kind: \"deny\", reason: \"grace\" };\n\tif (input.lastStopReason === \"length\") {\n\t\tif (input.consecutiveLengthRecoveries >= GOAL_LENGTH_RECOVERY_LIMIT) {\n\t\t\treturn { kind: \"deny\", reason: \"length-exhausted\" };\n\t\t}\n\t\treturn { kind: \"continue\", prompt: \"minimal\", stallNotice: shouldShowStallNotice(input) };\n\t}\n\treturn { kind: \"continue\", prompt: \"full\", stallNotice: shouldShowStallNotice(input) };\n}\n\n/** Produces a stable, whitespace-insensitive representation for repetition detection. */\nexport function normalizeAssistantText(text: string): string {\n\treturn text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\n/** Hashes normalized assistant text with the deterministic 32-bit FNV-1a algorithm. */\nexport function hashAssistantText(text: string): string {\n\tconst normalized = normalizeAssistantText(text);\n\tlet hash = 0x811c9dc5;\n\tfor (let index = 0; index < normalized.length; index++) {\n\t\thash ^= normalized.charCodeAt(index);\n\t\thash = Math.imul(hash, 0x01000193);\n\t}\n\treturn (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Identifies the observable goal progress for stale-continuation admission.\n * Deliberately excludes goal.updatedAt because usage accounting updates it after every agent turn.\n */\nexport function buildGoalContinuationSignature(\n\tgoal: Pick<Goal, \"id\">,\n\topenTodos: number,\n\ttotalTodos: number,\n\tlastAssistantTextHash: string,\n): string {\n\treturn `${goal.id}:${openTodos}/${totalTodos}:${lastAssistantTextHash}`;\n}\n\nexport function hasGoalContinuationProgress(\n\tinput: Pick<GoalContinuationInput, \"lastContinuationSignature\" | \"currentSignature\">,\n): boolean {\n\treturn (\n\t\tinput.lastContinuationSignature !== undefined &&\n\t\tinput.currentSignature !== undefined &&\n\t\tinput.lastContinuationSignature !== input.currentSignature\n\t);\n}\n\nexport function continuationTurnUsedTools(messages: readonly AgentMessage[]): boolean {\n\treturn messages.some((message) => {\n\t\tif (message?.role === \"toolResult\") return true;\n\t\treturn message?.role === \"assistant\" && message.content.some((content) => content.type === \"toolCall\");\n\t});\n}\n\nfunction isEligibleForGoalContinuation(input: GoalContinuationInput): boolean {\n\tif (input.goal?.status !== \"active\" || input.hasPendingMessages) return false;\n\tif (input.path === \"immediate\") {\n\t\treturn input.lastStopReason !== undefined && isContinuableStopReason(input.lastStopReason);\n\t}\n\treturn input.isIdle;\n}\n\nfunction isContinuationCapPath(path: GoalContinuationPath): boolean {\n\treturn path === \"immediate\" || path === \"userGrace\" || path === \"sessionStart\";\n}\n\nfunction hasRepeatedNormalizedOutputHash(hashes: readonly string[]): boolean {\n\tconst latestHash = hashes.at(-1);\n\tif (latestHash === undefined) return false;\n\n\tlet streak = 0;\n\tfor (let index = hashes.length - 1; index >= 0 && hashes[index] === latestHash; index--) {\n\t\tstreak += 1;\n\t}\n\treturn streak >= GOAL_REPETITION_HASH_STREAK;\n}\n\nfunction shouldShowStallNotice(input: GoalContinuationInput): boolean {\n\treturn input.toollessContinuationStreak >= GOAL_STALL_TOOLLESS_THRESHOLD;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AA0BpF,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AA0BpF,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA8T5D"}
|
|
@@ -43,7 +43,10 @@ export default function goalExtension(pi) {
|
|
|
43
43
|
registerGoalTools(pi, {
|
|
44
44
|
goalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),
|
|
45
45
|
accountCurrentAgentTurn,
|
|
46
|
-
beginAgentGoalAccounting
|
|
46
|
+
beginAgentGoalAccounting: (goal) => {
|
|
47
|
+
monitorContinuation.noteContinuationStarted();
|
|
48
|
+
beginAgentGoalAccounting(goal);
|
|
49
|
+
},
|
|
47
50
|
markGoalBlockedThisTurn,
|
|
48
51
|
markGoalCompletedThisTurn,
|
|
49
52
|
refreshGoalUi,
|