gsd-pi 2.80.0-dev.8b3a59f5c → 2.80.0-dev.b2a374d5b
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/GSD-WORKFLOW.md +2 -2
- package/dist/resources/extensions/gsd/auto/loop.js +32 -1
- package/dist/resources/extensions/gsd/auto/phases.js +37 -30
- package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
- package/dist/resources/extensions/gsd/auto-prompts.js +111 -1
- package/dist/resources/extensions/gsd/auto-start.js +2 -3
- package/dist/resources/extensions/gsd/auto.js +16 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +21 -0
- package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
- package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
- package/dist/resources/extensions/gsd/detection.js +106 -0
- package/dist/resources/extensions/gsd/guided-flow.js +63 -12
- package/dist/resources/extensions/gsd/migrate/command.js +40 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +7 -8
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/dist/resources/extensions/gsd/quick.js +34 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
- package/dist/resources/extensions/gsd/unit-runtime.js +11 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
- 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 +12 -12
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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.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/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/middleware-build-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/package.json +4 -2
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +3 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +32 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +17 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +99 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +25 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +25 -20
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +2 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +26 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +15 -5
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +53 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +21 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +3 -0
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +38 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
- package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +110 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +19 -1
- package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +39 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +25 -20
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +2 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +2 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +33 -13
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +56 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +24 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +25 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +17 -7
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/tui.ts +19 -7
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +36 -27
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/src/resources/GSD-WORKFLOW.md +2 -2
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +50 -8
- package/src/resources/extensions/gsd/auto/phases.ts +42 -28
- package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
- package/src/resources/extensions/gsd/auto-prompts.ts +116 -1
- package/src/resources/extensions/gsd/auto-start.ts +7 -6
- package/src/resources/extensions/gsd/auto.ts +23 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
- package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
- package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
- package/src/resources/extensions/gsd/detection.ts +128 -0
- package/src/resources/extensions/gsd/guided-flow.ts +66 -12
- package/src/resources/extensions/gsd/migrate/command.ts +47 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +7 -8
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/src/resources/extensions/gsd/quick.ts +37 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
- package/src/resources/extensions/gsd/unit-runtime.ts +14 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
- /package/dist/web/standalone/.next/static/{k-MDjzPMF62Rg1-FR437h → FU0iL9dhdc2IBzEYBDOlY}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{k-MDjzPMF62Rg1-FR437h → FU0iL9dhdc2IBzEYBDOlY}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// GSD2 TUI Tests - Runtime coverage for tool-card cleanup and success notification rendering.
|
|
1
2
|
// Runtime regression tests for the post-compaction tool-card cleanup and the
|
|
2
3
|
// green-bordered success-notification rendering. Replaces the source-grep
|
|
3
4
|
// `src/tests/tui-running-and-success-box.test.ts` that was deleted in #4875
|
|
@@ -74,7 +75,7 @@ function makeMockTUI(): MockTui {
|
|
|
74
75
|
// ─── Bug 1: tool cards stuck in "Running" after compaction ──────────────
|
|
75
76
|
|
|
76
77
|
describe("ToolExecutionComponent post-compaction cleanup", () => {
|
|
77
|
-
it("renders '
|
|
78
|
+
it("renders 'running' status while the tool call has no result", () => {
|
|
78
79
|
// Baseline: a freshly-constructed component (mid-stream) must show
|
|
79
80
|
// the running badge — this is the state we need to flip OUT of when
|
|
80
81
|
// compaction removes the result message.
|
|
@@ -88,12 +89,12 @@ describe("ToolExecutionComponent post-compaction cleanup", () => {
|
|
|
88
89
|
);
|
|
89
90
|
const rendered = c.render(60).map(stripAnsi).join("\n");
|
|
90
91
|
assert.ok(
|
|
91
|
-
rendered.includes("
|
|
92
|
-
"freshly constructed component should render '
|
|
92
|
+
rendered.includes("running"),
|
|
93
|
+
"freshly constructed component should render 'running' badge",
|
|
93
94
|
);
|
|
94
95
|
});
|
|
95
96
|
|
|
96
|
-
it("markHistoricalNoResult flips a stuck tool card OUT of '
|
|
97
|
+
it("markHistoricalNoResult flips a stuck tool card OUT of 'running'", () => {
|
|
97
98
|
// Real bug: after session-history replay (post-compaction or session
|
|
98
99
|
// switch), tool calls without matching tool_result messages stay in
|
|
99
100
|
// isPartial = true forever. markHistoricalNoResult must produce a
|
|
@@ -111,13 +112,13 @@ describe("ToolExecutionComponent post-compaction cleanup", () => {
|
|
|
111
112
|
|
|
112
113
|
const rendered = c.render(60).map(stripAnsi).join("\n");
|
|
113
114
|
assert.ok(
|
|
114
|
-
!rendered.includes("
|
|
115
|
-
"after markHistoricalNoResult, the tool card must NOT render '
|
|
115
|
+
!rendered.includes("running"),
|
|
116
|
+
"after markHistoricalNoResult, the tool card must NOT render 'running' -- got:\n" +
|
|
116
117
|
rendered,
|
|
117
118
|
);
|
|
118
119
|
assert.ok(
|
|
119
|
-
rendered.includes("
|
|
120
|
-
"flipped card should render '
|
|
120
|
+
rendered.includes("success"),
|
|
121
|
+
"flipped card should render 'success' status (no-result success)",
|
|
121
122
|
);
|
|
122
123
|
});
|
|
123
124
|
|
|
@@ -145,7 +146,7 @@ describe("ToolExecutionComponent post-compaction cleanup", () => {
|
|
|
145
146
|
);
|
|
146
147
|
|
|
147
148
|
const before = c.render(60).map(stripAnsi).join("\n");
|
|
148
|
-
assert.ok(before.includes("
|
|
149
|
+
assert.ok(before.includes("success"), "after complete(), card shows 'success'");
|
|
149
150
|
|
|
150
151
|
c.markHistoricalNoResult(); // must early-return
|
|
151
152
|
const after = c.render(60).map(stripAnsi).join("\n");
|
|
@@ -107,9 +107,9 @@ function renderToolFrame(
|
|
|
107
107
|
|
|
108
108
|
const borderColor = opts.tone === "error" ? "toolError" : opts.tone === "pending" ? "toolRunning" : "toolSuccess";
|
|
109
109
|
const topColor = borderColor;
|
|
110
|
-
const labelColor = opts.tone === "error" ? "toolError" : "
|
|
110
|
+
const labelColor = opts.tone === "error" ? "toolError" : opts.tone === "pending" ? "toolRunning" : "toolSuccess";
|
|
111
111
|
const statusColor = opts.tone === "error" ? "toolError" : opts.tone === "pending" ? "toolRunning" : "toolSuccess";
|
|
112
|
-
const leftStyled = theme.fg(labelColor, theme.bold(
|
|
112
|
+
const leftStyled = theme.fg(labelColor, theme.bold(opts.label));
|
|
113
113
|
const rightStyled = theme.fg(statusColor, opts.status);
|
|
114
114
|
const gap = Math.max(1, outerWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled));
|
|
115
115
|
const headerRow = `${leftStyled}${" ".repeat(gap)}${rightStyled}`;
|
|
@@ -128,6 +128,27 @@ function renderToolFrame(
|
|
|
128
128
|
.render(bodyLines, outerWidth);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
function renderCollapsedToolRow(
|
|
132
|
+
label: string,
|
|
133
|
+
status: string,
|
|
134
|
+
width: number,
|
|
135
|
+
tone: Extract<ToolFrameTone, "success">,
|
|
136
|
+
): string[] {
|
|
137
|
+
const outerWidth = Math.max(20, width);
|
|
138
|
+
const contentWidth = Math.max(1, outerWidth - 2);
|
|
139
|
+
const statusColor = tone === "success" ? "toolSuccess" : "toolMuted";
|
|
140
|
+
const labelStyled = theme.fg(statusColor, label);
|
|
141
|
+
const statusStyled = theme.fg(statusColor, status);
|
|
142
|
+
const labelWidth = Math.max(1, contentWidth - visibleWidth(statusStyled) - 1);
|
|
143
|
+
const clippedLabel = truncateToWidth(labelStyled, labelWidth, "");
|
|
144
|
+
const gap = Math.max(1, contentWidth - visibleWidth(clippedLabel) - visibleWidth(statusStyled));
|
|
145
|
+
const line = `${clippedLabel}${" ".repeat(gap)}${statusStyled}`;
|
|
146
|
+
return style()
|
|
147
|
+
.border("minimal")
|
|
148
|
+
.borderColor((text) => theme.fg(statusColor, text))
|
|
149
|
+
.render([line], outerWidth);
|
|
150
|
+
}
|
|
151
|
+
|
|
131
152
|
const COMPACT_ARG_VALUE_LIMIT = 60;
|
|
132
153
|
const GENERIC_OUTPUT_PREVIEW_LINES = 10;
|
|
133
154
|
const GENERIC_ARGS_JSON_PREVIEW_LINES = 10;
|
|
@@ -559,18 +580,13 @@ export class ToolExecutionComponent extends Container {
|
|
|
559
580
|
const frameTone: ToolFrameTone =
|
|
560
581
|
this.result?.isError ? "error" : this.isPartial || !this.result ? "pending" : "success";
|
|
561
582
|
const elapsed = formatElapsed((this.endedAt ?? Date.now()) - this.startedAt);
|
|
562
|
-
const frameStatus = `${this.isPartial || !this.result ? "
|
|
583
|
+
const frameStatus = `${this.isPartial || !this.result ? "running" : this.result.isError ? "failed" : "success"} · ${elapsed}`;
|
|
563
584
|
const parsed = parseMcpToolName(this.toolName);
|
|
564
585
|
const frameLabel = parsed
|
|
565
|
-
?
|
|
566
|
-
:
|
|
586
|
+
? `${parsed.server}·${parsed.tool}`
|
|
587
|
+
: prettifyToolName(this.toolName, this.toolDefinition?.label) || "unknown";
|
|
567
588
|
if (this.shouldRenderCompactSuccess()) {
|
|
568
|
-
|
|
569
|
-
const summaryWidth = Math.max(1, availableWidth - visibleWidth(frameStatus) - 1);
|
|
570
|
-
const summary = truncateToWidth(this.getCompactSummary(frameLabel), summaryWidth, "");
|
|
571
|
-
const gap = Math.max(1, availableWidth - visibleWidth(summary) - visibleWidth(frameStatus));
|
|
572
|
-
const line = `${theme.fg("toolSuccess", summary)}${" ".repeat(gap)}${theme.fg("toolSuccess", frameStatus)}`;
|
|
573
|
-
return ["", ...style().border("minimal").borderColor((text) => theme.fg("toolSuccess", text)).render([line], frameWidth)];
|
|
589
|
+
return ["", ...renderCollapsedToolRow(this.getCompactSummary(frameLabel), frameStatus, frameWidth, "success")];
|
|
574
590
|
}
|
|
575
591
|
const lines = super.render(contentWidth);
|
|
576
592
|
const framed = renderToolFrame(lines, frameWidth, {
|
|
@@ -584,7 +600,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
584
600
|
private shouldRenderCompactSuccess(): boolean {
|
|
585
601
|
if (this.expanded || this.isPartial || !this.result || this.result.isError) return false;
|
|
586
602
|
const hasImages = this.result.content?.some((block) => block.type === "image") ?? false;
|
|
587
|
-
return !hasImages
|
|
603
|
+
return !hasImages;
|
|
588
604
|
}
|
|
589
605
|
|
|
590
606
|
getRollupPhase(): ToolExecutionPhase | null {
|
|
@@ -615,7 +631,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
615
631
|
}
|
|
616
632
|
|
|
617
633
|
private getCompactSummary(frameLabel: string): string {
|
|
618
|
-
return
|
|
634
|
+
return frameLabel;
|
|
619
635
|
}
|
|
620
636
|
|
|
621
637
|
private updateDisplay(): void {
|
|
@@ -1271,6 +1287,10 @@ export class ToolPhaseSummaryComponent extends Container {
|
|
|
1271
1287
|
super();
|
|
1272
1288
|
}
|
|
1273
1289
|
|
|
1290
|
+
getPhases(): ToolExecutionPhase[] {
|
|
1291
|
+
return this.phases.map((phase) => ({ ...phase }));
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1274
1294
|
override render(width: number): string[] {
|
|
1275
1295
|
const frameWidth = Math.max(20, width);
|
|
1276
1296
|
const rows = this.phases.map((phase) => {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
|
+
import { Container } from "@gsd/pi-tui";
|
|
4
|
+
import stripAnsi from "strip-ansi";
|
|
3
5
|
|
|
4
6
|
import { findLatestPinnableText, handleAgentEvent } from "./chat-controller.js";
|
|
5
7
|
import { initTheme } from "../theme/theme.js";
|
|
@@ -111,3 +113,57 @@ test("handleAgentEvent: agent_start clears stale adaptive blocking error", async
|
|
|
111
113
|
assert.equal(cleared, true);
|
|
112
114
|
assert.equal(requestedRender, true);
|
|
113
115
|
});
|
|
116
|
+
|
|
117
|
+
test("handleAgentEvent: standalone completed tool events roll up incrementally", async () => {
|
|
118
|
+
initTheme("dark", false);
|
|
119
|
+
const chatContainer = new Container();
|
|
120
|
+
let renderCount = 0;
|
|
121
|
+
const host = {
|
|
122
|
+
isInitialized: true,
|
|
123
|
+
footer: { invalidate() {} },
|
|
124
|
+
settingsManager: {
|
|
125
|
+
getTimestampFormat() {
|
|
126
|
+
return "date-time-iso";
|
|
127
|
+
},
|
|
128
|
+
getShowImages() {
|
|
129
|
+
return false;
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
getRegisteredToolDefinition() {
|
|
133
|
+
return undefined;
|
|
134
|
+
},
|
|
135
|
+
chatContainer,
|
|
136
|
+
pendingTools: new Map(),
|
|
137
|
+
ui: {
|
|
138
|
+
requestRender() {
|
|
139
|
+
renderCount++;
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
} as any;
|
|
143
|
+
|
|
144
|
+
for (const [toolCallId, toolName] of [
|
|
145
|
+
["read-1", "read"],
|
|
146
|
+
["read-2", "read"],
|
|
147
|
+
["edit-1", "edit"],
|
|
148
|
+
] as const) {
|
|
149
|
+
await handleAgentEvent(host, {
|
|
150
|
+
type: "tool_execution_start",
|
|
151
|
+
toolCallId,
|
|
152
|
+
toolName,
|
|
153
|
+
args: { path: `/tmp/${toolCallId}.txt` },
|
|
154
|
+
} as any);
|
|
155
|
+
await handleAgentEvent(host, {
|
|
156
|
+
type: "tool_execution_end",
|
|
157
|
+
toolCallId,
|
|
158
|
+
toolName,
|
|
159
|
+
result: { content: [], isError: false },
|
|
160
|
+
isError: false,
|
|
161
|
+
} as any);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const rendered = stripAnsi(chatContainer.render(100).join("\n"));
|
|
165
|
+
assert.match(rendered, /Context reads 2 actions\s+success · \d+(ms|s)/);
|
|
166
|
+
assert.match(rendered, /File changes 1 action\s+success · \d+(ms|s)/);
|
|
167
|
+
assert.doesNotMatch(rendered, /\bread\s+success ·/);
|
|
168
|
+
assert.ok(renderCount > 0);
|
|
169
|
+
});
|
|
@@ -28,7 +28,8 @@ type RenderedSegment =
|
|
|
28
28
|
contentType: "text" | "thinking";
|
|
29
29
|
component: AssistantMessageComponent;
|
|
30
30
|
}
|
|
31
|
-
| { kind: "tool"; contentIndex: number; component: ToolExecutionComponent }
|
|
31
|
+
| { kind: "tool"; contentIndex: number; component: ToolExecutionComponent }
|
|
32
|
+
| { kind: "tool-summary"; component: ToolPhaseSummaryComponent; phases: ToolExecutionPhase[] };
|
|
32
33
|
|
|
33
34
|
let renderedSegments: RenderedSegment[] = [];
|
|
34
35
|
// When providers reuse one assistant lifecycle across internal sub-turns,
|
|
@@ -124,17 +125,25 @@ function replaceCompactToolRowsWithPhaseSummary(
|
|
|
124
125
|
): void {
|
|
125
126
|
let changed = false;
|
|
126
127
|
const nextRenderedSegments: RenderedSegment[] = [];
|
|
127
|
-
let rollupRun: Array<{
|
|
128
|
+
let rollupRun: Array<{
|
|
129
|
+
seg: Extract<RenderedSegment, { kind: "tool" | "tool-summary" }>;
|
|
130
|
+
phases: ToolExecutionPhase[];
|
|
131
|
+
}> = [];
|
|
128
132
|
|
|
129
133
|
const flushRollupRun = () => {
|
|
130
|
-
|
|
134
|
+
const actionCount = rollupRun.reduce(
|
|
135
|
+
(total, item) => total + item.phases.reduce((sum, phase) => sum + phase.count, 0),
|
|
136
|
+
0,
|
|
137
|
+
);
|
|
138
|
+
if (actionCount < 2) {
|
|
131
139
|
nextRenderedSegments.push(...rollupRun.map((item) => item.seg));
|
|
132
140
|
rollupRun = [];
|
|
133
141
|
return;
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
const firstIndex = Math.max(0, host.chatContainer.children.indexOf(rollupRun[0].seg.component));
|
|
137
|
-
const
|
|
145
|
+
const phases = mergeToolPhases(rollupRun.flatMap((item) => item.phases));
|
|
146
|
+
const summary = new ToolPhaseSummaryComponent(phases);
|
|
138
147
|
|
|
139
148
|
for (const { seg } of rollupRun) {
|
|
140
149
|
host.chatContainer.removeChild(seg.component);
|
|
@@ -149,13 +158,18 @@ function replaceCompactToolRowsWithPhaseSummary(
|
|
|
149
158
|
}
|
|
150
159
|
|
|
151
160
|
changed = true;
|
|
161
|
+
nextRenderedSegments.push({ kind: "tool-summary", component: summary, phases });
|
|
152
162
|
rollupRun = [];
|
|
153
163
|
};
|
|
154
164
|
|
|
155
165
|
for (const seg of renderedSegments) {
|
|
156
166
|
const phase = seg.kind === "tool" ? seg.component.getRollupPhase() : null;
|
|
157
167
|
if (seg.kind === "tool" && phase) {
|
|
158
|
-
rollupRun.push({ seg, phase });
|
|
168
|
+
rollupRun.push({ seg, phases: [phase] });
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (seg.kind === "tool-summary") {
|
|
172
|
+
rollupRun.push({ seg, phases: seg.component.getPhases() });
|
|
159
173
|
continue;
|
|
160
174
|
}
|
|
161
175
|
|
|
@@ -409,6 +423,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
409
423
|
details: externalToolResult.details,
|
|
410
424
|
isError: externalToolResult.isError,
|
|
411
425
|
});
|
|
426
|
+
replaceCompactToolRowsWithPhaseSummary(host);
|
|
412
427
|
}
|
|
413
428
|
}
|
|
414
429
|
|
|
@@ -843,7 +858,6 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
843
858
|
host.streamingComponent.setShowMetadata(true);
|
|
844
859
|
host.streamingComponent.updateContent(host.streamingMessage);
|
|
845
860
|
}
|
|
846
|
-
replaceCompactToolRowsWithPhaseSummary(host);
|
|
847
861
|
|
|
848
862
|
if (host.streamingMessage.stopReason === "aborted" || host.streamingMessage.stopReason === "error") {
|
|
849
863
|
if (!errorMessage) {
|
|
@@ -862,6 +876,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
862
876
|
for (const [, component] of host.pendingTools.entries()) {
|
|
863
877
|
component.setArgsComplete();
|
|
864
878
|
}
|
|
879
|
+
replaceCompactToolRowsWithPhaseSummary(host);
|
|
865
880
|
}
|
|
866
881
|
host.streamingComponent = undefined;
|
|
867
882
|
host.streamingMessage = undefined;
|
|
@@ -894,6 +909,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
894
909
|
component.setExpanded(host.toolOutputExpanded);
|
|
895
910
|
host.chatContainer.addChild(component);
|
|
896
911
|
host.pendingTools.set(event.toolCallId, component);
|
|
912
|
+
renderedSegments.push({ kind: "tool", contentIndex: Number.MAX_SAFE_INTEGER, component });
|
|
897
913
|
host.ui.requestRender();
|
|
898
914
|
}
|
|
899
915
|
break;
|
|
@@ -911,7 +927,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
911
927
|
const component = host.pendingTools.get(event.toolCallId);
|
|
912
928
|
if (component) {
|
|
913
929
|
component.updateResult({ ...event.result, isError: event.isError });
|
|
914
|
-
host
|
|
930
|
+
replaceCompactToolRowsWithPhaseSummary(host);
|
|
915
931
|
host.ui.requestRender();
|
|
916
932
|
}
|
|
917
933
|
break;
|
|
@@ -927,6 +943,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
927
943
|
host.streamingComponent.setShowMetadata(true);
|
|
928
944
|
host.streamingComponent.updateContent(host.streamingMessage);
|
|
929
945
|
}
|
|
946
|
+
replaceCompactToolRowsWithPhaseSummary(host);
|
|
930
947
|
host.streamingComponent = undefined;
|
|
931
948
|
host.streamingMessage = undefined;
|
|
932
949
|
renderedSegments = [];
|
|
@@ -1378,6 +1378,9 @@ export class InteractiveMode {
|
|
|
1378
1378
|
})();
|
|
1379
1379
|
},
|
|
1380
1380
|
getSystemPrompt: () => this.session.systemPrompt,
|
|
1381
|
+
setCompactionThresholdOverride: (percent) => {
|
|
1382
|
+
this.session.settingsManager.setCompactionThresholdOverride(percent);
|
|
1383
|
+
},
|
|
1381
1384
|
});
|
|
1382
1385
|
|
|
1383
1386
|
// Set up the extension shortcut handler on the default editor
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// GSD2 TUI - Built-in terminal theme definitions.
|
|
1
2
|
/**
|
|
2
3
|
* Built-in theme definitions.
|
|
3
4
|
*
|
|
@@ -18,27 +19,30 @@ import type { ThemeJson } from "./theme-schema.js";
|
|
|
18
19
|
const dark: ThemeJson = {
|
|
19
20
|
name: "dark",
|
|
20
21
|
vars: {
|
|
21
|
-
cyan: "#
|
|
22
|
-
blue: "#
|
|
23
|
-
green: "#
|
|
24
|
-
red: "#
|
|
25
|
-
yellow: "#
|
|
26
|
-
gray: "#
|
|
27
|
-
dimGray: "#
|
|
28
|
-
darkGray: "#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
cyan: "#5cc8c8",
|
|
23
|
+
blue: "#79b8ff",
|
|
24
|
+
green: "#7ad38b",
|
|
25
|
+
red: "#f27b7b",
|
|
26
|
+
yellow: "#d6b85f",
|
|
27
|
+
gray: "#87949b",
|
|
28
|
+
dimGray: "#657178",
|
|
29
|
+
darkGray: "#303a40",
|
|
30
|
+
line: "#52616a",
|
|
31
|
+
lineSoft: "#303a40",
|
|
32
|
+
textSoft: "#cbd6dc",
|
|
33
|
+
accent: "#5cc8c8",
|
|
34
|
+
selectedBg: "#1d282a",
|
|
35
|
+
userMsgBg: "#202a2f",
|
|
36
|
+
toolPendingBg: "#252721",
|
|
37
|
+
toolSuccessBg: "#1c251f",
|
|
38
|
+
toolErrorBg: "#251e20",
|
|
39
|
+
customMsgBg: "#202a2f",
|
|
36
40
|
},
|
|
37
41
|
colors: {
|
|
38
42
|
accent: "accent",
|
|
39
|
-
border: "
|
|
40
|
-
borderAccent: "
|
|
41
|
-
borderMuted: "
|
|
43
|
+
border: "line",
|
|
44
|
+
borderAccent: "accent",
|
|
45
|
+
borderMuted: "lineSoft",
|
|
42
46
|
success: "green",
|
|
43
47
|
error: "red",
|
|
44
48
|
warning: "yellow",
|
|
@@ -49,16 +53,21 @@ const dark: ThemeJson = {
|
|
|
49
53
|
|
|
50
54
|
selectedBg: "selectedBg",
|
|
51
55
|
userMessageBg: "userMsgBg",
|
|
52
|
-
userMessageText: "
|
|
53
|
-
assistantMessageText: "",
|
|
56
|
+
userMessageText: "textSoft",
|
|
57
|
+
assistantMessageText: "textSoft",
|
|
54
58
|
customMessageBg: "customMsgBg",
|
|
55
|
-
customMessageText: "",
|
|
56
|
-
customMessageLabel: "
|
|
59
|
+
customMessageText: "textSoft",
|
|
60
|
+
customMessageLabel: "blue",
|
|
57
61
|
toolPendingBg: "toolPendingBg",
|
|
58
62
|
toolSuccessBg: "toolSuccessBg",
|
|
59
63
|
toolErrorBg: "toolErrorBg",
|
|
60
|
-
toolTitle: "
|
|
61
|
-
toolOutput: "
|
|
64
|
+
toolTitle: "gray",
|
|
65
|
+
toolOutput: "textSoft",
|
|
66
|
+
surfaceTitle: "accent",
|
|
67
|
+
surfaceAccent: "accent",
|
|
68
|
+
toolRunning: "yellow",
|
|
69
|
+
toolSuccess: "green",
|
|
70
|
+
toolError: "red",
|
|
62
71
|
|
|
63
72
|
mdHeading: "#fbbf24",
|
|
64
73
|
mdLink: "#93c5fd",
|
|
@@ -95,9 +104,9 @@ const dark: ThemeJson = {
|
|
|
95
104
|
bashMode: "green",
|
|
96
105
|
},
|
|
97
106
|
export: {
|
|
98
|
-
pageBg: "#
|
|
99
|
-
cardBg: "#
|
|
100
|
-
infoBg: "#
|
|
107
|
+
pageBg: "#111416",
|
|
108
|
+
cardBg: "#1e2529",
|
|
109
|
+
infoBg: "#252721",
|
|
101
110
|
},
|
|
102
111
|
};
|
|
103
112
|
|
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import assert from "node:assert/strict";
|
|
4
4
|
import { describe, test } from "node:test";
|
|
5
|
+
import stripAnsi from "strip-ansi";
|
|
5
6
|
|
|
7
|
+
import { AdaptiveLayoutComponent } from "./components/adaptive-layout.js";
|
|
8
|
+
import { initTheme } from "./theme/theme.js";
|
|
6
9
|
import { resolveTuiMode } from "./tui-mode.js";
|
|
7
10
|
|
|
11
|
+
initTheme("dark", false);
|
|
12
|
+
|
|
8
13
|
describe("resolveTuiMode", () => {
|
|
9
14
|
test("explicit overrides beat auto selection", () => {
|
|
10
15
|
assert.equal(
|
|
@@ -38,3 +43,23 @@ describe("resolveTuiMode", () => {
|
|
|
38
43
|
assert.equal(resolveTuiMode({ terminalWidth: 100 }), "chat");
|
|
39
44
|
});
|
|
40
45
|
});
|
|
46
|
+
|
|
47
|
+
describe("AdaptiveLayoutComponent", () => {
|
|
48
|
+
test("renders workflow layout with prototype rule frames", () => {
|
|
49
|
+
const layout = new AdaptiveLayoutComponent(() => ({
|
|
50
|
+
override: "workflow",
|
|
51
|
+
activeToolCount: 2,
|
|
52
|
+
gsdPhase: "execute-task",
|
|
53
|
+
sessionName: "main",
|
|
54
|
+
cwd: "/Users/example/project",
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
const plain = layout.render(120).map(stripAnsi);
|
|
58
|
+
|
|
59
|
+
assert.match(plain[0], /^─+/, "workflow layout should start with a rule frame");
|
|
60
|
+
assert.ok(plain.some((line) => line.includes("GSD Command Center")), "workflow title should render");
|
|
61
|
+
assert.ok(plain.some((line) => line.includes("signals")), "inspector title should render");
|
|
62
|
+
assert.ok(plain.some((line) => line.includes("│ Active")), "body rows should keep prototype gutter");
|
|
63
|
+
assert.ok(!plain.some((line) => /[╭╮╰╯]/.test(line)), "workflow layout should not use rounded box corners");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
|
|
6
|
+
test("MemoryStorage persists sql.js snapshots through the atomic DB snapshot writer", () => {
|
|
7
|
+
const src = readFileSync(
|
|
8
|
+
join(process.cwd(), "packages", "pi-coding-agent", "src", "resources", "extensions", "memory", "storage.ts"),
|
|
9
|
+
"utf-8",
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
assert.match(src, /atomicWriteDbSnapshotSync\(/, "storage must use atomic DB snapshot writes");
|
|
13
|
+
assert.doesNotMatch(src, /writeFileSync\(this\.dbPath/, "direct live DB overwrite is forbidden");
|
|
14
|
+
});
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
import initSqlJs, { type Database as SqlJsDatabase } from "sql.js";
|
|
11
11
|
import { randomUUID } from "crypto";
|
|
12
|
-
import { existsSync, mkdirSync, readFileSync
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync } from "fs";
|
|
13
13
|
import { dirname } from "path";
|
|
14
|
+
import { atomicWriteDbSnapshotSync } from "../../../core/db-snapshot.js";
|
|
14
15
|
|
|
15
16
|
export interface ThreadRow {
|
|
16
17
|
thread_id: string;
|
|
@@ -74,7 +75,7 @@ export class MemoryStorage {
|
|
|
74
75
|
|
|
75
76
|
private persist(): void {
|
|
76
77
|
const data = this.db.export();
|
|
77
|
-
|
|
78
|
+
atomicWriteDbSnapshotSync(this.dbPath, data);
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
private schedulePersist(): void {
|