@prestyj/cli 5.10.0 → 5.12.0
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/README.md +3 -4
- package/assets/skills/compliance-guard/SKILL.md +251 -0
- package/assets/skills/compliance-guard/references/artifacts.md +186 -0
- package/assets/skills/compliance-guard/references/eu-uk.md +151 -0
- package/assets/skills/compliance-guard/references/exposure-triage.md +161 -0
- package/assets/skills/compliance-guard/references/lawsuit-vectors.md +141 -0
- package/assets/skills/compliance-guard/references/provenance.md +42 -0
- package/assets/skills/compliance-guard/references/sector-gates.md +173 -0
- package/assets/skills/compliance-guard/references/security-baseline.md +130 -0
- package/assets/skills/compliance-guard/references/trigger-map.md +163 -0
- package/assets/skills/compliance-guard/references/us.md +164 -0
- package/dist/app-sidecar-auth-broadcast.test.d.ts +2 -0
- package/dist/app-sidecar-auth-broadcast.test.d.ts.map +1 -0
- package/dist/app-sidecar-auth-broadcast.test.js +348 -0
- package/dist/app-sidecar-auth-broadcast.test.js.map +1 -0
- package/dist/app-sidecar-sessions.d.ts +5 -2
- package/dist/app-sidecar-sessions.d.ts.map +1 -1
- package/dist/app-sidecar-sessions.js +34 -8
- package/dist/app-sidecar-sessions.js.map +1 -1
- package/dist/app-sidecar-sessions.test.js +96 -1
- package/dist/app-sidecar-sessions.test.js.map +1 -1
- package/dist/app-sidecar.js +616 -173
- package/dist/app-sidecar.js.map +1 -1
- package/dist/chat-agents/jiwa.test.js +1 -1
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +33 -36
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/command-routing.d.ts +1 -1
- package/dist/cli/command-routing.d.ts.map +1 -1
- package/dist/cli/command-routing.js +1 -0
- package/dist/cli/command-routing.js.map +1 -1
- package/dist/cli/command-routing.test.js +1 -0
- package/dist/cli/command-routing.test.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +179 -48
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +18 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +45 -76
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +30 -13
- package/dist/config.test.js.map +1 -1
- package/dist/core/agent-notifications.d.ts +62 -0
- package/dist/core/agent-notifications.d.ts.map +1 -0
- package/dist/core/agent-notifications.js +92 -0
- package/dist/core/agent-notifications.js.map +1 -0
- package/dist/core/agent-notifications.test.d.ts +2 -0
- package/dist/core/agent-notifications.test.d.ts.map +1 -0
- package/dist/core/agent-notifications.test.js +97 -0
- package/dist/core/agent-notifications.test.js.map +1 -0
- package/dist/core/agent-session-checkpoint-flush.test.d.ts +2 -0
- package/dist/core/agent-session-checkpoint-flush.test.d.ts.map +1 -0
- package/dist/core/agent-session-checkpoint-flush.test.js +201 -0
- package/dist/core/agent-session-checkpoint-flush.test.js.map +1 -0
- package/dist/core/agent-session-compaction.test.js +323 -6
- package/dist/core/agent-session-compaction.test.js.map +1 -1
- package/dist/core/agent-session-crash-durability.test.d.ts +2 -0
- package/dist/core/agent-session-crash-durability.test.d.ts.map +1 -0
- package/dist/core/agent-session-crash-durability.test.js +102 -0
- package/dist/core/agent-session-crash-durability.test.js.map +1 -0
- package/dist/core/agent-session-marker-anchors.test.js +181 -2
- package/dist/core/agent-session-marker-anchors.test.js.map +1 -1
- package/dist/core/agent-session-model-switch.test.d.ts +2 -0
- package/dist/core/agent-session-model-switch.test.d.ts.map +1 -0
- package/dist/core/agent-session-model-switch.test.js +161 -0
- package/dist/core/agent-session-model-switch.test.js.map +1 -0
- package/dist/core/agent-session-notifications.test.d.ts +2 -0
- package/dist/core/agent-session-notifications.test.d.ts.map +1 -0
- package/dist/core/agent-session-notifications.test.js +114 -0
- package/dist/core/agent-session-notifications.test.js.map +1 -0
- package/dist/core/agent-session-process-gate.test.d.ts +2 -0
- package/dist/core/agent-session-process-gate.test.d.ts.map +1 -0
- package/dist/core/agent-session-process-gate.test.js +98 -0
- package/dist/core/agent-session-process-gate.test.js.map +1 -0
- package/dist/core/agent-session-queue.test.js +65 -0
- package/dist/core/agent-session-queue.test.js.map +1 -1
- package/dist/core/agent-session-review-coverage.test.js +80 -23
- package/dist/core/agent-session-review-coverage.test.js.map +1 -1
- package/dist/core/agent-session-slash-restore.test.d.ts +2 -0
- package/dist/core/agent-session-slash-restore.test.d.ts.map +1 -0
- package/dist/core/agent-session-slash-restore.test.js +121 -0
- package/dist/core/agent-session-slash-restore.test.js.map +1 -0
- package/dist/core/agent-session-tool-tiers.test.d.ts +2 -0
- package/dist/core/agent-session-tool-tiers.test.d.ts.map +1 -0
- package/dist/core/agent-session-tool-tiers.test.js +138 -0
- package/dist/core/agent-session-tool-tiers.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +257 -13
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +1118 -241
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/agents.d.ts +29 -1
- package/dist/core/agents.d.ts.map +1 -1
- package/dist/core/agents.js +47 -97
- package/dist/core/agents.js.map +1 -1
- package/dist/core/agents.test.js +87 -7
- package/dist/core/agents.test.js.map +1 -1
- package/dist/core/api-benchmark.d.ts +3 -3
- package/dist/core/api-benchmark.js +7 -7
- package/dist/core/auth-providers.d.ts +37 -1
- package/dist/core/auth-providers.d.ts.map +1 -1
- package/dist/core/auth-providers.js +83 -3
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/auto-update.test.js +1 -1
- package/dist/core/autopilot-gate.d.ts +2 -2
- package/dist/core/autopilot-gate.js +1 -1
- package/dist/core/bash-spawn-benchmark.js +6 -6
- package/dist/core/bundled-agents.d.ts +3 -0
- package/dist/core/bundled-agents.d.ts.map +1 -0
- package/dist/core/bundled-agents.js +252 -0
- package/dist/core/bundled-agents.js.map +1 -0
- package/dist/core/cache-warm-benchmark.d.ts +2 -2
- package/dist/core/cache-warm-benchmark.js +5 -5
- package/dist/core/code-retrieval-chunkers.d.ts +27 -0
- package/dist/core/code-retrieval-chunkers.d.ts.map +1 -0
- package/dist/core/code-retrieval-chunkers.js +264 -0
- package/dist/core/code-retrieval-chunkers.js.map +1 -0
- package/dist/core/code-retrieval-chunkers.test.d.ts +2 -0
- package/dist/core/code-retrieval-chunkers.test.d.ts.map +1 -0
- package/dist/core/code-retrieval-chunkers.test.js +203 -0
- package/dist/core/code-retrieval-chunkers.test.js.map +1 -0
- package/dist/core/code-retrieval.d.ts +6 -0
- package/dist/core/code-retrieval.d.ts.map +1 -1
- package/dist/core/code-retrieval.js +38 -1
- package/dist/core/code-retrieval.js.map +1 -1
- package/dist/core/compaction/active-context.test.js +21 -0
- package/dist/core/compaction/active-context.test.js.map +1 -1
- package/dist/core/compaction/compactor.d.ts +108 -8
- package/dist/core/compaction/compactor.d.ts.map +1 -1
- package/dist/core/compaction/compactor.js +423 -119
- package/dist/core/compaction/compactor.js.map +1 -1
- package/dist/core/compaction/compactor.test.js +360 -8
- package/dist/core/compaction/compactor.test.js.map +1 -1
- package/dist/core/compaction/policy.d.ts +17 -0
- package/dist/core/compaction/policy.d.ts.map +1 -0
- package/dist/core/compaction/policy.js +22 -0
- package/dist/core/compaction/policy.js.map +1 -0
- package/dist/core/compaction/policy.test.d.ts +2 -0
- package/dist/core/compaction/policy.test.d.ts.map +1 -0
- package/dist/core/compaction/policy.test.js +35 -0
- package/dist/core/compaction/policy.test.js.map +1 -0
- package/dist/core/compaction/query-aware-selector.d.ts +33 -0
- package/dist/core/compaction/query-aware-selector.d.ts.map +1 -0
- package/dist/core/compaction/query-aware-selector.js +202 -0
- package/dist/core/compaction/query-aware-selector.js.map +1 -0
- package/dist/core/compaction/query-aware-selector.test.d.ts +2 -0
- package/dist/core/compaction/query-aware-selector.test.d.ts.map +1 -0
- package/dist/core/compaction/query-aware-selector.test.js +96 -0
- package/dist/core/compaction/query-aware-selector.test.js.map +1 -0
- package/dist/core/compaction/tool-result-pruner.d.ts +24 -11
- package/dist/core/compaction/tool-result-pruner.d.ts.map +1 -1
- package/dist/core/compaction/tool-result-pruner.js +98 -26
- package/dist/core/compaction/tool-result-pruner.js.map +1 -1
- package/dist/core/compaction/tool-result-pruner.test.js +178 -6
- package/dist/core/compaction/tool-result-pruner.test.js.map +1 -1
- package/dist/core/encode-cwd.test.js +1 -1
- package/dist/core/event-bus.d.ts +23 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +10 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +28 -8
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/plugin-bundles.d.ts +23 -0
- package/dist/core/extensions/plugin-bundles.d.ts.map +1 -0
- package/dist/core/extensions/plugin-bundles.js +228 -0
- package/dist/core/extensions/plugin-bundles.js.map +1 -0
- package/dist/core/extensions/plugin-bundles.test.d.ts +2 -0
- package/dist/core/extensions/plugin-bundles.test.d.ts.map +1 -0
- package/dist/core/extensions/plugin-bundles.test.js +110 -0
- package/dist/core/extensions/plugin-bundles.test.js.map +1 -0
- package/dist/core/fast-apply-benchmark.d.ts +2 -2
- package/dist/core/fast-apply-benchmark.js +6 -6
- package/dist/core/foreign-session-import.d.ts +120 -0
- package/dist/core/foreign-session-import.d.ts.map +1 -0
- package/dist/core/foreign-session-import.js +598 -0
- package/dist/core/foreign-session-import.js.map +1 -0
- package/dist/core/foreign-session-import.test.d.ts +2 -0
- package/dist/core/foreign-session-import.test.d.ts.map +1 -0
- package/dist/core/foreign-session-import.test.js +220 -0
- package/dist/core/foreign-session-import.test.js.map +1 -0
- package/dist/core/foreign-transcript-blocks.d.ts +51 -0
- package/dist/core/foreign-transcript-blocks.d.ts.map +1 -0
- package/dist/core/foreign-transcript-blocks.js +151 -0
- package/dist/core/foreign-transcript-blocks.js.map +1 -0
- package/dist/core/goal-lifecycle-smoke.test.js +2 -2
- package/dist/core/goal-store.js +1 -1
- package/dist/core/goal-store.test.js +2 -2
- package/dist/core/goal-verifier.test.js +2 -2
- package/dist/core/goal-worker-dev-server-lifecycle.test.js +1 -1
- package/dist/core/goal-worker.test.js +2 -2
- package/dist/core/hashline-edit-benchmark.d.ts +2 -2
- package/dist/core/hashline-edit-benchmark.js +7 -7
- package/dist/core/ideal-review.d.ts +20 -1
- package/dist/core/ideal-review.d.ts.map +1 -1
- package/dist/core/ideal-review.js +37 -2
- package/dist/core/ideal-review.js.map +1 -1
- package/dist/core/ideal-review.test.js +99 -3
- package/dist/core/ideal-review.test.js.map +1 -1
- package/dist/core/local-endpoint-store.test.js +1 -1
- package/dist/core/logger.d.ts +1 -1
- package/dist/core/logger.js +2 -2
- package/dist/core/logger.js.map +1 -1
- package/dist/core/loop-breaker.d.ts.map +1 -1
- package/dist/core/loop-breaker.js +1 -0
- package/dist/core/loop-breaker.js.map +1 -1
- package/dist/core/lsp/client-navigation.test.d.ts +2 -0
- package/dist/core/lsp/client-navigation.test.d.ts.map +1 -0
- package/dist/core/lsp/client-navigation.test.js +135 -0
- package/dist/core/lsp/client-navigation.test.js.map +1 -0
- package/dist/core/lsp/client.d.ts +84 -0
- package/dist/core/lsp/client.d.ts.map +1 -1
- package/dist/core/lsp/client.js +190 -3
- package/dist/core/lsp/client.js.map +1 -1
- package/dist/core/lsp/integration.test.js +2 -2
- package/dist/core/lsp/manager-navigation.test.d.ts +2 -0
- package/dist/core/lsp/manager-navigation.test.d.ts.map +1 -0
- package/dist/core/lsp/manager-navigation.test.js +121 -0
- package/dist/core/lsp/manager-navigation.test.js.map +1 -0
- package/dist/core/lsp/manager.d.ts +81 -9
- package/dist/core/lsp/manager.d.ts.map +1 -1
- package/dist/core/lsp/manager.js +183 -64
- package/dist/core/lsp/manager.js.map +1 -1
- package/dist/core/lsp/manager.test.js +18 -0
- package/dist/core/lsp/manager.test.js.map +1 -1
- package/dist/core/lsp/pool.d.ts +113 -0
- package/dist/core/lsp/pool.d.ts.map +1 -0
- package/dist/core/lsp/pool.js +255 -0
- package/dist/core/lsp/pool.js.map +1 -0
- package/dist/core/lsp/pool.test.d.ts +2 -0
- package/dist/core/lsp/pool.test.d.ts.map +1 -0
- package/dist/core/lsp/pool.test.js +286 -0
- package/dist/core/lsp/pool.test.js.map +1 -0
- package/dist/core/lsp/servers.d.ts.map +1 -1
- package/dist/core/lsp/servers.js +43 -3
- package/dist/core/lsp/servers.js.map +1 -1
- package/dist/core/lsp/servers.test.d.ts +2 -0
- package/dist/core/lsp/servers.test.d.ts.map +1 -0
- package/dist/core/lsp/servers.test.js +67 -0
- package/dist/core/lsp/servers.test.js.map +1 -0
- package/dist/core/lsp/windows.test.js +6 -18
- package/dist/core/lsp/windows.test.js.map +1 -1
- package/dist/core/mcp/catalog-cache.d.ts +63 -0
- package/dist/core/mcp/catalog-cache.d.ts.map +1 -0
- package/dist/core/mcp/catalog-cache.js +163 -0
- package/dist/core/mcp/catalog-cache.js.map +1 -0
- package/dist/core/mcp/catalog-cache.test.d.ts +2 -0
- package/dist/core/mcp/catalog-cache.test.d.ts.map +1 -0
- package/dist/core/mcp/catalog-cache.test.js +99 -0
- package/dist/core/mcp/catalog-cache.test.js.map +1 -0
- package/dist/core/mcp/client-session-recovery.test.d.ts +2 -0
- package/dist/core/mcp/client-session-recovery.test.d.ts.map +1 -0
- package/dist/core/mcp/client-session-recovery.test.js +231 -0
- package/dist/core/mcp/client-session-recovery.test.js.map +1 -0
- package/dist/core/mcp/client.d.ts +158 -0
- package/dist/core/mcp/client.d.ts.map +1 -1
- package/dist/core/mcp/client.js +478 -45
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/content.d.ts +19 -0
- package/dist/core/mcp/content.d.ts.map +1 -0
- package/dist/core/mcp/content.js +172 -0
- package/dist/core/mcp/content.js.map +1 -0
- package/dist/core/mcp/content.test.d.ts +2 -0
- package/dist/core/mcp/content.test.d.ts.map +1 -0
- package/dist/core/mcp/content.test.js +135 -0
- package/dist/core/mcp/content.test.js.map +1 -0
- package/dist/core/mcp/deferred-catalog.d.ts +1 -1
- package/dist/core/mcp/deferred-catalog.js +1 -1
- package/dist/core/mcp/elicitation-bridge.d.ts +41 -0
- package/dist/core/mcp/elicitation-bridge.d.ts.map +1 -0
- package/dist/core/mcp/elicitation-bridge.js +52 -0
- package/dist/core/mcp/elicitation-bridge.js.map +1 -0
- package/dist/core/mcp/elicitation.test.d.ts +2 -0
- package/dist/core/mcp/elicitation.test.d.ts.map +1 -0
- package/dist/core/mcp/elicitation.test.js +158 -0
- package/dist/core/mcp/elicitation.test.js.map +1 -0
- package/dist/core/mcp/index.d.ts +5 -1
- package/dist/core/mcp/index.d.ts.map +1 -1
- package/dist/core/mcp/index.js +2 -0
- package/dist/core/mcp/index.js.map +1 -1
- package/dist/core/mcp/legacy-negotiation.test.d.ts +2 -0
- package/dist/core/mcp/legacy-negotiation.test.d.ts.map +1 -0
- package/dist/core/mcp/legacy-negotiation.test.js +80 -0
- package/dist/core/mcp/legacy-negotiation.test.js.map +1 -0
- package/dist/core/mcp/oauth-provider.d.ts +1 -2
- package/dist/core/mcp/oauth-provider.d.ts.map +1 -1
- package/dist/core/mcp/oauth-provider.js +6 -2
- package/dist/core/mcp/oauth-provider.js.map +1 -1
- package/dist/core/mcp/oauth-store.d.ts +1 -1
- package/dist/core/mcp/oauth-store.d.ts.map +1 -1
- package/dist/core/mcp/oauth-store.js.map +1 -1
- package/dist/core/mcp/oauth-store.test.js +2 -2
- package/dist/core/mcp/resolve-stdio.test.js +5 -5
- package/dist/core/mcp/session-elicitation-wiring.test.d.ts +2 -0
- package/dist/core/mcp/session-elicitation-wiring.test.d.ts.map +1 -0
- package/dist/core/mcp/session-elicitation-wiring.test.js +138 -0
- package/dist/core/mcp/session-elicitation-wiring.test.js.map +1 -0
- package/dist/core/mcp/shared-pool.d.ts +158 -0
- package/dist/core/mcp/shared-pool.d.ts.map +1 -0
- package/dist/core/mcp/shared-pool.js +235 -0
- package/dist/core/mcp/shared-pool.js.map +1 -0
- package/dist/core/mcp/shared-pool.test.d.ts +2 -0
- package/dist/core/mcp/shared-pool.test.d.ts.map +1 -0
- package/dist/core/mcp/shared-pool.test.js +425 -0
- package/dist/core/mcp/shared-pool.test.js.map +1 -0
- package/dist/core/mcp/store.test.js +5 -5
- package/dist/core/mcp/types.d.ts +12 -0
- package/dist/core/mcp/types.d.ts.map +1 -1
- package/dist/core/mcp/when-connected.test.d.ts +2 -0
- package/dist/core/mcp/when-connected.test.d.ts.map +1 -0
- package/dist/core/mcp/when-connected.test.js +46 -0
- package/dist/core/mcp/when-connected.test.js.map +1 -0
- package/dist/core/nolan-context.d.ts.map +1 -1
- package/dist/core/nolan-context.js +8 -0
- package/dist/core/nolan-context.js.map +1 -1
- package/dist/core/nolan-context.test.js +40 -0
- package/dist/core/nolan-context.test.js.map +1 -1
- package/dist/core/nolan-model.test.js +1 -1
- package/dist/core/nolan-prompt.js +8 -5
- package/dist/core/nolan-prompt.js.map +1 -1
- package/dist/core/nolan-prompt.test.js +5 -0
- package/dist/core/nolan-prompt.test.js.map +1 -1
- package/dist/core/oauth/xai.d.ts +2 -0
- package/dist/core/oauth/xai.d.ts.map +1 -0
- package/dist/core/oauth/xai.js +4 -0
- package/dist/core/oauth/xai.js.map +1 -0
- package/dist/core/persistent-shell.d.ts +3 -2
- package/dist/core/persistent-shell.d.ts.map +1 -1
- package/dist/core/persistent-shell.js +11 -4
- package/dist/core/persistent-shell.js.map +1 -1
- package/dist/core/persistent-shell.test.js +6 -6
- package/dist/core/process-gate.d.ts +45 -0
- package/dist/core/process-gate.d.ts.map +1 -0
- package/dist/core/process-gate.js +79 -0
- package/dist/core/process-gate.js.map +1 -0
- package/dist/core/process-gate.test.d.ts +2 -0
- package/dist/core/process-gate.test.d.ts.map +1 -0
- package/dist/core/process-gate.test.js +87 -0
- package/dist/core/process-gate.test.js.map +1 -0
- package/dist/core/process-manager-dev-server-repro.test.js +51 -12
- package/dist/core/process-manager-dev-server-repro.test.js.map +1 -1
- package/dist/core/process-manager-notifications.test.d.ts +2 -0
- package/dist/core/process-manager-notifications.test.d.ts.map +1 -0
- package/dist/core/process-manager-notifications.test.js +227 -0
- package/dist/core/process-manager-notifications.test.js.map +1 -0
- package/dist/core/process-manager.d.ts +72 -1
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +247 -4
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/progress/git-xp.test.js +2 -2
- package/dist/core/progress/ranks.d.ts +14 -3
- package/dist/core/progress/ranks.d.ts.map +1 -1
- package/dist/core/progress/ranks.js +181 -12
- package/dist/core/progress/ranks.js.map +1 -1
- package/dist/core/progress/ranks.test.js +48 -7
- package/dist/core/progress/ranks.test.js.map +1 -1
- package/dist/core/progress/rebuild.test.js +1 -1
- package/dist/core/progress/store.test.js +1 -1
- package/dist/core/progress/types.d.ts +2 -1
- package/dist/core/progress/types.d.ts.map +1 -1
- package/dist/core/project-discovery.d.ts +31 -6
- package/dist/core/project-discovery.d.ts.map +1 -1
- package/dist/core/project-discovery.js +349 -79
- package/dist/core/project-discovery.js.map +1 -1
- package/dist/core/project-discovery.test.js +128 -4
- package/dist/core/project-discovery.test.js.map +1 -1
- package/dist/core/prompt-commands.js +3 -3
- package/dist/core/radio.d.ts +1 -1
- package/dist/core/radio.d.ts.map +1 -1
- package/dist/core/radio.js +90 -6
- package/dist/core/radio.js.map +1 -1
- package/dist/core/radio.test.js +15 -2
- package/dist/core/radio.test.js.map +1 -1
- package/dist/core/regrounding.d.ts.map +1 -1
- package/dist/core/regrounding.js +1 -0
- package/dist/core/regrounding.js.map +1 -1
- package/dist/core/run-claim.d.ts +37 -0
- package/dist/core/run-claim.d.ts.map +1 -0
- package/dist/core/run-claim.js +46 -0
- package/dist/core/run-claim.js.map +1 -0
- package/dist/core/run-claim.test.d.ts +2 -0
- package/dist/core/run-claim.test.d.ts.map +1 -0
- package/dist/core/run-claim.test.js +107 -0
- package/dist/core/run-claim.test.js.map +1 -0
- package/dist/core/run-journal.test.d.ts +2 -0
- package/dist/core/run-journal.test.d.ts.map +1 -0
- package/dist/core/run-journal.test.js +195 -0
- package/dist/core/run-journal.test.js.map +1 -0
- package/dist/core/run-lifecycle.d.ts +22 -3
- package/dist/core/run-lifecycle.d.ts.map +1 -1
- package/dist/core/run-lifecycle.js +12 -3
- package/dist/core/run-lifecycle.js.map +1 -1
- package/dist/core/sandbox-domains.d.ts +14 -0
- package/dist/core/sandbox-domains.d.ts.map +1 -0
- package/dist/core/sandbox-domains.js +76 -0
- package/dist/core/sandbox-domains.js.map +1 -0
- package/dist/core/sandbox-feedback.d.ts +22 -0
- package/dist/core/sandbox-feedback.d.ts.map +1 -0
- package/dist/core/sandbox-feedback.js +69 -0
- package/dist/core/sandbox-feedback.js.map +1 -0
- package/dist/core/sandbox-feedback.test.d.ts +2 -0
- package/dist/core/sandbox-feedback.test.d.ts.map +1 -0
- package/dist/core/sandbox-feedback.test.js +32 -0
- package/dist/core/sandbox-feedback.test.js.map +1 -0
- package/dist/core/sandbox.d.ts +91 -0
- package/dist/core/sandbox.d.ts.map +1 -0
- package/dist/core/sandbox.js +254 -0
- package/dist/core/sandbox.js.map +1 -0
- package/dist/core/sandbox.test.d.ts +2 -0
- package/dist/core/sandbox.test.d.ts.map +1 -0
- package/dist/core/sandbox.test.js +157 -0
- package/dist/core/sandbox.test.js.map +1 -0
- package/dist/core/semantic-search-benchmark.d.ts +2 -2
- package/dist/core/semantic-search-benchmark.js +5 -5
- package/dist/core/session-compaction.d.ts +6 -0
- package/dist/core/session-compaction.d.ts.map +1 -1
- package/dist/core/session-compaction.js +11 -1
- package/dist/core/session-compaction.js.map +1 -1
- package/dist/core/session-compaction.test.js +19 -2
- package/dist/core/session-compaction.test.js.map +1 -1
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +12 -4
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-history.d.ts +95 -6
- package/dist/core/session-history.d.ts.map +1 -1
- package/dist/core/session-history.js +261 -17
- package/dist/core/session-history.js.map +1 -1
- package/dist/core/session-history.test.js +173 -2
- package/dist/core/session-history.test.js.map +1 -1
- package/dist/core/session-manager.d.ts +223 -6
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +579 -74
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-manager.test.js +154 -10
- package/dist/core/session-manager.test.js.map +1 -1
- package/dist/core/session-notification-visibility.test.d.ts +2 -0
- package/dist/core/session-notification-visibility.test.d.ts.map +1 -0
- package/dist/core/session-notification-visibility.test.js +113 -0
- package/dist/core/session-notification-visibility.test.js.map +1 -0
- package/dist/core/session-preview.d.ts +5 -4
- package/dist/core/session-preview.d.ts.map +1 -1
- package/dist/core/session-preview.js +12 -5
- package/dist/core/session-preview.js.map +1 -1
- package/dist/core/session-restore-display.test.js +25 -0
- package/dist/core/session-restore-display.test.js.map +1 -1
- package/dist/core/session-storage-fd-leak.test.d.ts +2 -0
- package/dist/core/session-storage-fd-leak.test.d.ts.map +1 -0
- package/dist/core/session-storage-fd-leak.test.js +116 -0
- package/dist/core/session-storage-fd-leak.test.js.map +1 -0
- package/dist/core/session-storage.d.ts +22 -2
- package/dist/core/session-storage.d.ts.map +1 -1
- package/dist/core/session-storage.js +72 -9
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/session-storage.test.js +8 -3
- package/dist/core/session-storage.test.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +36 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/shell-path.js +1 -1
- package/dist/core/shell.d.ts +1 -1
- package/dist/core/shell.js +2 -2
- package/dist/core/shell.test.js +2 -2
- package/dist/core/shutdown.d.ts +71 -0
- package/dist/core/shutdown.d.ts.map +1 -0
- package/dist/core/shutdown.js +144 -0
- package/dist/core/shutdown.js.map +1 -0
- package/dist/core/shutdown.test.d.ts +2 -0
- package/dist/core/shutdown.test.d.ts.map +1 -0
- package/dist/core/shutdown.test.js +160 -0
- package/dist/core/shutdown.test.js.map +1 -0
- package/dist/core/sidecar-error-reporter.js +1 -1
- package/dist/core/sidecar-error-reporter.test.js +2 -2
- package/dist/core/skills-routing.test.js +96 -0
- package/dist/core/skills-routing.test.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +3 -0
- package/dist/core/skills.js.map +1 -1
- package/dist/core/steering.d.ts +12 -0
- package/dist/core/steering.d.ts.map +1 -1
- package/dist/core/steering.js +16 -0
- package/dist/core/steering.js.map +1 -1
- package/dist/core/subagent-manager.d.ts +22 -0
- package/dist/core/subagent-manager.d.ts.map +1 -1
- package/dist/core/subagent-manager.js +84 -13
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/subagent-manager.test.js +57 -15
- package/dist/core/subagent-manager.test.js.map +1 -1
- package/dist/core/subagent-store.test.js +3 -3
- package/dist/core/task-store.js +1 -1
- package/dist/core/verification-evidence.d.ts +17 -0
- package/dist/core/verification-evidence.d.ts.map +1 -0
- package/dist/core/verification-evidence.js +283 -0
- package/dist/core/verification-evidence.js.map +1 -0
- package/dist/core/verification-evidence.test.d.ts +2 -0
- package/dist/core/verification-evidence.test.d.ts.map +1 -0
- package/dist/core/verification-evidence.test.js +103 -0
- package/dist/core/verification-evidence.test.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interactive.d.ts.map +1 -1
- package/dist/interactive.js +17 -3
- package/dist/interactive.js.map +1 -1
- package/dist/modes/acp-mode.d.ts +122 -0
- package/dist/modes/acp-mode.d.ts.map +1 -0
- package/dist/modes/acp-mode.js +1366 -0
- package/dist/modes/acp-mode.js.map +1 -0
- package/dist/modes/acp-mode.test.d.ts +2 -0
- package/dist/modes/acp-mode.test.d.ts.map +1 -0
- package/dist/modes/acp-mode.test.js +1065 -0
- package/dist/modes/acp-mode.test.js.map +1 -0
- package/dist/modes/agent-home-mode.d.ts.map +1 -1
- package/dist/modes/agent-home-mode.js +15 -11
- package/dist/modes/agent-home-mode.js.map +1 -1
- package/dist/modes/index.d.ts +1 -0
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +1 -0
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/json-mode.d.ts +36 -0
- package/dist/modes/json-mode.d.ts.map +1 -1
- package/dist/modes/json-mode.js +39 -0
- package/dist/modes/json-mode.js.map +1 -1
- package/dist/modes/json-mode.test.d.ts +2 -0
- package/dist/modes/json-mode.test.d.ts.map +1 -0
- package/dist/modes/json-mode.test.js +84 -0
- package/dist/modes/json-mode.test.js.map +1 -0
- package/dist/modes/serve-mode.d.ts +1 -1
- package/dist/modes/serve-mode.d.ts.map +1 -1
- package/dist/modes/serve-mode.js +14 -9
- package/dist/modes/serve-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.d.ts +8 -0
- package/dist/modes/subagent-worker-mode.d.ts.map +1 -1
- package/dist/modes/subagent-worker-mode.js +91 -11
- package/dist/modes/subagent-worker-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.test.d.ts +2 -0
- package/dist/modes/subagent-worker-mode.test.d.ts.map +1 -0
- package/dist/modes/subagent-worker-mode.test.js +52 -0
- package/dist/modes/subagent-worker-mode.test.js.map +1 -0
- package/dist/session.d.ts +29 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +41 -0
- package/dist/session.js.map +1 -1
- package/dist/session.test.js +1 -1
- package/dist/system-prompt.d.ts +37 -1
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +123 -11
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +90 -11
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/system-prompt.tiering.test.d.ts +2 -0
- package/dist/system-prompt.tiering.test.d.ts.map +1 -0
- package/dist/system-prompt.tiering.test.js +105 -0
- package/dist/system-prompt.tiering.test.js.map +1 -0
- package/dist/tools/bash.d.ts +2 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +55 -16
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/code-nav.d.ts +30 -0
- package/dist/tools/code-nav.d.ts.map +1 -0
- package/dist/tools/code-nav.js +320 -0
- package/dist/tools/code-nav.js.map +1 -0
- package/dist/tools/code-nav.test.d.ts +2 -0
- package/dist/tools/code-nav.test.d.ts.map +1 -0
- package/dist/tools/code-nav.test.js +136 -0
- package/dist/tools/code-nav.test.js.map +1 -0
- package/dist/tools/edit.test.js +1 -1
- package/dist/tools/generate-image.d.ts +1 -1
- package/dist/tools/goals.d.ts +4 -4
- package/dist/tools/goals.test.js +2 -2
- package/dist/tools/grep-parity.test.d.ts +2 -0
- package/dist/tools/grep-parity.test.d.ts.map +1 -0
- package/dist/tools/grep-parity.test.js +92 -0
- package/dist/tools/grep-parity.test.js.map +1 -0
- package/dist/tools/grep-recall.test.d.ts +2 -0
- package/dist/tools/grep-recall.test.d.ts.map +1 -0
- package/dist/tools/grep-recall.test.js +114 -0
- package/dist/tools/grep-recall.test.js.map +1 -0
- package/dist/tools/grep-spawn.test.d.ts +2 -0
- package/dist/tools/grep-spawn.test.d.ts.map +1 -0
- package/dist/tools/grep-spawn.test.js +66 -0
- package/dist/tools/grep-spawn.test.js.map +1 -0
- package/dist/tools/grep.d.ts +13 -3
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +342 -41
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/grep.test.js +17 -14
- package/dist/tools/grep.test.js.map +1 -1
- package/dist/tools/index.d.ts +20 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +28 -18
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/index.test.d.ts +2 -0
- package/dist/tools/index.test.d.ts.map +1 -0
- package/dist/tools/index.test.js +55 -0
- package/dist/tools/index.test.js.map +1 -0
- package/dist/tools/plan-mode.test.js +1 -1
- package/dist/tools/prompt-hints.d.ts +9 -0
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +61 -8
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/read-only-bash.d.ts +3 -0
- package/dist/tools/read-only-bash.d.ts.map +1 -1
- package/dist/tools/read-only-bash.js +7 -9
- package/dist/tools/read-only-bash.js.map +1 -1
- package/dist/tools/safe-env.js +1 -1
- package/dist/tools/search-code.d.ts.map +1 -1
- package/dist/tools/search-code.js +7 -6
- package/dist/tools/search-code.js.map +1 -1
- package/dist/tools/search-code.test.js +8 -2
- package/dist/tools/search-code.test.js.map +1 -1
- package/dist/tools/skill.js +2 -1
- package/dist/tools/skill.js.map +1 -1
- package/dist/tools/subagent-control.d.ts.map +1 -1
- package/dist/tools/subagent-control.js +25 -6
- package/dist/tools/subagent-control.js.map +1 -1
- package/dist/tools/subagent-control.test.js +34 -1
- package/dist/tools/subagent-control.test.js.map +1 -1
- package/dist/tools/subagent-shared.d.ts +26 -1
- package/dist/tools/subagent-shared.d.ts.map +1 -1
- package/dist/tools/subagent-shared.js +40 -7
- package/dist/tools/subagent-shared.js.map +1 -1
- package/dist/tools/subagent-shared.test.js +43 -9
- package/dist/tools/subagent-shared.test.js.map +1 -1
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +54 -16
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/subagent.test.js +68 -3
- package/dist/tools/subagent.test.js.map +1 -1
- package/dist/tools/task-output.d.ts.map +1 -1
- package/dist/tools/task-output.js +3 -1
- package/dist/tools/task-output.js.map +1 -1
- package/dist/tools/task-send.test.js +19 -10
- package/dist/tools/task-send.test.js.map +1 -1
- package/dist/tools/tool-search.d.ts +12 -1
- package/dist/tools/tool-search.d.ts.map +1 -1
- package/dist/tools/tool-search.js +24 -4
- package/dist/tools/tool-search.js.map +1 -1
- package/dist/tools/tool-search.test.d.ts +2 -0
- package/dist/tools/tool-search.test.d.ts.map +1 -0
- package/dist/tools/tool-search.test.js +69 -0
- package/dist/tools/tool-search.test.js.map +1 -0
- package/dist/tools/tool-tiers.d.ts +42 -0
- package/dist/tools/tool-tiers.d.ts.map +1 -0
- package/dist/tools/tool-tiers.js +78 -0
- package/dist/tools/tool-tiers.js.map +1 -0
- package/dist/tools/tool-tiers.test.d.ts +2 -0
- package/dist/tools/tool-tiers.test.d.ts.map +1 -0
- package/dist/tools/tool-tiers.test.js +48 -0
- package/dist/tools/tool-tiers.test.js.map +1 -0
- package/dist/tools/web-fetch.d.ts +1 -1
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +5 -2
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/write.test.js +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +27 -1
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/components/Banner.d.ts.map +1 -1
- package/dist/ui/components/Banner.js +24 -16
- package/dist/ui/components/Banner.js.map +1 -1
- package/dist/ui/components/ToolExecution.js +42 -34
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/components/force-color.d.ts +2 -0
- package/dist/ui/components/force-color.d.ts.map +1 -0
- package/dist/ui/components/force-color.js +11 -0
- package/dist/ui/components/force-color.js.map +1 -0
- package/dist/ui/components/themed-output.test.d.ts +2 -0
- package/dist/ui/components/themed-output.test.d.ts.map +1 -0
- package/dist/ui/components/themed-output.test.js +111 -0
- package/dist/ui/components/themed-output.test.js.map +1 -0
- package/dist/ui/error-item.d.ts +1 -1
- package/dist/ui/error-item.js +3 -3
- package/dist/ui/error-item.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts +3 -0
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +45 -6
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/login.js +1 -1
- package/dist/ui/login.js.map +1 -1
- package/dist/ui/render.d.ts +1 -1
- package/dist/ui/render.js +6 -6
- package/dist/ui/theme/dark-ansi.json +6 -0
- package/dist/ui/theme/dark-daltonized.json +6 -0
- package/dist/ui/theme/dark.json +6 -0
- package/dist/ui/theme/light-ansi.json +6 -0
- package/dist/ui/theme/light-daltonized.json +6 -0
- package/dist/ui/theme/light.json +6 -0
- package/dist/ui/theme/theme.d.ts +6 -0
- package/dist/ui/theme/theme.d.ts.map +1 -1
- package/dist/ui/tui-terminal-recorder.test.js +1 -1
- package/dist/utils/git.test.js +3 -3
- package/dist/utils/github.test.js +3 -3
- package/dist/utils/github.test.js.map +1 -1
- package/dist/utils/image.d.ts +26 -3
- package/dist/utils/image.d.ts.map +1 -1
- package/dist/utils/image.js +83 -14
- package/dist/utils/image.js.map +1 -1
- package/dist/utils/image.test.d.ts +2 -0
- package/dist/utils/image.test.d.ts.map +1 -0
- package/dist/utils/image.test.js +139 -0
- package/dist/utils/image.test.js.map +1 -0
- package/package.json +7 -6
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pushed background-status updates ride the steering path into the model's
|
|
3
|
+
* context, so they are persisted as `user` messages. But the LIVE transcript
|
|
4
|
+
* never shows a bubble for them — the loop yields `steering_message`, which no
|
|
5
|
+
* host forwards to the UI.
|
|
6
|
+
*
|
|
7
|
+
* That asymmetry was the bug: a session looked clean while you worked in it and
|
|
8
|
+
* came back full of "Background process … exited with code 0" lines the moment
|
|
9
|
+
* you reopened it. Every surface that reconstructs a transcript from the
|
|
10
|
+
* session file must therefore skip them, exactly as it already skips autopilot
|
|
11
|
+
* injections.
|
|
12
|
+
*/
|
|
13
|
+
import { describe, expect, it } from "vitest";
|
|
14
|
+
import { restoreUserRow } from "./session-history.js";
|
|
15
|
+
import { findUserSessionPrompt, getUserSessionPrompt } from "./session-preview.js";
|
|
16
|
+
import { sessionToMarkdown } from "./session-export.js";
|
|
17
|
+
import { buildNotificationSteeringText, STEERING_PREFIX } from "./steering.js";
|
|
18
|
+
const DEV_SERVER_NOTIFICATION = buildNotificationSteeringText([
|
|
19
|
+
'Background process c1c45a8d (pnpm dev) exited with code 0 after 40s. Last output: …ELIFECYCLE Command failed. Read it with task_output id="c1c45a8d".',
|
|
20
|
+
]);
|
|
21
|
+
const PROGRESS_NOTIFICATION = buildNotificationSteeringText([
|
|
22
|
+
"Background process c1c45a8d (pnpm dev) is still running after 3.2m, 48210 bytes logged. Latest: [electron] compiled ok",
|
|
23
|
+
]);
|
|
24
|
+
/** A realistic resumed transcript: real work, with status updates interleaved. */
|
|
25
|
+
function transcript() {
|
|
26
|
+
return [
|
|
27
|
+
{ role: "user", content: "start the dev server and fix the login bug" },
|
|
28
|
+
{ role: "assistant", content: "Starting it now." },
|
|
29
|
+
{ role: "user", content: PROGRESS_NOTIFICATION },
|
|
30
|
+
{ role: "assistant", content: "Still building. Meanwhile, here's the fix." },
|
|
31
|
+
{ role: "user", content: DEV_SERVER_NOTIFICATION },
|
|
32
|
+
{ role: "assistant", content: "The server exited; I'll restart it." },
|
|
33
|
+
{ role: "user", content: `${STEERING_PREFIX}also add dark mode` },
|
|
34
|
+
{ role: "assistant", content: "Done." },
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
describe("resumed transcript", () => {
|
|
38
|
+
it("hides pushed status updates but keeps everything the user sent", () => {
|
|
39
|
+
const visible = transcript()
|
|
40
|
+
.filter((m) => m.role === "user")
|
|
41
|
+
.map((m) => restoreUserRow(m.content))
|
|
42
|
+
.filter((row) => !row.notification)
|
|
43
|
+
.map((row) => row.text);
|
|
44
|
+
expect(visible).toEqual(["start the dev server and fix the login bug", "also add dark mode"]);
|
|
45
|
+
});
|
|
46
|
+
it("hides them whether the process is still running or has exited", () => {
|
|
47
|
+
expect(restoreUserRow(PROGRESS_NOTIFICATION).notification).toBe(true);
|
|
48
|
+
expect(restoreUserRow(DEV_SERVER_NOTIFICATION).notification).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe("session title", () => {
|
|
52
|
+
it("never uses a status update as the title", () => {
|
|
53
|
+
// Otherwise a session is listed as "Background process c1c45a8d (pnpm dev)
|
|
54
|
+
// exited with code 0" — unrecognisable and unsearchable.
|
|
55
|
+
expect(getUserSessionPrompt(DEV_SERVER_NOTIFICATION)).toBeNull();
|
|
56
|
+
expect(getUserSessionPrompt(PROGRESS_NOTIFICATION)).toBeNull();
|
|
57
|
+
});
|
|
58
|
+
it("falls through a leading status update to the real prompt", () => {
|
|
59
|
+
const title = findUserSessionPrompt([
|
|
60
|
+
{ role: "user", content: DEV_SERVER_NOTIFICATION },
|
|
61
|
+
{ role: "user", content: "fix the login bug" },
|
|
62
|
+
]);
|
|
63
|
+
expect(title).toBe("fix the login bug");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe("session export", () => {
|
|
67
|
+
it("omits status updates from exported markdown", () => {
|
|
68
|
+
const markdown = sessionToMarkdown({ mode: "code", cwd: "/tmp/project", provider: "anthropic", model: "claude-test" }, transcript());
|
|
69
|
+
// The user's own words survive.
|
|
70
|
+
expect(markdown).toContain("start the dev server and fix the login bug");
|
|
71
|
+
expect(markdown).toContain("also add dark mode");
|
|
72
|
+
// The machine framing and its payload do not — an export must match the
|
|
73
|
+
// conversation the user actually had.
|
|
74
|
+
expect(markdown).not.toContain("Status update on background work");
|
|
75
|
+
expect(markdown).not.toContain("c1c45a8d");
|
|
76
|
+
expect(markdown).not.toContain("still running after");
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe("provenance-first visibility", () => {
|
|
80
|
+
const human = { source: "human", kind: "prompt", visibility: "transcript" };
|
|
81
|
+
const hiddenRuntime = {
|
|
82
|
+
source: "runtime",
|
|
83
|
+
kind: "notification",
|
|
84
|
+
visibility: "hidden",
|
|
85
|
+
};
|
|
86
|
+
it("trusts metadata over misleading message text for titles and exports", () => {
|
|
87
|
+
const messages = [
|
|
88
|
+
{ role: "user", content: "ordinary-looking generated context", provenance: hiddenRuntime },
|
|
89
|
+
{ role: "user", content: DEV_SERVER_NOTIFICATION, provenance: human },
|
|
90
|
+
];
|
|
91
|
+
expect(findUserSessionPrompt(messages)).toBe(DEV_SERVER_NOTIFICATION);
|
|
92
|
+
const markdown = sessionToMarkdown({ mode: "code", cwd: "/tmp/project", provider: "anthropic", model: "claude-test" }, messages);
|
|
93
|
+
expect(markdown).not.toContain("ordinary-looking generated context");
|
|
94
|
+
expect(markdown).toContain(DEV_SERVER_NOTIFICATION);
|
|
95
|
+
});
|
|
96
|
+
it("renders tagged summaries as compaction markers without exporting their payload", () => {
|
|
97
|
+
const markdown = sessionToMarkdown({ mode: "code", cwd: "/tmp/project", provider: "anthropic", model: "claude-test" }, [
|
|
98
|
+
{
|
|
99
|
+
role: "user",
|
|
100
|
+
content: "summary payload without a legacy prefix",
|
|
101
|
+
provenance: {
|
|
102
|
+
source: "runtime",
|
|
103
|
+
kind: "compaction_summary",
|
|
104
|
+
visibility: "summary",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
]);
|
|
108
|
+
expect(markdown).toContain("conversation compacted here");
|
|
109
|
+
expect(markdown).not.toContain("summary payload without a legacy prefix");
|
|
110
|
+
expect(markdown).not.toContain("no messages yet");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
//# sourceMappingURL=session-notification-visibility.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-notification-visibility.test.js","sourceRoot":"","sources":["../../src/core/session-notification-visibility.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { Message } from "@prestyj/ai";
|
|
1
|
+
import type { Message, MessageProvenance } from "@prestyj/ai";
|
|
2
2
|
/** Extract visible text from a persisted message content value. */
|
|
3
3
|
export declare function extractSessionText(content: Message["content"] | unknown): string;
|
|
4
4
|
/**
|
|
5
5
|
* Return user-authored prompt text suitable for a stable session title.
|
|
6
|
-
* Compaction summaries
|
|
7
|
-
* not new conversations, so they must never
|
|
6
|
+
* Compaction summaries, Nolan's autopilot injections, and background-status
|
|
7
|
+
* updates are model-owned context, not new conversations, so they must never
|
|
8
|
+
* replace the user's title.
|
|
8
9
|
*/
|
|
9
|
-
export declare function getUserSessionPrompt(content: Message["content"] | unknown): string | null;
|
|
10
|
+
export declare function getUserSessionPrompt(content: Message["content"] | unknown, provenance?: MessageProvenance): string | null;
|
|
10
11
|
export declare function findUserSessionPrompt(messages: readonly Message[]): string;
|
|
11
12
|
//# sourceMappingURL=session-preview.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-preview.d.ts","sourceRoot":"","sources":["../../src/core/session-preview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"session-preview.d.ts","sourceRoot":"","sources":["../../src/core/session-preview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQ9D,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,GAAG,MAAM,CAWhF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,EACrC,UAAU,CAAC,EAAE,iBAAiB,GAC7B,MAAM,GAAG,IAAI,CAmBf;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAO1E"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NOTIFICATION_PREFIX } from "./steering.js";
|
|
1
2
|
const COMPACTION_SUMMARY_PREFIX = "[Previous conversation summary]";
|
|
2
3
|
const AUTOPILOT_PROMPT_PREFIX = "[Autopilot] This turn was triggered by Nolan, EZ Coder's automated reviewer";
|
|
3
4
|
const STEERING_PREFIX_START = "[The user added this while you were working";
|
|
@@ -19,14 +20,20 @@ export function extractSessionText(content) {
|
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
21
22
|
* Return user-authored prompt text suitable for a stable session title.
|
|
22
|
-
* Compaction summaries
|
|
23
|
-
* not new conversations, so they must never
|
|
23
|
+
* Compaction summaries, Nolan's autopilot injections, and background-status
|
|
24
|
+
* updates are model-owned context, not new conversations, so they must never
|
|
25
|
+
* replace the user's title.
|
|
24
26
|
*/
|
|
25
|
-
export function getUserSessionPrompt(content) {
|
|
27
|
+
export function getUserSessionPrompt(content, provenance) {
|
|
28
|
+
if (provenance && provenance.source !== "human")
|
|
29
|
+
return null;
|
|
26
30
|
let text = extractSessionText(content).trim();
|
|
27
31
|
if (!text)
|
|
28
32
|
return null;
|
|
29
|
-
if (
|
|
33
|
+
if (!provenance &&
|
|
34
|
+
(text.startsWith(COMPACTION_SUMMARY_PREFIX) ||
|
|
35
|
+
text.startsWith(AUTOPILOT_PROMPT_PREFIX) ||
|
|
36
|
+
text.startsWith(NOTIFICATION_PREFIX))) {
|
|
30
37
|
return null;
|
|
31
38
|
}
|
|
32
39
|
// A queued steering note is still user-authored; remove only its machine frame.
|
|
@@ -41,7 +48,7 @@ export function findUserSessionPrompt(messages) {
|
|
|
41
48
|
for (const message of messages) {
|
|
42
49
|
if (message.role !== "user")
|
|
43
50
|
continue;
|
|
44
|
-
const text = getUserSessionPrompt(message.content);
|
|
51
|
+
const text = getUserSessionPrompt(message.content, message.provenance);
|
|
45
52
|
if (text)
|
|
46
53
|
return text;
|
|
47
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-preview.js","sourceRoot":"","sources":["../../src/core/session-preview.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-preview.js","sourceRoot":"","sources":["../../src/core/session-preview.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,yBAAyB,GAAG,iCAAiC,CAAC;AACpE,MAAM,uBAAuB,GAC3B,6EAA6E,CAAC;AAChF,MAAM,qBAAqB,GAAG,6CAA6C,CAAC;AAE5E,mEAAmE;AACnE,MAAM,UAAU,kBAAkB,CAAC,OAAqC;IACtE,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,OAAO;SACX,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACzE,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;QAChD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9C,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAqC,EACrC,UAA8B;IAE9B,IAAI,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC7D,IAAI,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IACE,CAAC,UAAU;QACX,CAAC,IAAI,CAAC,UAAU,CAAC,yBAAyB,CAAC;YACzC,IAAI,CAAC,UAAU,CAAC,uBAAuB,CAAC;YACxC,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,EACvC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gFAAgF;IAChF,IAAI,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,OAAO,IAAI,CAAC;YAAE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,CAAC;IACD,OAAO,IAAI,IAAI,IAAI,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAA4B;IAChE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACtC,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QACvE,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;IACxB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -74,5 +74,30 @@ describe("continued session replay display filtering", () => {
|
|
|
74
74
|
expect(replayedText).toContain("/help");
|
|
75
75
|
expect(replayedText).toContain("Here are the available commands.");
|
|
76
76
|
});
|
|
77
|
+
it("uses provenance before role or legacy prefixes", () => {
|
|
78
|
+
const persisted = [
|
|
79
|
+
{
|
|
80
|
+
role: "user",
|
|
81
|
+
content: "generated control with ordinary text",
|
|
82
|
+
provenance: { source: "runtime", kind: "automation", visibility: "hidden" },
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
role: "user",
|
|
86
|
+
content: "queued follow-up",
|
|
87
|
+
provenance: { source: "human", kind: "steering", visibility: "transcript" },
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
role: "assistant",
|
|
91
|
+
content: "generated acknowledgement",
|
|
92
|
+
provenance: { source: "runtime", kind: "compaction_ack", visibility: "hidden" },
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
role: "user",
|
|
96
|
+
content: "summary without prefix",
|
|
97
|
+
provenance: { source: "runtime", kind: "compaction_summary", visibility: "summary" },
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
expect(replayTexts(persisted)).toEqual(["queued follow-up", "summary without prefix"]);
|
|
101
|
+
});
|
|
77
102
|
});
|
|
78
103
|
//# sourceMappingURL=session-restore-display.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-restore-display.test.js","sourceRoot":"","sources":["../../src/core/session-restore-display.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session-restore-display.test.js","sourceRoot":"","sources":["../../src/core/session-restore-display.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-storage-fd-leak.test.d.ts","sourceRoot":"","sources":["../../src/core/session-storage-fd-leak.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { createWriteStream } from "node:fs";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { createInterface } from "node:readline";
|
|
7
|
+
import { createGzip } from "node:zlib";
|
|
8
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
9
|
+
import { openSessionReadStream } from "./session-storage.js";
|
|
10
|
+
/**
|
|
11
|
+
* Regression cover for a file-descriptor leak in archived session reads.
|
|
12
|
+
*
|
|
13
|
+
* `openSessionReadStream` returns `source.pipe(createGunzip())`. `.pipe()` does
|
|
14
|
+
* not propagate destroy() upstream, so tearing down only the returned stream —
|
|
15
|
+
* the intuitive cleanup, and what the session listing used to do — leaves the
|
|
16
|
+
* source ReadStream's fd open with no reference able to close it.
|
|
17
|
+
*
|
|
18
|
+
* It leaked one fd per archived session per listing, and session listing walks
|
|
19
|
+
* every session on the machine: a real install was found holding 814 stranded
|
|
20
|
+
* descriptors across 211 archives. Nothing failed loudly, it just accrued until
|
|
21
|
+
* the process hit its descriptor ceiling.
|
|
22
|
+
*
|
|
23
|
+
* The test asserts on real open descriptors rather than stream state, because
|
|
24
|
+
* the bug is precisely that the stream object *looks* destroyed while its fd
|
|
25
|
+
* is not.
|
|
26
|
+
*/
|
|
27
|
+
describe("openSessionReadStream fd hygiene", () => {
|
|
28
|
+
let dir;
|
|
29
|
+
let archivePath;
|
|
30
|
+
const openFdCount = () => {
|
|
31
|
+
// lsof is POSIX-only; the suite skips elsewhere.
|
|
32
|
+
const out = execFileSync("lsof", ["-p", String(process.pid)], {
|
|
33
|
+
encoding: "utf8",
|
|
34
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
35
|
+
});
|
|
36
|
+
return out.split("\n").filter((line) => line.includes(archivePath)).length;
|
|
37
|
+
};
|
|
38
|
+
beforeAll(async () => {
|
|
39
|
+
dir = await fs.mkdtemp(path.join(os.tmpdir(), "ez-session-fd-"));
|
|
40
|
+
archivePath = path.join(dir, "leak-probe.jsonl.gz");
|
|
41
|
+
await new Promise((resolve, reject) => {
|
|
42
|
+
const gzip = createGzip();
|
|
43
|
+
const out = createWriteStream(archivePath);
|
|
44
|
+
out.on("close", () => resolve());
|
|
45
|
+
out.on("error", reject);
|
|
46
|
+
gzip.on("error", reject);
|
|
47
|
+
gzip.pipe(out);
|
|
48
|
+
gzip.write(`${JSON.stringify({ type: "session", id: "probe" })}\n`);
|
|
49
|
+
// Comfortably more than the reader consumes, so the early exit is real
|
|
50
|
+
// and backpressure leaves the source mid-file rather than drained.
|
|
51
|
+
for (let i = 0; i < 20_000; i++) {
|
|
52
|
+
gzip.write(`${JSON.stringify({ type: "message", i, pad: "x".repeat(120) })}\n`);
|
|
53
|
+
}
|
|
54
|
+
gzip.end();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
afterAll(async () => {
|
|
58
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
59
|
+
});
|
|
60
|
+
it.skipIf(process.platform === "win32")("leaves no descriptor behind when a partial read stops early", async () => {
|
|
61
|
+
const before = openFdCount();
|
|
62
|
+
for (let i = 0; i < 40; i++) {
|
|
63
|
+
const { stream, close } = await openSessionReadStream(archivePath);
|
|
64
|
+
const rl = createInterface({ input: stream, crlfDelay: Infinity });
|
|
65
|
+
try {
|
|
66
|
+
let lines = 0;
|
|
67
|
+
for await (const _line of rl) {
|
|
68
|
+
if (++lines > 5)
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
rl.close();
|
|
74
|
+
close();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Destroy is synchronous to request but the 'close' event is not.
|
|
78
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
79
|
+
expect(openFdCount()).toBe(before);
|
|
80
|
+
});
|
|
81
|
+
it.skipIf(process.platform === "win32")("leaves no descriptor behind when the whole archive is read", async () => {
|
|
82
|
+
const before = openFdCount();
|
|
83
|
+
for (let i = 0; i < 10; i++) {
|
|
84
|
+
const { stream, close } = await openSessionReadStream(archivePath);
|
|
85
|
+
const rl = createInterface({ input: stream, crlfDelay: Infinity });
|
|
86
|
+
try {
|
|
87
|
+
for await (const _line of rl) {
|
|
88
|
+
// Drain.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
rl.close();
|
|
93
|
+
close(); // Idempotent after a natural end-of-stream.
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
97
|
+
expect(openFdCount()).toBe(before);
|
|
98
|
+
});
|
|
99
|
+
it("yields the archive's decompressed contents", async () => {
|
|
100
|
+
const { stream, close } = await openSessionReadStream(archivePath);
|
|
101
|
+
const rl = createInterface({ input: stream, crlfDelay: Infinity });
|
|
102
|
+
let header;
|
|
103
|
+
try {
|
|
104
|
+
for await (const line of rl) {
|
|
105
|
+
header = JSON.parse(line);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
rl.close();
|
|
111
|
+
close();
|
|
112
|
+
}
|
|
113
|
+
expect(header).toEqual({ type: "session", id: "probe" });
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=session-storage-fd-leak.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-storage-fd-leak.test.js","sourceRoot":"","sources":["../../src/core/session-storage-fd-leak.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,8 +7,8 @@ export declare const SESSION_MEDIA_MARKER_VERSION = 1;
|
|
|
7
7
|
export declare const SESSION_PLAIN_SUFFIX = ".jsonl";
|
|
8
8
|
export declare const SESSION_ARCHIVE_SUFFIX = ".jsonl.gz";
|
|
9
9
|
export declare const SESSION_ASSET_SUFFIX = ".jsonl.assets";
|
|
10
|
-
export declare const SESSION_TEMP_MARKER = ".
|
|
11
|
-
declare const REDIRECT_TYPE = "
|
|
10
|
+
export declare const SESSION_TEMP_MARKER = ".ez-session-tmp-";
|
|
11
|
+
declare const REDIRECT_TYPE = "ez_session_redirect";
|
|
12
12
|
export interface SessionRedirect {
|
|
13
13
|
type: typeof REDIRECT_TYPE;
|
|
14
14
|
version: typeof SESSION_REDIRECT_VERSION;
|
|
@@ -41,9 +41,29 @@ export declare function sessionGroupPaths(filePath: string): {
|
|
|
41
41
|
export declare function temporarySiblingPath(filePath: string): string;
|
|
42
42
|
export declare function resolveSessionPath(filePath: string): Promise<string>;
|
|
43
43
|
export declare function isGzipSessionPath(filePath: string): Promise<boolean>;
|
|
44
|
+
/**
|
|
45
|
+
* Open a session transcript for reading, transparently gunzipping archives.
|
|
46
|
+
*
|
|
47
|
+
* Returns `close()` alongside the stream because tearing down a gzip read is a
|
|
48
|
+
* trap: `source.pipe(gunzip)` leaves the source unreachable, and `.pipe()` does
|
|
49
|
+
* NOT propagate destroy() upstream. Destroying only the returned stream — the
|
|
50
|
+
* intuitive cleanup — severs the pipe before the source can be torn down and
|
|
51
|
+
* orphans its file descriptor forever.
|
|
52
|
+
*
|
|
53
|
+
* Measured on the shipped Node 22.12 runtime, 100 partial reads:
|
|
54
|
+
* destroy(gunzip) only ....... 10 leaked fds
|
|
55
|
+
* destroy(gunzip) + source ... 0 leaked fds
|
|
56
|
+
*
|
|
57
|
+
* A bare `break` out of `for await` is safe on its own (readline's iterator
|
|
58
|
+
* return() tears down the whole chain), but any explicit teardown must go
|
|
59
|
+
* through `close()` so both ends are destroyed together. Callers that stop
|
|
60
|
+
* early should always call it; destroy() is idempotent, so calling it after a
|
|
61
|
+
* natural end-of-stream is harmless.
|
|
62
|
+
*/
|
|
44
63
|
export declare function openSessionReadStream(filePath: string): Promise<{
|
|
45
64
|
path: string;
|
|
46
65
|
stream: Readable;
|
|
66
|
+
close: () => void;
|
|
47
67
|
}>;
|
|
48
68
|
export declare function thawSessionArchive(filePath: string): Promise<string>;
|
|
49
69
|
export declare function normalizeSessionEntryForStorage<T>(entry: T, sessionPath: string, metrics?: StorageNormalizationMetrics): Promise<T | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-storage.d.ts","sourceRoot":"","sources":["../../src/core/session-storage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK5C,eAAO,MAAM,6BAA6B,QAAS,CAAC;AACpD,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAC7C,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAClD,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AACpD,eAAO,MAAM,mBAAmB,qBAAqB,CAAC;AAEtD,QAAA,MAAM,aAAa,wBAAwB,CAAC;AAK5C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,aAAa,CAAC;IAC3B,OAAO,EAAE,OAAO,wBAAwB,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAqB,SAAQ,2BAA2B;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,gCAAgC,IAAI,2BAA2B,CAO9E;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAOA;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK7D;AAuCD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW1E;AAED,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU1E;AAED,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"session-storage.d.ts","sourceRoot":"","sources":["../../src/core/session-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,9 +13,9 @@ export const SESSION_MEDIA_MARKER_VERSION = 1;
|
|
|
13
13
|
export const SESSION_PLAIN_SUFFIX = ".jsonl";
|
|
14
14
|
export const SESSION_ARCHIVE_SUFFIX = ".jsonl.gz";
|
|
15
15
|
export const SESSION_ASSET_SUFFIX = ".jsonl.assets";
|
|
16
|
-
export const SESSION_TEMP_MARKER = ".
|
|
17
|
-
const REDIRECT_TYPE = "
|
|
18
|
-
const MEDIA_MARKER_PREFIX = `
|
|
16
|
+
export const SESSION_TEMP_MARKER = ".ez-session-tmp-";
|
|
17
|
+
const REDIRECT_TYPE = "ez_session_redirect";
|
|
18
|
+
const MEDIA_MARKER_PREFIX = `ez-session-asset:v${SESSION_MEDIA_MARKER_VERSION}:`;
|
|
19
19
|
const SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
20
20
|
const MAX_REDIRECT_BYTES = 4096;
|
|
21
21
|
export function emptyStorageNormalizationMetrics() {
|
|
@@ -112,13 +112,40 @@ export async function isGzipSessionPath(filePath) {
|
|
|
112
112
|
await handle.close();
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Open a session transcript for reading, transparently gunzipping archives.
|
|
117
|
+
*
|
|
118
|
+
* Returns `close()` alongside the stream because tearing down a gzip read is a
|
|
119
|
+
* trap: `source.pipe(gunzip)` leaves the source unreachable, and `.pipe()` does
|
|
120
|
+
* NOT propagate destroy() upstream. Destroying only the returned stream — the
|
|
121
|
+
* intuitive cleanup — severs the pipe before the source can be torn down and
|
|
122
|
+
* orphans its file descriptor forever.
|
|
123
|
+
*
|
|
124
|
+
* Measured on the shipped Node 22.12 runtime, 100 partial reads:
|
|
125
|
+
* destroy(gunzip) only ....... 10 leaked fds
|
|
126
|
+
* destroy(gunzip) + source ... 0 leaked fds
|
|
127
|
+
*
|
|
128
|
+
* A bare `break` out of `for await` is safe on its own (readline's iterator
|
|
129
|
+
* return() tears down the whole chain), but any explicit teardown must go
|
|
130
|
+
* through `close()` so both ends are destroyed together. Callers that stop
|
|
131
|
+
* early should always call it; destroy() is idempotent, so calling it after a
|
|
132
|
+
* natural end-of-stream is harmless.
|
|
133
|
+
*/
|
|
115
134
|
export async function openSessionReadStream(filePath) {
|
|
116
135
|
const resolved = await resolveSessionPath(filePath);
|
|
117
136
|
const input = createReadStream(resolved);
|
|
118
137
|
if (await isGzipSessionPath(resolved)) {
|
|
119
|
-
|
|
138
|
+
const stream = input.pipe(createGunzip());
|
|
139
|
+
return {
|
|
140
|
+
path: resolved,
|
|
141
|
+
stream,
|
|
142
|
+
close: () => {
|
|
143
|
+
stream.destroy();
|
|
144
|
+
input.destroy();
|
|
145
|
+
},
|
|
146
|
+
};
|
|
120
147
|
}
|
|
121
|
-
return { path: resolved, stream: input };
|
|
148
|
+
return { path: resolved, stream: input, close: () => input.destroy() };
|
|
122
149
|
}
|
|
123
150
|
/**
|
|
124
151
|
* Flush a file's contents to disk before it is renamed into place.
|
|
@@ -153,12 +180,48 @@ async function syncFile(filePath) {
|
|
|
153
180
|
await handle.close();
|
|
154
181
|
}
|
|
155
182
|
}
|
|
183
|
+
const WINDOWS_REPLACE_RETRY_CODES = new Set(["EACCES", "EBUSY", "EPERM"]);
|
|
184
|
+
async function retryWindowsReplace(operation) {
|
|
185
|
+
const maxAttempts = process.platform === "win32" ? 10 : 1;
|
|
186
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
187
|
+
try {
|
|
188
|
+
await operation();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
const code = error.code;
|
|
193
|
+
if (!code || !WINDOWS_REPLACE_RETRY_CODES.has(code) || attempt === maxAttempts)
|
|
194
|
+
throw error;
|
|
195
|
+
await new Promise((resolve) => setTimeout(resolve, attempt * 25));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async function replaceFile(tempPath, filePath) {
|
|
200
|
+
try {
|
|
201
|
+
await retryWindowsReplace(() => fs.rename(tempPath, filePath));
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
const code = error.code;
|
|
205
|
+
if (process.platform !== "win32" || !code || !WINDOWS_REPLACE_RETRY_CODES.has(code)) {
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
// Windows cannot atomically replace some existing/open files. Once the
|
|
209
|
+
// destination lock clears, remove the old copy and install the durable temp.
|
|
210
|
+
await retryWindowsReplace(async () => {
|
|
211
|
+
await fs.unlink(filePath).catch((unlinkError) => {
|
|
212
|
+
if (unlinkError.code !== "ENOENT")
|
|
213
|
+
throw unlinkError;
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
await retryWindowsReplace(() => fs.rename(tempPath, filePath));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
156
219
|
async function atomicWrite(filePath, content) {
|
|
157
220
|
const tempPath = temporarySiblingPath(filePath);
|
|
158
221
|
try {
|
|
159
222
|
await fs.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
|
|
160
223
|
await syncFile(tempPath);
|
|
161
|
-
await
|
|
224
|
+
await replaceFile(tempPath, filePath);
|
|
162
225
|
}
|
|
163
226
|
finally {
|
|
164
227
|
await fs.unlink(tempPath).catch(() => { });
|
|
@@ -235,7 +298,7 @@ export async function thawSessionArchive(filePath) {
|
|
|
235
298
|
if (after.size !== before.size || after.mtimeMs !== before.mtimeMs) {
|
|
236
299
|
throw new Error(`Session archive changed while thawing: ${archivePath}`);
|
|
237
300
|
}
|
|
238
|
-
await
|
|
301
|
+
await replaceFile(tempPath, plainPath);
|
|
239
302
|
await fs.utimes(plainPath, before.atime, before.mtime);
|
|
240
303
|
await writeRedirect(archivePath, plainPath);
|
|
241
304
|
return plainPath;
|
|
@@ -258,7 +321,7 @@ function mediaMarker(sha256) {
|
|
|
258
321
|
return `${MEDIA_MARKER_PREFIX}${sha256}`;
|
|
259
322
|
}
|
|
260
323
|
function parseMediaMarker(value) {
|
|
261
|
-
if (typeof value !== "string" || !value.startsWith("
|
|
324
|
+
if (typeof value !== "string" || !value.startsWith("ez-session-asset:"))
|
|
262
325
|
return null;
|
|
263
326
|
if (!value.startsWith(MEDIA_MARKER_PREFIX))
|
|
264
327
|
return { valid: false };
|
|
@@ -544,7 +607,7 @@ export async function archiveColdSession(sessionPath) {
|
|
|
544
607
|
if (after.size !== before.size || after.mtimeMs !== before.mtimeMs) {
|
|
545
608
|
throw new Error(`Session changed while archiving: ${plainPath}`);
|
|
546
609
|
}
|
|
547
|
-
await
|
|
610
|
+
await replaceFile(gzipTemp, archivePath);
|
|
548
611
|
await fs.utimes(archivePath, before.atime, before.mtime);
|
|
549
612
|
await writeRedirect(plainPath, archivePath);
|
|
550
613
|
const archiveStat = await fs.stat(archivePath);
|