@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.72e3af2a
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/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
- package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
- package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
- package/dist/resources/extensions/gsd/auto-prompts.js +26 -11
- package/dist/resources/extensions/gsd/auto-recovery.js +6 -507
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +38 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +6 -1
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +10 -19
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +68 -10
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/commands-context.js +19 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -10
- package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
- package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
- package/dist/resources/extensions/gsd/db/queries.js +60 -0
- package/dist/resources/extensions/gsd/db-workspace.js +55 -3
- package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
- package/dist/resources/extensions/gsd/exec-sandbox.js +45 -9
- package/dist/resources/extensions/gsd/forensics.js +2 -32
- package/dist/resources/extensions/gsd/git-service.js +4 -4
- package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
- package/dist/resources/extensions/gsd/health-widget.js +55 -29
- package/dist/resources/extensions/gsd/layout-policy.js +3 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
- package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
- package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
- package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
- package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/dist/resources/extensions/gsd/quick.js +45 -2
- package/dist/resources/extensions/gsd/session-forensics.js +11 -1
- package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
- package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
- package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
- package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
- package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
- package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
- package/dist/resources/extensions/gsd/state.js +12 -611
- package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
- package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
- package/dist/resources/extensions/gsd/unit-registry.js +32 -4
- package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
- package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
- package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
- package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +1 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +2 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +3 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts +2 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +2 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
- package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
- package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/README.md +1 -1
- package/packages/mcp-server/dist/server.d.ts +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +3 -3
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +34 -20
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/README.md +3 -2
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme-schema.d.ts +75 -75
- package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/theme/theme-schema.js +1 -1
- package/pkg/dist/theme/theme-schema.js.map +1 -1
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +11 -7
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
- package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
- package/src/resources/extensions/gsd/auto/session.ts +5 -0
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +21 -23
- package/src/resources/extensions/gsd/auto-prompts.ts +38 -12
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -508
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +43 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +6 -1
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -19
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +74 -10
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/commands-context.ts +18 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +14 -9
- package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
- package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
- package/src/resources/extensions/gsd/db/queries.ts +79 -0
- package/src/resources/extensions/gsd/db-workspace.ts +61 -3
- package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/forensics.ts +2 -33
- package/src/resources/extensions/gsd/git-service.ts +5 -5
- package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
- package/src/resources/extensions/gsd/health-widget.ts +69 -32
- package/src/resources/extensions/gsd/layout-policy.ts +2 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
- package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
- package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
- package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/src/resources/extensions/gsd/quick.ts +43 -2
- package/src/resources/extensions/gsd/session-forensics.ts +11 -1
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
- package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
- package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
- package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
- package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
- package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
- package/src/resources/extensions/gsd/state.ts +32 -732
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
- package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +119 -1
- package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
- package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
- package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
- package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
- package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
- package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
- package/src/resources/extensions/gsd/unit-registry.ts +32 -4
- package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
- package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
- package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
- package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
- package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_ssgManifest.js +0 -0
|
@@ -1,457 +1,20 @@
|
|
|
1
1
|
import { uuidv7 } from "@gsd/pi-agent-core";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { readdir, readFile, stat } from "fs/promises";
|
|
2
|
+
import { appendFileSync, existsSync, mkdirSync, writeFileSync, } from "fs";
|
|
3
|
+
import { readdir } from "fs/promises";
|
|
5
4
|
import { join, resolve } from "path";
|
|
6
|
-
import {
|
|
5
|
+
import { getSessionsDir } from "../config.js";
|
|
7
6
|
import { normalizePath, resolvePath } from "../utils/paths.js";
|
|
8
|
-
import {
|
|
9
|
-
|
|
7
|
+
import { CURRENT_SESSION_VERSION, } from "./session-manager-types.js";
|
|
8
|
+
import { buildSessionContext } from "./session-manager-context.js";
|
|
9
|
+
import { buildSessionInfosWithConcurrency, findMostRecentSession, getDefaultSessionDir, listSessionsFromDir, loadEntriesFromFile, } from "./session-manager-list.js";
|
|
10
|
+
import { generateSessionEntryId, migrateToCurrentVersion, } from "./session-manager-migration.js";
|
|
11
|
+
export { CURRENT_SESSION_VERSION, } from "./session-manager-types.js";
|
|
12
|
+
export { buildSessionContext, getLatestCompactionEntry, } from "./session-manager-context.js";
|
|
13
|
+
export { findMostRecentSession, getDefaultSessionDir, listSessionsFromDir, loadEntriesFromFile, } from "./session-manager-list.js";
|
|
14
|
+
export { migrateSessionEntries, parseSessionEntries, } from "./session-manager-migration.js";
|
|
10
15
|
function createSessionId() {
|
|
11
16
|
return uuidv7();
|
|
12
17
|
}
|
|
13
|
-
/** Generate a unique short ID (8 hex chars, collision-checked) */
|
|
14
|
-
function generateId(byId) {
|
|
15
|
-
for (let i = 0; i < 100; i++) {
|
|
16
|
-
const id = randomUUID().slice(0, 8);
|
|
17
|
-
if (!byId.has(id))
|
|
18
|
-
return id;
|
|
19
|
-
}
|
|
20
|
-
// Fallback to full UUID if somehow we have collisions
|
|
21
|
-
return randomUUID();
|
|
22
|
-
}
|
|
23
|
-
/** Migrate v1 → v2: add id/parentId tree structure. Mutates in place. */
|
|
24
|
-
function migrateV1ToV2(entries) {
|
|
25
|
-
const ids = new Set();
|
|
26
|
-
let prevId = null;
|
|
27
|
-
for (const entry of entries) {
|
|
28
|
-
if (entry.type === "session") {
|
|
29
|
-
entry.version = 2;
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
entry.id = generateId(ids);
|
|
33
|
-
entry.parentId = prevId;
|
|
34
|
-
prevId = entry.id;
|
|
35
|
-
// Convert firstKeptEntryIndex to firstKeptEntryId for compaction
|
|
36
|
-
if (entry.type === "compaction") {
|
|
37
|
-
const comp = entry;
|
|
38
|
-
if (typeof comp.firstKeptEntryIndex === "number") {
|
|
39
|
-
const targetEntry = entries[comp.firstKeptEntryIndex];
|
|
40
|
-
if (targetEntry && targetEntry.type !== "session") {
|
|
41
|
-
comp.firstKeptEntryId = targetEntry.id;
|
|
42
|
-
}
|
|
43
|
-
delete comp.firstKeptEntryIndex;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
/** Migrate v2 → v3: rename hookMessage role to custom. Mutates in place. */
|
|
49
|
-
function migrateV2ToV3(entries) {
|
|
50
|
-
for (const entry of entries) {
|
|
51
|
-
if (entry.type === "session") {
|
|
52
|
-
entry.version = 3;
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
// Update message entries with hookMessage role
|
|
56
|
-
if (entry.type === "message") {
|
|
57
|
-
const msgEntry = entry;
|
|
58
|
-
if (msgEntry.message && msgEntry.message.role === "hookMessage") {
|
|
59
|
-
msgEntry.message.role = "custom";
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Run all necessary migrations to bring entries to current version.
|
|
66
|
-
* Mutates entries in place. Returns true if any migration was applied.
|
|
67
|
-
*/
|
|
68
|
-
function migrateToCurrentVersion(entries) {
|
|
69
|
-
const header = entries.find((e) => e.type === "session");
|
|
70
|
-
const version = header?.version ?? 1;
|
|
71
|
-
if (version >= CURRENT_SESSION_VERSION)
|
|
72
|
-
return false;
|
|
73
|
-
if (version < 2)
|
|
74
|
-
migrateV1ToV2(entries);
|
|
75
|
-
if (version < 3)
|
|
76
|
-
migrateV2ToV3(entries);
|
|
77
|
-
return true;
|
|
78
|
-
}
|
|
79
|
-
/** Exported for testing */
|
|
80
|
-
export function migrateSessionEntries(entries) {
|
|
81
|
-
migrateToCurrentVersion(entries);
|
|
82
|
-
}
|
|
83
|
-
/** Exported for compaction.test.ts */
|
|
84
|
-
export function parseSessionEntries(content) {
|
|
85
|
-
const entries = [];
|
|
86
|
-
const lines = content.trim().split("\n");
|
|
87
|
-
for (const line of lines) {
|
|
88
|
-
if (!line.trim())
|
|
89
|
-
continue;
|
|
90
|
-
try {
|
|
91
|
-
const entry = JSON.parse(line);
|
|
92
|
-
entries.push(entry);
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
// Skip malformed lines
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return entries;
|
|
99
|
-
}
|
|
100
|
-
export function getLatestCompactionEntry(entries) {
|
|
101
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
102
|
-
if (entries[i].type === "compaction") {
|
|
103
|
-
return entries[i];
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Build the session context from entries using tree traversal.
|
|
110
|
-
* If leafId is provided, walks from that entry to root.
|
|
111
|
-
* Handles compaction and branch summaries along the path.
|
|
112
|
-
*/
|
|
113
|
-
export function buildSessionContext(entries, leafId, byId) {
|
|
114
|
-
// Build uuid index if not available
|
|
115
|
-
if (!byId) {
|
|
116
|
-
byId = new Map();
|
|
117
|
-
for (const entry of entries) {
|
|
118
|
-
byId.set(entry.id, entry);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
// Find leaf
|
|
122
|
-
let leaf;
|
|
123
|
-
if (leafId === null) {
|
|
124
|
-
// Explicitly null - return no messages (navigated to before first entry)
|
|
125
|
-
return { messages: [], thinkingLevel: "off", model: null };
|
|
126
|
-
}
|
|
127
|
-
if (leafId) {
|
|
128
|
-
leaf = byId.get(leafId);
|
|
129
|
-
}
|
|
130
|
-
if (!leaf) {
|
|
131
|
-
// Fallback to last entry (when leafId is undefined)
|
|
132
|
-
leaf = entries[entries.length - 1];
|
|
133
|
-
}
|
|
134
|
-
if (!leaf) {
|
|
135
|
-
return { messages: [], thinkingLevel: "off", model: null };
|
|
136
|
-
}
|
|
137
|
-
// Walk from leaf to root, collecting path
|
|
138
|
-
const path = [];
|
|
139
|
-
let current = leaf;
|
|
140
|
-
while (current) {
|
|
141
|
-
path.unshift(current);
|
|
142
|
-
current = current.parentId ? byId.get(current.parentId) : undefined;
|
|
143
|
-
}
|
|
144
|
-
// Extract settings and find compaction
|
|
145
|
-
let thinkingLevel = "off";
|
|
146
|
-
let model = null;
|
|
147
|
-
let compaction = null;
|
|
148
|
-
for (const entry of path) {
|
|
149
|
-
if (entry.type === "thinking_level_change") {
|
|
150
|
-
thinkingLevel = entry.thinkingLevel;
|
|
151
|
-
}
|
|
152
|
-
else if (entry.type === "model_change") {
|
|
153
|
-
model = { provider: entry.provider, modelId: entry.modelId };
|
|
154
|
-
}
|
|
155
|
-
else if (entry.type === "message" && entry.message.role === "assistant") {
|
|
156
|
-
model = { provider: entry.message.provider, modelId: entry.message.model };
|
|
157
|
-
}
|
|
158
|
-
else if (entry.type === "compaction") {
|
|
159
|
-
compaction = entry;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
// Build messages and collect corresponding entries
|
|
163
|
-
// When there's a compaction, we need to:
|
|
164
|
-
// 1. Emit summary first (entry = compaction)
|
|
165
|
-
// 2. Emit kept messages (from firstKeptEntryId up to compaction)
|
|
166
|
-
// 3. Emit messages after compaction
|
|
167
|
-
const messages = [];
|
|
168
|
-
const appendMessage = (entry) => {
|
|
169
|
-
if (entry.type === "message") {
|
|
170
|
-
messages.push(entry.message);
|
|
171
|
-
}
|
|
172
|
-
else if (entry.type === "custom_message") {
|
|
173
|
-
messages.push(createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp));
|
|
174
|
-
}
|
|
175
|
-
else if (entry.type === "branch_summary" && entry.summary) {
|
|
176
|
-
messages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
if (compaction) {
|
|
180
|
-
// Emit summary first
|
|
181
|
-
messages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));
|
|
182
|
-
// Find compaction index in path
|
|
183
|
-
const compactionIdx = path.findIndex((e) => e.type === "compaction" && e.id === compaction.id);
|
|
184
|
-
// Emit kept messages (before compaction, starting from firstKeptEntryId)
|
|
185
|
-
let foundFirstKept = false;
|
|
186
|
-
for (let i = 0; i < compactionIdx; i++) {
|
|
187
|
-
const entry = path[i];
|
|
188
|
-
if (entry.id === compaction.firstKeptEntryId) {
|
|
189
|
-
foundFirstKept = true;
|
|
190
|
-
}
|
|
191
|
-
if (foundFirstKept) {
|
|
192
|
-
appendMessage(entry);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
// Emit messages after compaction
|
|
196
|
-
for (let i = compactionIdx + 1; i < path.length; i++) {
|
|
197
|
-
const entry = path[i];
|
|
198
|
-
appendMessage(entry);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
// No compaction - emit all messages, handle branch summaries and custom messages
|
|
203
|
-
for (const entry of path) {
|
|
204
|
-
appendMessage(entry);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return { messages, thinkingLevel, model };
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Compute the default session directory for a cwd.
|
|
211
|
-
* Encodes cwd into a safe directory name under ~/.pi/agent/sessions/.
|
|
212
|
-
*/
|
|
213
|
-
export function getDefaultSessionDir(cwd, agentDir = getDefaultAgentDir()) {
|
|
214
|
-
const resolvedCwd = resolvePath(cwd);
|
|
215
|
-
const resolvedAgentDir = resolvePath(agentDir);
|
|
216
|
-
const safePath = `--${resolvedCwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
|
|
217
|
-
const sessionDir = join(resolvedAgentDir, "sessions", safePath);
|
|
218
|
-
if (!existsSync(sessionDir)) {
|
|
219
|
-
mkdirSync(sessionDir, { recursive: true });
|
|
220
|
-
}
|
|
221
|
-
return sessionDir;
|
|
222
|
-
}
|
|
223
|
-
/** Exported for testing */
|
|
224
|
-
export function loadEntriesFromFile(filePath) {
|
|
225
|
-
const resolvedFilePath = normalizePath(filePath);
|
|
226
|
-
if (!existsSync(resolvedFilePath))
|
|
227
|
-
return [];
|
|
228
|
-
const content = readFileSync(resolvedFilePath, "utf8");
|
|
229
|
-
const entries = [];
|
|
230
|
-
const lines = content.trim().split("\n");
|
|
231
|
-
for (const line of lines) {
|
|
232
|
-
if (!line.trim())
|
|
233
|
-
continue;
|
|
234
|
-
try {
|
|
235
|
-
const entry = JSON.parse(line);
|
|
236
|
-
entries.push(entry);
|
|
237
|
-
}
|
|
238
|
-
catch {
|
|
239
|
-
// Skip malformed lines
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
// Validate session header
|
|
243
|
-
if (entries.length === 0)
|
|
244
|
-
return entries;
|
|
245
|
-
const header = entries[0];
|
|
246
|
-
if (header.type !== "session" || typeof header.id !== "string") {
|
|
247
|
-
return [];
|
|
248
|
-
}
|
|
249
|
-
return entries;
|
|
250
|
-
}
|
|
251
|
-
function isValidSessionFile(filePath) {
|
|
252
|
-
try {
|
|
253
|
-
const fd = openSync(filePath, "r");
|
|
254
|
-
const buffer = Buffer.alloc(512);
|
|
255
|
-
const bytesRead = readSync(fd, buffer, 0, 512, 0);
|
|
256
|
-
closeSync(fd);
|
|
257
|
-
const firstLine = buffer.toString("utf8", 0, bytesRead).split("\n")[0];
|
|
258
|
-
if (!firstLine)
|
|
259
|
-
return false;
|
|
260
|
-
const header = JSON.parse(firstLine);
|
|
261
|
-
return header.type === "session" && typeof header.id === "string";
|
|
262
|
-
}
|
|
263
|
-
catch {
|
|
264
|
-
return false;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
/** Exported for testing */
|
|
268
|
-
export function findMostRecentSession(sessionDir) {
|
|
269
|
-
const resolvedSessionDir = normalizePath(sessionDir);
|
|
270
|
-
try {
|
|
271
|
-
const files = readdirSync(resolvedSessionDir)
|
|
272
|
-
.filter((f) => f.endsWith(".jsonl"))
|
|
273
|
-
.map((f) => join(resolvedSessionDir, f))
|
|
274
|
-
.filter(isValidSessionFile)
|
|
275
|
-
.map((path) => ({ path, mtime: statSync(path).mtime }))
|
|
276
|
-
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
277
|
-
return files[0]?.path || null;
|
|
278
|
-
}
|
|
279
|
-
catch {
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
function isMessageWithContent(message) {
|
|
284
|
-
return typeof message.role === "string" && "content" in message;
|
|
285
|
-
}
|
|
286
|
-
function extractTextContent(message) {
|
|
287
|
-
const content = message.content;
|
|
288
|
-
if (typeof content === "string") {
|
|
289
|
-
return content;
|
|
290
|
-
}
|
|
291
|
-
return content
|
|
292
|
-
.filter((block) => block.type === "text")
|
|
293
|
-
.map((block) => block.text)
|
|
294
|
-
.join(" ");
|
|
295
|
-
}
|
|
296
|
-
function getLastActivityTime(entries) {
|
|
297
|
-
let lastActivityTime;
|
|
298
|
-
for (const entry of entries) {
|
|
299
|
-
if (entry.type !== "message")
|
|
300
|
-
continue;
|
|
301
|
-
const message = entry.message;
|
|
302
|
-
if (!isMessageWithContent(message))
|
|
303
|
-
continue;
|
|
304
|
-
if (message.role !== "user" && message.role !== "assistant")
|
|
305
|
-
continue;
|
|
306
|
-
const msgTimestamp = message.timestamp;
|
|
307
|
-
if (typeof msgTimestamp === "number") {
|
|
308
|
-
lastActivityTime = Math.max(lastActivityTime ?? 0, msgTimestamp);
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
const entryTimestamp = entry.timestamp;
|
|
312
|
-
if (typeof entryTimestamp === "string") {
|
|
313
|
-
const t = new Date(entryTimestamp).getTime();
|
|
314
|
-
if (!Number.isNaN(t)) {
|
|
315
|
-
lastActivityTime = Math.max(lastActivityTime ?? 0, t);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return lastActivityTime;
|
|
320
|
-
}
|
|
321
|
-
function getSessionModifiedDate(entries, header, statsMtime) {
|
|
322
|
-
const lastActivityTime = getLastActivityTime(entries);
|
|
323
|
-
if (typeof lastActivityTime === "number" && lastActivityTime > 0) {
|
|
324
|
-
return new Date(lastActivityTime);
|
|
325
|
-
}
|
|
326
|
-
const headerTime = typeof header.timestamp === "string" ? new Date(header.timestamp).getTime() : NaN;
|
|
327
|
-
return !Number.isNaN(headerTime) ? new Date(headerTime) : statsMtime;
|
|
328
|
-
}
|
|
329
|
-
async function buildSessionInfo(filePath) {
|
|
330
|
-
try {
|
|
331
|
-
const content = await readFile(filePath, "utf8");
|
|
332
|
-
const entries = [];
|
|
333
|
-
const lines = content.trim().split("\n");
|
|
334
|
-
for (const line of lines) {
|
|
335
|
-
if (!line.trim())
|
|
336
|
-
continue;
|
|
337
|
-
try {
|
|
338
|
-
entries.push(JSON.parse(line));
|
|
339
|
-
}
|
|
340
|
-
catch {
|
|
341
|
-
// Skip malformed lines
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
if (entries.length === 0)
|
|
345
|
-
return null;
|
|
346
|
-
const header = entries[0];
|
|
347
|
-
if (header.type !== "session")
|
|
348
|
-
return null;
|
|
349
|
-
const stats = await stat(filePath);
|
|
350
|
-
let messageCount = 0;
|
|
351
|
-
let firstMessage = "";
|
|
352
|
-
const allMessages = [];
|
|
353
|
-
let name;
|
|
354
|
-
for (const entry of entries) {
|
|
355
|
-
// Extract session name (use latest, including explicit clears)
|
|
356
|
-
if (entry.type === "session_info") {
|
|
357
|
-
const infoEntry = entry;
|
|
358
|
-
name = infoEntry.name?.trim() || undefined;
|
|
359
|
-
}
|
|
360
|
-
if (entry.type !== "message")
|
|
361
|
-
continue;
|
|
362
|
-
messageCount++;
|
|
363
|
-
const message = entry.message;
|
|
364
|
-
if (!isMessageWithContent(message))
|
|
365
|
-
continue;
|
|
366
|
-
if (message.role !== "user" && message.role !== "assistant")
|
|
367
|
-
continue;
|
|
368
|
-
const textContent = extractTextContent(message);
|
|
369
|
-
if (!textContent)
|
|
370
|
-
continue;
|
|
371
|
-
allMessages.push(textContent);
|
|
372
|
-
if (!firstMessage && message.role === "user") {
|
|
373
|
-
firstMessage = textContent;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
const cwd = typeof header.cwd === "string" ? header.cwd : "";
|
|
377
|
-
const parentSessionPath = header.parentSession;
|
|
378
|
-
const modified = getSessionModifiedDate(entries, header, stats.mtime);
|
|
379
|
-
return {
|
|
380
|
-
path: filePath,
|
|
381
|
-
id: header.id,
|
|
382
|
-
cwd,
|
|
383
|
-
name,
|
|
384
|
-
parentSessionPath,
|
|
385
|
-
created: new Date(header.timestamp),
|
|
386
|
-
modified,
|
|
387
|
-
messageCount,
|
|
388
|
-
firstMessage: firstMessage || "(no messages)",
|
|
389
|
-
allMessagesText: allMessages.join(" "),
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
catch {
|
|
393
|
-
return null;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
const MAX_CONCURRENT_SESSION_INFO_LOADS = 10;
|
|
397
|
-
async function buildSessionInfosWithConcurrency(files, onLoaded) {
|
|
398
|
-
const results = new Array(files.length).fill(null);
|
|
399
|
-
const inFlight = new Set();
|
|
400
|
-
let nextIndex = 0;
|
|
401
|
-
const startNext = () => {
|
|
402
|
-
const index = nextIndex++;
|
|
403
|
-
const file = files[index];
|
|
404
|
-
if (!file)
|
|
405
|
-
return;
|
|
406
|
-
let task;
|
|
407
|
-
task = buildSessionInfo(file)
|
|
408
|
-
.then((info) => {
|
|
409
|
-
results[index] = info;
|
|
410
|
-
})
|
|
411
|
-
.catch(() => {
|
|
412
|
-
results[index] = null;
|
|
413
|
-
})
|
|
414
|
-
.finally(() => {
|
|
415
|
-
inFlight.delete(task);
|
|
416
|
-
onLoaded();
|
|
417
|
-
});
|
|
418
|
-
inFlight.add(task);
|
|
419
|
-
};
|
|
420
|
-
while (nextIndex < files.length || inFlight.size > 0) {
|
|
421
|
-
while (nextIndex < files.length && inFlight.size < MAX_CONCURRENT_SESSION_INFO_LOADS) {
|
|
422
|
-
startNext();
|
|
423
|
-
}
|
|
424
|
-
if (inFlight.size > 0) {
|
|
425
|
-
await Promise.race(inFlight);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
return results;
|
|
429
|
-
}
|
|
430
|
-
async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progressTotal) {
|
|
431
|
-
const sessions = [];
|
|
432
|
-
if (!existsSync(dir)) {
|
|
433
|
-
return sessions;
|
|
434
|
-
}
|
|
435
|
-
try {
|
|
436
|
-
const dirEntries = await readdir(dir);
|
|
437
|
-
const files = dirEntries.filter((f) => f.endsWith(".jsonl")).map((f) => join(dir, f));
|
|
438
|
-
const total = progressTotal ?? files.length;
|
|
439
|
-
let loaded = 0;
|
|
440
|
-
const results = await buildSessionInfosWithConcurrency(files, () => {
|
|
441
|
-
loaded++;
|
|
442
|
-
onProgress?.(progressOffset + loaded, total);
|
|
443
|
-
});
|
|
444
|
-
for (const info of results) {
|
|
445
|
-
if (info) {
|
|
446
|
-
sessions.push(info);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
catch {
|
|
451
|
-
// Return empty list on error
|
|
452
|
-
}
|
|
453
|
-
return sessions;
|
|
454
|
-
}
|
|
455
18
|
/**
|
|
456
19
|
* Manages conversation sessions as append-only trees stored in JSONL files.
|
|
457
20
|
*
|
|
@@ -613,7 +176,7 @@ export class SessionManager {
|
|
|
613
176
|
appendMessage(message) {
|
|
614
177
|
const entry = {
|
|
615
178
|
type: "message",
|
|
616
|
-
id:
|
|
179
|
+
id: generateSessionEntryId(this.byId),
|
|
617
180
|
parentId: this.leafId,
|
|
618
181
|
timestamp: new Date().toISOString(),
|
|
619
182
|
message,
|
|
@@ -625,7 +188,7 @@ export class SessionManager {
|
|
|
625
188
|
appendThinkingLevelChange(thinkingLevel) {
|
|
626
189
|
const entry = {
|
|
627
190
|
type: "thinking_level_change",
|
|
628
|
-
id:
|
|
191
|
+
id: generateSessionEntryId(this.byId),
|
|
629
192
|
parentId: this.leafId,
|
|
630
193
|
timestamp: new Date().toISOString(),
|
|
631
194
|
thinkingLevel,
|
|
@@ -637,7 +200,7 @@ export class SessionManager {
|
|
|
637
200
|
appendModelChange(provider, modelId) {
|
|
638
201
|
const entry = {
|
|
639
202
|
type: "model_change",
|
|
640
|
-
id:
|
|
203
|
+
id: generateSessionEntryId(this.byId),
|
|
641
204
|
parentId: this.leafId,
|
|
642
205
|
timestamp: new Date().toISOString(),
|
|
643
206
|
provider,
|
|
@@ -650,7 +213,7 @@ export class SessionManager {
|
|
|
650
213
|
appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook) {
|
|
651
214
|
const entry = {
|
|
652
215
|
type: "compaction",
|
|
653
|
-
id:
|
|
216
|
+
id: generateSessionEntryId(this.byId),
|
|
654
217
|
parentId: this.leafId,
|
|
655
218
|
timestamp: new Date().toISOString(),
|
|
656
219
|
summary,
|
|
@@ -668,7 +231,7 @@ export class SessionManager {
|
|
|
668
231
|
type: "custom",
|
|
669
232
|
customType,
|
|
670
233
|
data,
|
|
671
|
-
id:
|
|
234
|
+
id: generateSessionEntryId(this.byId),
|
|
672
235
|
parentId: this.leafId,
|
|
673
236
|
timestamp: new Date().toISOString(),
|
|
674
237
|
};
|
|
@@ -679,7 +242,7 @@ export class SessionManager {
|
|
|
679
242
|
appendSessionInfo(name) {
|
|
680
243
|
const entry = {
|
|
681
244
|
type: "session_info",
|
|
682
|
-
id:
|
|
245
|
+
id: generateSessionEntryId(this.byId),
|
|
683
246
|
parentId: this.leafId,
|
|
684
247
|
timestamp: new Date().toISOString(),
|
|
685
248
|
name: name.trim(),
|
|
@@ -715,7 +278,7 @@ export class SessionManager {
|
|
|
715
278
|
content,
|
|
716
279
|
display,
|
|
717
280
|
details,
|
|
718
|
-
id:
|
|
281
|
+
id: generateSessionEntryId(this.byId),
|
|
719
282
|
parentId: this.leafId,
|
|
720
283
|
timestamp: new Date().toISOString(),
|
|
721
284
|
};
|
|
@@ -763,7 +326,7 @@ export class SessionManager {
|
|
|
763
326
|
}
|
|
764
327
|
const entry = {
|
|
765
328
|
type: "label",
|
|
766
|
-
id:
|
|
329
|
+
id: generateSessionEntryId(this.byId),
|
|
767
330
|
parentId: this.leafId,
|
|
768
331
|
timestamp: new Date().toISOString(),
|
|
769
332
|
targetId,
|
|
@@ -894,7 +457,7 @@ export class SessionManager {
|
|
|
894
457
|
this.leafId = branchFromId;
|
|
895
458
|
const entry = {
|
|
896
459
|
type: "branch_summary",
|
|
897
|
-
id:
|
|
460
|
+
id: generateSessionEntryId(this.byId),
|
|
898
461
|
parentId: branchFromId,
|
|
899
462
|
timestamp: new Date().toISOString(),
|
|
900
463
|
fromId: branchFromId ?? "root",
|
|
@@ -946,7 +509,7 @@ export class SessionManager {
|
|
|
946
509
|
for (const { targetId, label, timestamp: labelTimestamp } of labelsToWrite) {
|
|
947
510
|
const labelEntry = {
|
|
948
511
|
type: "label",
|
|
949
|
-
id:
|
|
512
|
+
id: generateSessionEntryId(new Set(pathEntryIds)),
|
|
950
513
|
parentId,
|
|
951
514
|
timestamp: labelTimestamp,
|
|
952
515
|
targetId,
|
|
@@ -981,7 +544,7 @@ export class SessionManager {
|
|
|
981
544
|
for (const { targetId, label, timestamp: labelTimestamp } of labelsToWrite) {
|
|
982
545
|
const labelEntry = {
|
|
983
546
|
type: "label",
|
|
984
|
-
id:
|
|
547
|
+
id: generateSessionEntryId(new Set([...pathEntryIds, ...labelEntries.map((e) => e.id)])),
|
|
985
548
|
parentId,
|
|
986
549
|
timestamp: labelTimestamp,
|
|
987
550
|
targetId,
|