gsd-pi 2.76.0-dev.4c866b677 → 2.76.0-dev.7218806ab
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/claude-cli-check.js +32 -3
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.js +35 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +4 -3
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +77 -17
- package/dist/resources/extensions/gsd/auto-model-selection.js +1 -1
- package/dist/resources/extensions/gsd/auto-start.js +11 -15
- package/dist/resources/extensions/gsd/auto.js +13 -17
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +40 -4
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +12 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
- package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
- package/dist/resources/extensions/gsd/error-classifier.js +10 -3
- package/dist/resources/extensions/gsd/exec-history.js +120 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
- package/dist/resources/extensions/gsd/gsd-db.js +3 -1
- package/dist/resources/extensions/gsd/guided-flow.js +189 -0
- package/dist/resources/extensions/gsd/health-widget.js +4 -1
- package/dist/resources/extensions/gsd/key-manager.js +6 -0
- package/dist/resources/extensions/gsd/model-router.js +36 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -9
- package/dist/resources/extensions/gsd/preferences-types.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
- package/dist/resources/extensions/gsd/preferences.js +17 -17
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/dist/resources/extensions/gsd/token-counter.js +22 -5
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
- 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 +11 -11
- 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 +11 -11
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- 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 +1 -1
- package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
- package/packages/mcp-server/dist/remote-questions.js +732 -0
- package/packages/mcp-server/dist/remote-questions.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +18 -1
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +64 -25
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -1
- package/packages/mcp-server/src/remote-questions.test.ts +294 -0
- package/packages/mcp-server/src/remote-questions.ts +916 -0
- package/packages/mcp-server/src/server.ts +19 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +146 -1
- package/packages/mcp-server/src/workflow-tools.ts +84 -43
- package/packages/mcp-server/tsconfig.test.json +19 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +16 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.ts +3 -1
- package/packages/pi-ai/src/providers/simple-options.ts +17 -1
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +14 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +9 -5
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +25 -1
- package/packages/pi-coding-agent/dist/core/session-manager.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 +13 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +16 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +36 -1
- package/packages/pi-coding-agent/src/core/session-manager.ts +9 -5
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +4 -3
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +78 -17
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +149 -5
- package/src/resources/extensions/gsd/auto-model-selection.ts +1 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +0 -1
- package/src/resources/extensions/gsd/auto-start.ts +13 -16
- package/src/resources/extensions/gsd/auto.ts +12 -17
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +23 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +42 -4
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +13 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
- package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
- package/src/resources/extensions/gsd/error-classifier.ts +10 -3
- package/src/resources/extensions/gsd/exec-history.ts +153 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
- package/src/resources/extensions/gsd/gsd-db.ts +3 -1
- package/src/resources/extensions/gsd/guided-flow.ts +221 -0
- package/src/resources/extensions/gsd/health-widget.ts +3 -1
- package/src/resources/extensions/gsd/key-manager.ts +6 -0
- package/src/resources/extensions/gsd/model-router.ts +42 -1
- package/src/resources/extensions/gsd/pre-execution-checks.ts +36 -10
- package/src/resources/extensions/gsd/preferences-types.ts +38 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
- package/src/resources/extensions/gsd/preferences.ts +17 -17
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +234 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
- package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
- package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
- package/src/resources/extensions/gsd/token-counter.ts +22 -5
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +2 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
- /package/dist/web/standalone/.next/static/{jDqWYbuP_CG6Kjc-uKwkN → 5qAwYhcU5Fs2VOq_R8lOc}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{jDqWYbuP_CG6Kjc-uKwkN → 5qAwYhcU5Fs2VOq_R8lOc}/_ssgManifest.js +0 -0
|
@@ -19,6 +19,18 @@ function registerAlias(pi, toolDef, aliasName, canonicalName) {
|
|
|
19
19
|
promptGuidelines: [`Alias for ${canonicalName} — prefer the canonical name.`],
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Read a tool result's structured payload, accommodating MCP's `details` →
|
|
24
|
+
* `structuredContent` rename (#4472, #4477). In-process executions still
|
|
25
|
+
* deliver the payload on `result.details`; MCP-routed executions deliver it
|
|
26
|
+
* on `result.structuredContent` (post `adaptExecutorResult` transform). All
|
|
27
|
+
* `renderResult` callbacks in this file route through this helper so a future
|
|
28
|
+
* field rename only needs to be applied in one place.
|
|
29
|
+
*/
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- result shape varies by tool
|
|
31
|
+
function readDetails(result) {
|
|
32
|
+
return result?.details ?? result?.structuredContent;
|
|
33
|
+
}
|
|
22
34
|
export function registerDbTools(pi) {
|
|
23
35
|
// ─── gsd_decision_save (formerly gsd_save_decision) ─────────────────────
|
|
24
36
|
const decisionSaveExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
|
|
@@ -92,7 +104,7 @@ export function registerDbTools(pi) {
|
|
|
92
104
|
return new Text(text, 0, 0);
|
|
93
105
|
},
|
|
94
106
|
renderResult(result, _options, theme) {
|
|
95
|
-
const d = result
|
|
107
|
+
const d = readDetails(result);
|
|
96
108
|
if (result.isError || d?.error) {
|
|
97
109
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
98
110
|
}
|
|
@@ -175,7 +187,7 @@ export function registerDbTools(pi) {
|
|
|
175
187
|
return new Text(text, 0, 0);
|
|
176
188
|
},
|
|
177
189
|
renderResult(result, _options, theme) {
|
|
178
|
-
const d = result
|
|
190
|
+
const d = readDetails(result);
|
|
179
191
|
if (result.isError || d?.error) {
|
|
180
192
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
181
193
|
}
|
|
@@ -255,7 +267,7 @@ export function registerDbTools(pi) {
|
|
|
255
267
|
return new Text(text, 0, 0);
|
|
256
268
|
},
|
|
257
269
|
renderResult(result, _options, theme) {
|
|
258
|
-
const d = result
|
|
270
|
+
const d = readDetails(result);
|
|
259
271
|
if (result.isError || d?.error) {
|
|
260
272
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
261
273
|
}
|
|
@@ -301,7 +313,7 @@ export function registerDbTools(pi) {
|
|
|
301
313
|
return new Text(text, 0, 0);
|
|
302
314
|
},
|
|
303
315
|
renderResult(result, _options, theme) {
|
|
304
|
-
const d = result
|
|
316
|
+
const d = readDetails(result);
|
|
305
317
|
if (result.isError || d?.error) {
|
|
306
318
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
307
319
|
}
|
|
@@ -382,7 +394,7 @@ export function registerDbTools(pi) {
|
|
|
382
394
|
return new Text(theme.fg("toolTitle", theme.bold("milestone_generate_id")), 0, 0);
|
|
383
395
|
},
|
|
384
396
|
renderResult(result, _options, theme) {
|
|
385
|
-
const d = result
|
|
397
|
+
const d = readDetails(result);
|
|
386
398
|
if (result.isError || d?.error) {
|
|
387
399
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
388
400
|
}
|
|
@@ -967,13 +979,31 @@ export function registerDbTools(pi) {
|
|
|
967
979
|
text += theme.fg("dim", ` → ${args.verdict ?? ""}`);
|
|
968
980
|
return new Text(text, 0, 0);
|
|
969
981
|
},
|
|
982
|
+
/**
|
|
983
|
+
* Render the save_gate_result tool output for the TUI.
|
|
984
|
+
*
|
|
985
|
+
* Prefers structured fields, but falls back to `content[0].text` when the
|
|
986
|
+
* structured payload is empty. Defensive: the structural fix on this
|
|
987
|
+
* branch plumbs `details` through MCP via `structuredContent`, but older
|
|
988
|
+
* hosts, a future handler that forgets `structuredContent`, or any drop
|
|
989
|
+
* of non-standard return fields would otherwise render as
|
|
990
|
+
* "undefined: undefined". Same fallback applies to error rendering, and
|
|
991
|
+
* we strip a leading `Error:` from the fallback text to avoid producing
|
|
992
|
+
* `Error: Error: ...`.
|
|
993
|
+
*/
|
|
970
994
|
renderResult(result, _options, theme) {
|
|
971
|
-
const d = result
|
|
995
|
+
const d = readDetails(result);
|
|
972
996
|
if (result.isError || d?.error) {
|
|
973
|
-
|
|
997
|
+
const rawMsg = d?.error ?? result.content?.[0]?.text ?? "unknown";
|
|
998
|
+
const msg = rawMsg.replace(/^\s*Error:\s*/i, "");
|
|
999
|
+
return new Text(theme.fg("error", `Error: ${msg}`), 0, 0);
|
|
1000
|
+
}
|
|
1001
|
+
if (!d?.gateId || !d?.verdict) {
|
|
1002
|
+
const text = result.content?.[0]?.text ?? "Gate result saved";
|
|
1003
|
+
return new Text(theme.fg("success", text), 0, 0);
|
|
974
1004
|
}
|
|
975
|
-
const color = d
|
|
976
|
-
return new Text(theme.fg(color, `${d
|
|
1005
|
+
const color = d.verdict === "flag" ? "warning" : "success";
|
|
1006
|
+
return new Text(theme.fg(color, `${d.gateId}: ${d.verdict}`), 0, 0);
|
|
977
1007
|
},
|
|
978
1008
|
};
|
|
979
1009
|
pi.registerTool(saveGateResultTool);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// GSD2 — Exec (context-mode) tool registration.
|
|
2
|
+
//
|
|
3
|
+
// Exposes the `gsd_exec` tool over MCP. Opt-in: disabled unless
|
|
4
|
+
// `context_mode.enabled: true` is set in preferences.
|
|
5
|
+
import { Type } from "@sinclair/typebox";
|
|
6
|
+
import { executeGsdExec } from "../tools/exec-tool.js";
|
|
7
|
+
import { executeExecSearch } from "../tools/exec-search-tool.js";
|
|
8
|
+
import { executeResume } from "../tools/resume-tool.js";
|
|
9
|
+
import { loadEffectiveGSDPreferences } from "../preferences.js";
|
|
10
|
+
import { logWarning } from "../workflow-logger.js";
|
|
11
|
+
export function registerExecTools(pi) {
|
|
12
|
+
pi.registerTool({
|
|
13
|
+
name: "gsd_exec",
|
|
14
|
+
label: "Exec (Sandboxed)",
|
|
15
|
+
description: "Run a short script (bash/node/python) in a subprocess. Full stdout/stderr persist to " +
|
|
16
|
+
".gsd/exec/<id>.{stdout,stderr,meta.json}; only a short digest returns in context. Use " +
|
|
17
|
+
"this instead of reading many files or emitting large tool outputs — e.g. have the script " +
|
|
18
|
+
"count/grep/summarize and log the finding. Enabled by default; opt out via " +
|
|
19
|
+
"preferences.context_mode.enabled=false.",
|
|
20
|
+
promptSnippet: "Run a bash/node/python script in a sandbox; full output is saved to disk and only a digest returns",
|
|
21
|
+
promptGuidelines: [
|
|
22
|
+
"Prefer gsd_exec for analyses that would otherwise read >3 files or produce large tool output.",
|
|
23
|
+
"Write scripts that log the finding (counts, matches, summaries) rather than raw dumps.",
|
|
24
|
+
"The digest is the last ~300 chars of stdout — size your log output accordingly.",
|
|
25
|
+
"Need the full output? Read the stdout_path returned in details (file on local disk).",
|
|
26
|
+
],
|
|
27
|
+
parameters: Type.Object({
|
|
28
|
+
runtime: Type.Union([Type.Literal("bash"), Type.Literal("node"), Type.Literal("python")], { description: "Interpreter: bash (-c), node (-e), or python3 (-c)." }),
|
|
29
|
+
script: Type.String({ description: "Script body. Keep output small (log the finding, not the data)." }),
|
|
30
|
+
purpose: Type.Optional(Type.String({ description: "Short label recorded in meta.json for later review." })),
|
|
31
|
+
timeout_ms: Type.Optional(Type.Number({
|
|
32
|
+
description: "Per-invocation timeout (ms). Capped at 600000. Default from preferences.",
|
|
33
|
+
minimum: 1_000,
|
|
34
|
+
maximum: 600_000,
|
|
35
|
+
})),
|
|
36
|
+
}),
|
|
37
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
38
|
+
let prefs = null;
|
|
39
|
+
try {
|
|
40
|
+
prefs = loadEffectiveGSDPreferences();
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
logWarning("tool", `gsd_exec could not load preferences: ${err instanceof Error ? err.message : String(err)}`);
|
|
44
|
+
}
|
|
45
|
+
return executeGsdExec(params, {
|
|
46
|
+
baseDir: process.cwd(),
|
|
47
|
+
preferences: prefs?.preferences ?? null,
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
pi.registerTool({
|
|
52
|
+
name: "gsd_exec_search",
|
|
53
|
+
label: "Search gsd_exec History",
|
|
54
|
+
description: "List prior gsd_exec runs (most recent first) from .gsd/exec/*.meta.json. Useful for " +
|
|
55
|
+
"rediscovering the stdout_path of an earlier run without re-executing it. Read-only.",
|
|
56
|
+
promptSnippet: "Search prior gsd_exec runs by substring, runtime, or failing-only filter",
|
|
57
|
+
promptGuidelines: [
|
|
58
|
+
"Use this before re-running an expensive analysis — the prior run's stdout file may still answer.",
|
|
59
|
+
"The preview shows the trailing ~300 chars of stdout; read stdout_path for the full transcript.",
|
|
60
|
+
],
|
|
61
|
+
parameters: Type.Object({
|
|
62
|
+
query: Type.Optional(Type.String({ description: "Substring matched against id and purpose (case-insensitive)." })),
|
|
63
|
+
runtime: Type.Optional(Type.Union([Type.Literal("bash"), Type.Literal("node"), Type.Literal("python")], {
|
|
64
|
+
description: "Restrict to one runtime.",
|
|
65
|
+
})),
|
|
66
|
+
failing_only: Type.Optional(Type.Boolean({ description: "Only non-zero exit codes and timeouts." })),
|
|
67
|
+
limit: Type.Optional(Type.Number({ description: "Max results (default 20, cap 200)", minimum: 1, maximum: 200 })),
|
|
68
|
+
}),
|
|
69
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
70
|
+
return executeExecSearch(params, {
|
|
71
|
+
baseDir: process.cwd(),
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
pi.registerTool({
|
|
76
|
+
name: "gsd_resume",
|
|
77
|
+
label: "Resume (Read Snapshot)",
|
|
78
|
+
description: "Return the contents of .gsd/last-snapshot.md — a ≤2 KB digest of top memories, recent " +
|
|
79
|
+
"gsd_exec runs, and active context, written automatically on session_before_compact. Use " +
|
|
80
|
+
"this after compaction or session resume to re-orient quickly.",
|
|
81
|
+
promptSnippet: "Read the pre-compaction snapshot to re-orient after context loss",
|
|
82
|
+
promptGuidelines: [
|
|
83
|
+
"Call this right after a session resumes if you feel you've lost durable context.",
|
|
84
|
+
"The snapshot is a summary — use memory_query or gsd_exec_search for detail.",
|
|
85
|
+
],
|
|
86
|
+
parameters: Type.Object({}),
|
|
87
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
88
|
+
return executeResume(params, {
|
|
89
|
+
baseDir: process.cwd(),
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
@@ -4,6 +4,7 @@ import { registerWorktreeCommand } from "../worktree-command.js";
|
|
|
4
4
|
import { loadEcosystemExtensions } from "../ecosystem/loader.js";
|
|
5
5
|
import { registerDbTools } from "./db-tools.js";
|
|
6
6
|
import { registerDynamicTools } from "./dynamic-tools.js";
|
|
7
|
+
import { registerExecTools } from "./exec-tools.js";
|
|
7
8
|
import { registerJournalTools } from "./journal-tools.js";
|
|
8
9
|
import { registerMemoryTools } from "./memory-tools.js";
|
|
9
10
|
import { registerQueryTools } from "./query-tools.js";
|
|
@@ -86,6 +87,7 @@ export function registerGsdExtension(pi) {
|
|
|
86
87
|
["journal-tools", () => registerJournalTools(pi)],
|
|
87
88
|
["query-tools", () => registerQueryTools(pi)],
|
|
88
89
|
["memory-tools", () => registerMemoryTools(pi)],
|
|
90
|
+
["exec-tools", () => registerExecTools(pi)],
|
|
89
91
|
["shortcuts", () => registerShortcuts(pi)],
|
|
90
92
|
["hooks", () => registerHooks(pi, ecosystemHandlers)],
|
|
91
93
|
["ecosystem", () => {
|
|
@@ -13,7 +13,6 @@ import { loadToolApiKeys } from "../commands-config.js";
|
|
|
13
13
|
import { loadFile, saveFile, formatContinue } from "../files.js";
|
|
14
14
|
import { deriveState } from "../state.js";
|
|
15
15
|
import { getAutoDashboardData, isAutoActive, isAutoPaused, markToolEnd, markToolStart, recordToolInvocationError } from "../auto.js";
|
|
16
|
-
import { hideFooter } from "../auto-dashboard.js";
|
|
17
16
|
import { isParallelActive, shutdownParallel } from "../parallel-orchestrator.js";
|
|
18
17
|
import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
|
|
19
18
|
import { saveActivityLog } from "../activity-log.js";
|
|
@@ -37,7 +36,9 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
37
36
|
initNotificationStore(process.cwd());
|
|
38
37
|
installNotifyInterceptor(ctx);
|
|
39
38
|
initNotificationWidget(ctx);
|
|
40
|
-
|
|
39
|
+
if (!isAutoActive()) {
|
|
40
|
+
initHealthWidget(ctx);
|
|
41
|
+
}
|
|
41
42
|
resetWriteGateState();
|
|
42
43
|
resetToolCallLoopGuard();
|
|
43
44
|
resetAskUserQuestionsCache();
|
|
@@ -79,7 +80,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
79
80
|
}
|
|
80
81
|
loadToolApiKeys();
|
|
81
82
|
if (isAutoActive()) {
|
|
82
|
-
ctx.ui.
|
|
83
|
+
ctx.ui.setWidget("gsd-health", undefined);
|
|
83
84
|
}
|
|
84
85
|
});
|
|
85
86
|
pi.on("session_switch", async (_event, ctx) => {
|
|
@@ -101,7 +102,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
101
102
|
}
|
|
102
103
|
loadToolApiKeys();
|
|
103
104
|
if (isAutoActive()) {
|
|
104
|
-
ctx.ui.
|
|
105
|
+
ctx.ui.setWidget("gsd-health", undefined);
|
|
105
106
|
}
|
|
106
107
|
});
|
|
107
108
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
@@ -204,6 +205,41 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
204
205
|
nextAction: `Resume task ${state.activeTask.id}: ${state.activeTask.title}.`,
|
|
205
206
|
}));
|
|
206
207
|
});
|
|
208
|
+
// Context-mode snapshot: write .gsd/last-snapshot.md before compaction so
|
|
209
|
+
// agents can call gsd_resume (or Read the file) to re-orient. Opt-in via
|
|
210
|
+
// preferences.context_mode.enabled. Runs after the auto-cancel handler
|
|
211
|
+
// above — if that one returned cancel:true, pi still fires us but the
|
|
212
|
+
// compaction won't actually happen; the snapshot is still useful then,
|
|
213
|
+
// since auto may pause and resume later.
|
|
214
|
+
pi.on("session_before_compact", async () => {
|
|
215
|
+
try {
|
|
216
|
+
const { loadEffectiveGSDPreferences } = await import("../preferences.js");
|
|
217
|
+
const { isContextModeEnabled } = await import("../preferences-types.js");
|
|
218
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
219
|
+
if (!isContextModeEnabled(prefs?.preferences))
|
|
220
|
+
return;
|
|
221
|
+
const { writeCompactionSnapshot } = await import("../compaction-snapshot.js");
|
|
222
|
+
const { ensureDbOpen } = await import("./dynamic-tools.js");
|
|
223
|
+
await ensureDbOpen();
|
|
224
|
+
const basePath = process.cwd();
|
|
225
|
+
let activeContext = null;
|
|
226
|
+
try {
|
|
227
|
+
const state = await deriveState(basePath);
|
|
228
|
+
if (state.activeMilestone && state.activeSlice && state.activeTask) {
|
|
229
|
+
activeContext =
|
|
230
|
+
`Active: ${state.activeMilestone.id} / ${state.activeSlice.id} / ${state.activeTask.id}` +
|
|
231
|
+
(state.activeTask.title ? ` — ${state.activeTask.title}` : "");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
/* non-fatal */
|
|
236
|
+
}
|
|
237
|
+
writeCompactionSnapshot(basePath, { activeContext });
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
safetyLogWarning("context-mode", `failed to write compaction snapshot: ${err instanceof Error ? err.message : String(err)}`);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
207
243
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
208
244
|
if (isParallelActive()) {
|
|
209
245
|
try {
|
|
@@ -99,10 +99,21 @@ function normalizeWriteGateSnapshot(value) {
|
|
|
99
99
|
pendingGateId: typeof record.pendingGateId === "string" ? record.pendingGateId : null,
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
+
const EMPTY_SNAPSHOT = {
|
|
103
|
+
verifiedDepthMilestones: [],
|
|
104
|
+
activeQueuePhase: false,
|
|
105
|
+
pendingGateId: null,
|
|
106
|
+
};
|
|
102
107
|
export function loadWriteGateSnapshot(basePath = process.cwd()) {
|
|
103
108
|
const path = writeGateSnapshotPath(basePath);
|
|
104
|
-
if (!existsSync(path))
|
|
109
|
+
if (!existsSync(path)) {
|
|
110
|
+
// When persist mode is active and the file has been deleted, treat it as a
|
|
111
|
+
// full state reset so deleting the file clears the HARD BLOCK gate.
|
|
112
|
+
// In non-persist mode the file is never written, so fall back to in-memory.
|
|
113
|
+
if (shouldPersistWriteGateSnapshot())
|
|
114
|
+
return EMPTY_SNAPSHOT;
|
|
105
115
|
return currentWriteGateSnapshot();
|
|
116
|
+
}
|
|
106
117
|
try {
|
|
107
118
|
return normalizeWriteGateSnapshot(JSON.parse(readFileSync(path, "utf-8")));
|
|
108
119
|
}
|