gsd-pi 2.70.1-dev.ec24142 → 2.71.0-dev.977c553
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 +24 -17
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +16 -12
- package/dist/resources/extensions/gsd/file-lock.js +60 -0
- package/dist/resources/extensions/gsd/state.js +234 -332
- package/dist/resources/extensions/gsd/workflow-events.js +25 -13
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- 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/required-server-files.json +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.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 +9 -9
- 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/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +202 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +19 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +50 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.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 +90 -2
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
- 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 +57 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +249 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +58 -2
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +96 -2
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +65 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +66 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
- package/packages/pi-tui/dist/components/markdown.d.ts +3 -0
- package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/markdown.js +17 -1
- package/packages/pi-tui/dist/components/markdown.js.map +1 -1
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +75 -0
- package/packages/pi-tui/src/components/markdown.ts +22 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +19 -14
- package/src/resources/extensions/gsd/file-lock.ts +59 -0
- package/src/resources/extensions/gsd/state.ts +274 -344
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +103 -0
- package/src/resources/extensions/gsd/workflow-events.ts +34 -25
- /package/dist/web/standalone/.next/static/{20e8bFnNjxQJflHNodEve → 4xyaXTn7-shVHaGMcl75o}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{20e8bFnNjxQJflHNodEve → 4xyaXTn7-shVHaGMcl75o}/_ssgManifest.js +0 -0
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
import { injectContext } from "./context-injector.js";
|
|
35
35
|
import type { WorkflowDefinition, StepDefinition } from "./definition-loader.js";
|
|
36
36
|
import { parseUnitId } from "./unit-id.js";
|
|
37
|
+
import { withFileLock } from "./file-lock.js";
|
|
37
38
|
|
|
38
39
|
/** Read and parse the frozen DEFINITION.yaml from a run directory. */
|
|
39
40
|
export function readFrozenDefinition(runDir: string): WorkflowDefinition {
|
|
@@ -179,24 +180,28 @@ export class CustomWorkflowEngine implements WorkflowEngine {
|
|
|
179
180
|
state: EngineState,
|
|
180
181
|
completedStep: CompletedStep,
|
|
181
182
|
): Promise<ReconcileResult> {
|
|
182
|
-
|
|
183
|
-
// workflow edits with a stale in-memory snapshot from deriveState().
|
|
184
|
-
const graph = readGraph(this.runDir);
|
|
183
|
+
const graphPath = join(this.runDir, "GRAPH.yaml");
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
return await withFileLock(graphPath, () => {
|
|
186
|
+
// Re-read the graph from disk so we do not overwrite concurrent
|
|
187
|
+
// workflow edits with a stale in-memory snapshot from deriveState().
|
|
188
|
+
const graph = readGraph(this.runDir);
|
|
189
189
|
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
// Extract stepId from "<workflowName>/<stepId>"
|
|
191
|
+
const { milestone, slice, task } = parseUnitId(completedStep.unitId);
|
|
192
|
+
const stepId = task ?? slice ?? milestone;
|
|
192
193
|
|
|
193
|
-
|
|
194
|
-
(
|
|
195
|
-
);
|
|
194
|
+
const updatedGraph = markStepComplete(graph, stepId);
|
|
195
|
+
writeGraph(this.runDir, updatedGraph);
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
const allDone = updatedGraph.steps.every(
|
|
198
|
+
(s) => s.status === "complete" || s.status === "expanded",
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
outcome: allDone ? "milestone-complete" : "continue",
|
|
203
|
+
};
|
|
204
|
+
});
|
|
200
205
|
}
|
|
201
206
|
|
|
202
207
|
/**
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
function _require(name: string) {
|
|
4
|
+
try {
|
|
5
|
+
return require(name);
|
|
6
|
+
} catch {
|
|
7
|
+
try {
|
|
8
|
+
const gsdPiRequire = require("module").createRequire(
|
|
9
|
+
require("path").join(process.cwd(), "node_modules", "gsd-pi", "index.js")
|
|
10
|
+
);
|
|
11
|
+
return gsdPiRequire(name);
|
|
12
|
+
} catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function withFileLockSync<T>(filePath: string, fn: () => T): T {
|
|
19
|
+
const lockfile = _require("proper-lockfile");
|
|
20
|
+
if (!lockfile) return fn();
|
|
21
|
+
|
|
22
|
+
if (!existsSync(filePath)) return fn();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const release = lockfile.lockSync(filePath, { retries: 5, stale: 10000 });
|
|
26
|
+
try {
|
|
27
|
+
return fn();
|
|
28
|
+
} finally {
|
|
29
|
+
release();
|
|
30
|
+
}
|
|
31
|
+
} catch (err: any) {
|
|
32
|
+
if (err.code === "ELOCKED") {
|
|
33
|
+
// Could not get lock after retries, let's fallback to un-locked instead of crashing the whole state machine
|
|
34
|
+
return fn();
|
|
35
|
+
}
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function withFileLock<T>(filePath: string, fn: () => Promise<T> | T): Promise<T> {
|
|
41
|
+
const lockfile = _require("proper-lockfile");
|
|
42
|
+
if (!lockfile) return await fn();
|
|
43
|
+
|
|
44
|
+
if (!existsSync(filePath)) return await fn();
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const release = await lockfile.lock(filePath, { retries: 5, stale: 10000 });
|
|
48
|
+
try {
|
|
49
|
+
return await fn();
|
|
50
|
+
} finally {
|
|
51
|
+
await release();
|
|
52
|
+
}
|
|
53
|
+
} catch (err: any) {
|
|
54
|
+
if (err.code === "ELOCKED") {
|
|
55
|
+
return await fn();
|
|
56
|
+
}
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
}
|