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
|
@@ -16,7 +16,11 @@ async function getEncoder() {
|
|
|
16
16
|
try {
|
|
17
17
|
// @ts-ignore — tiktoken may not have type declarations in extensions tsconfig
|
|
18
18
|
const tiktoken = await import("tiktoken");
|
|
19
|
-
|
|
19
|
+
// Use cl100k_base — the most conservative and broadly compatible BPE encoding.
|
|
20
|
+
// It is shared by GPT-3.5/GPT-4 and gives a safer (larger) estimate than
|
|
21
|
+
// gpt-4o's o200k_base encoding, which produces fewer tokens for the same text
|
|
22
|
+
// and would cause context windows for non-OpenAI providers to be under-counted.
|
|
23
|
+
encoder = tiktoken.get_encoding("cl100k_base");
|
|
20
24
|
return encoder;
|
|
21
25
|
}
|
|
22
26
|
catch {
|
|
@@ -24,19 +28,32 @@ async function getEncoder() {
|
|
|
24
28
|
return null;
|
|
25
29
|
}
|
|
26
30
|
}
|
|
27
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Count tokens in `text` using tiktoken (cl100k_base) when available.
|
|
33
|
+
*
|
|
34
|
+
* When tiktoken is not loaded, falls back to a provider-aware character-ratio
|
|
35
|
+
* estimate via `estimateTokensForProvider`. Passing `provider` is recommended
|
|
36
|
+
* so the heuristic fallback is as accurate as possible.
|
|
37
|
+
*/
|
|
38
|
+
export async function countTokens(text, provider) {
|
|
28
39
|
const enc = await getEncoder();
|
|
29
40
|
if (enc) {
|
|
30
41
|
const tokens = enc.encode(text);
|
|
31
42
|
return tokens.length;
|
|
32
43
|
}
|
|
33
|
-
return
|
|
44
|
+
return estimateTokensForProvider(text, provider ?? "unknown");
|
|
34
45
|
}
|
|
35
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Synchronous token count — only accurate after `initTokenCounter()` resolves.
|
|
48
|
+
*
|
|
49
|
+
* Before init, or when tiktoken is unavailable, falls back to a provider-aware
|
|
50
|
+
* character-ratio estimate. Passing `provider` is recommended.
|
|
51
|
+
*/
|
|
52
|
+
export function countTokensSync(text, provider) {
|
|
36
53
|
if (encoder) {
|
|
37
54
|
return encoder.encode(text).length;
|
|
38
55
|
}
|
|
39
|
-
return
|
|
56
|
+
return estimateTokensForProvider(text, provider ?? "unknown");
|
|
40
57
|
}
|
|
41
58
|
export async function initTokenCounter() {
|
|
42
59
|
const enc = await getEncoder();
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// GSD Exec Search Tool — lists and filters prior gsd_exec runs.
|
|
2
|
+
//
|
|
3
|
+
// Scans .gsd/exec/*.meta.json and returns a ranked summary so agents can
|
|
4
|
+
// re-discover past runs without re-executing. Read-only; no DB writes.
|
|
5
|
+
import { searchExecHistory } from "../exec-history.js";
|
|
6
|
+
export function executeExecSearch(params, opts) {
|
|
7
|
+
const searchOpts = {
|
|
8
|
+
query: typeof params.query === "string" ? params.query : undefined,
|
|
9
|
+
runtime: params.runtime,
|
|
10
|
+
failing_only: params.failing_only === true,
|
|
11
|
+
limit: typeof params.limit === "number" ? params.limit : undefined,
|
|
12
|
+
};
|
|
13
|
+
const hits = searchExecHistory(opts.baseDir, searchOpts);
|
|
14
|
+
if (hits.length === 0) {
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: "text", text: "No prior gsd_exec runs match those filters." }],
|
|
17
|
+
details: { operation: "gsd_exec_search", matches: 0 },
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const lines = [`Found ${hits.length} exec run(s), most recent first:`];
|
|
21
|
+
for (const hit of hits) {
|
|
22
|
+
const e = hit.entry;
|
|
23
|
+
const status = formatStatus(e);
|
|
24
|
+
const purpose = e.purpose ? ` — ${e.purpose}` : "";
|
|
25
|
+
const truncated = e.stdout_truncated ? " (stdout truncated)" : "";
|
|
26
|
+
lines.push(`- [${e.id}] ${e.runtime} ${status} ${e.duration_ms}ms${truncated}${purpose}`, ` stdout: ${e.stdout_path}`);
|
|
27
|
+
if (hit.digest_preview) {
|
|
28
|
+
const preview = hit.digest_preview.replace(/\n/g, "\n ");
|
|
29
|
+
lines.push(` preview:\n ${preview}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
34
|
+
details: {
|
|
35
|
+
operation: "gsd_exec_search",
|
|
36
|
+
matches: hits.length,
|
|
37
|
+
results: hits.map((hit) => ({
|
|
38
|
+
id: hit.entry.id,
|
|
39
|
+
runtime: hit.entry.runtime,
|
|
40
|
+
exit_code: hit.entry.exit_code,
|
|
41
|
+
timed_out: hit.entry.timed_out,
|
|
42
|
+
duration_ms: hit.entry.duration_ms,
|
|
43
|
+
purpose: hit.entry.purpose,
|
|
44
|
+
stdout_path: hit.entry.stdout_path,
|
|
45
|
+
stderr_path: hit.entry.stderr_path,
|
|
46
|
+
meta_path: hit.entry.meta_path,
|
|
47
|
+
})),
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function formatStatus(entry) {
|
|
52
|
+
if (entry.timed_out)
|
|
53
|
+
return "timeout";
|
|
54
|
+
if (entry.signal)
|
|
55
|
+
return `signal:${entry.signal}`;
|
|
56
|
+
if (entry.exit_code === null)
|
|
57
|
+
return "exit:null";
|
|
58
|
+
return `exit:${entry.exit_code}`;
|
|
59
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// GSD Exec Tool — executor for the gsd_exec MCP tool.
|
|
2
|
+
//
|
|
3
|
+
// Thin wrapper around exec-sandbox.ts that reads effective options from
|
|
4
|
+
// the project preferences (context_mode block) and formats the result
|
|
5
|
+
// for MCP return.
|
|
6
|
+
import { EXEC_DEFAULTS, runExecSandbox, } from "../exec-sandbox.js";
|
|
7
|
+
import { isContextModeEnabled } from "../preferences-types.js";
|
|
8
|
+
export function buildExecOptions(baseDir, cfg, extras) {
|
|
9
|
+
const allowlist = Array.isArray(cfg?.exec_env_allowlist) ? cfg.exec_env_allowlist : EXEC_DEFAULTS.envAllowlist;
|
|
10
|
+
const stdoutCap = clampNumber(cfg?.exec_stdout_cap_bytes, EXEC_DEFAULTS.stdoutCapBytes, 4_096, 16_777_216);
|
|
11
|
+
const defaultTimeout = clampNumber(cfg?.exec_timeout_ms, EXEC_DEFAULTS.defaultTimeoutMs, 1_000, EXEC_DEFAULTS.clampTimeoutMs);
|
|
12
|
+
const digestChars = clampNumber(cfg?.exec_digest_chars, EXEC_DEFAULTS.digestChars, 0, 4_000);
|
|
13
|
+
return {
|
|
14
|
+
baseDir,
|
|
15
|
+
clamp_timeout_ms: EXEC_DEFAULTS.clampTimeoutMs,
|
|
16
|
+
default_timeout_ms: defaultTimeout,
|
|
17
|
+
stdout_cap_bytes: stdoutCap,
|
|
18
|
+
stderr_cap_bytes: EXEC_DEFAULTS.stderrCapBytes,
|
|
19
|
+
digest_chars: digestChars,
|
|
20
|
+
env_allowlist: allowlist,
|
|
21
|
+
...extras,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function clampNumber(value, fallback, min, max) {
|
|
25
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
26
|
+
return fallback;
|
|
27
|
+
if (value < min)
|
|
28
|
+
return min;
|
|
29
|
+
if (value > max)
|
|
30
|
+
return max;
|
|
31
|
+
return Math.floor(value);
|
|
32
|
+
}
|
|
33
|
+
function isEnabled(prefs) {
|
|
34
|
+
return isContextModeEnabled(prefs);
|
|
35
|
+
}
|
|
36
|
+
function disabledResult() {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: "gsd_exec is disabled by `context_mode.enabled: false` in preferences. Remove that " +
|
|
42
|
+
"override (or set it to true) to re-enable sandboxed tool-output execution.",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
details: { operation: "gsd_exec", error: "context_mode_disabled" },
|
|
46
|
+
isError: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function paramError(message) {
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
52
|
+
details: { operation: "gsd_exec", error: "invalid_params", detail: message },
|
|
53
|
+
isError: true,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export async function executeGsdExec(params, deps) {
|
|
57
|
+
if (!isEnabled(deps.preferences))
|
|
58
|
+
return disabledResult();
|
|
59
|
+
const runtime = params.runtime;
|
|
60
|
+
if (runtime !== "bash" && runtime !== "node" && runtime !== "python") {
|
|
61
|
+
return paramError(`invalid runtime "${String(runtime)}" — must be bash | node | python`);
|
|
62
|
+
}
|
|
63
|
+
const script = typeof params.script === "string" ? params.script : "";
|
|
64
|
+
if (script.trim().length === 0) {
|
|
65
|
+
return paramError("script is required and must be a non-empty string");
|
|
66
|
+
}
|
|
67
|
+
if (Buffer.byteLength(script, "utf8") > 200_000) {
|
|
68
|
+
return paramError("script exceeds the 200 KB length limit");
|
|
69
|
+
}
|
|
70
|
+
const opts = buildExecOptions(deps.baseDir, deps.preferences?.context_mode, { now: deps.now, generateId: deps.generateId });
|
|
71
|
+
const run = deps.run ?? runExecSandbox;
|
|
72
|
+
try {
|
|
73
|
+
const result = await run({
|
|
74
|
+
runtime,
|
|
75
|
+
script,
|
|
76
|
+
...(typeof params.purpose === "string" ? { purpose: params.purpose } : {}),
|
|
77
|
+
...(typeof params.timeout_ms === "number" ? { timeout_ms: params.timeout_ms } : {}),
|
|
78
|
+
}, opts);
|
|
79
|
+
return formatResult(result);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
83
|
+
return {
|
|
84
|
+
content: [{ type: "text", text: `Error: gsd_exec failed — ${message}` }],
|
|
85
|
+
details: { operation: "gsd_exec", error: message },
|
|
86
|
+
isError: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function formatResult(result) {
|
|
91
|
+
const headerLines = [
|
|
92
|
+
`gsd_exec[${result.id}] runtime=${result.runtime} exit=${formatExit(result)} duration=${result.duration_ms}ms`,
|
|
93
|
+
` stdout: ${result.stdout_bytes}B${result.stdout_truncated ? " (truncated)" : ""} → ${result.stdout_path}`,
|
|
94
|
+
` stderr: ${result.stderr_bytes}B${result.stderr_truncated ? " (truncated)" : ""} → ${result.stderr_path}`,
|
|
95
|
+
];
|
|
96
|
+
const summary = `${headerLines.join("\n")}\n--- digest ---\n${result.digest}`.trimEnd();
|
|
97
|
+
return {
|
|
98
|
+
content: [{ type: "text", text: summary }],
|
|
99
|
+
details: {
|
|
100
|
+
operation: "gsd_exec",
|
|
101
|
+
id: result.id,
|
|
102
|
+
runtime: result.runtime,
|
|
103
|
+
exit_code: result.exit_code,
|
|
104
|
+
signal: result.signal,
|
|
105
|
+
timed_out: result.timed_out,
|
|
106
|
+
duration_ms: result.duration_ms,
|
|
107
|
+
stdout_bytes: result.stdout_bytes,
|
|
108
|
+
stderr_bytes: result.stderr_bytes,
|
|
109
|
+
stdout_truncated: result.stdout_truncated,
|
|
110
|
+
stderr_truncated: result.stderr_truncated,
|
|
111
|
+
stdout_path: result.stdout_path,
|
|
112
|
+
stderr_path: result.stderr_path,
|
|
113
|
+
meta_path: result.meta_path,
|
|
114
|
+
},
|
|
115
|
+
isError: result.timed_out || result.signal !== null || result.exit_code !== 0,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function formatExit(result) {
|
|
119
|
+
if (result.timed_out)
|
|
120
|
+
return "timeout";
|
|
121
|
+
if (result.signal)
|
|
122
|
+
return `signal:${result.signal}`;
|
|
123
|
+
if (result.exit_code === null)
|
|
124
|
+
return "null";
|
|
125
|
+
return String(result.exit_code);
|
|
126
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// GSD Resume Tool — returns the contents of .gsd/last-snapshot.md so
|
|
2
|
+
// agents can re-orient after compaction or session resume without
|
|
3
|
+
// re-deriving project memory state.
|
|
4
|
+
import { readCompactionSnapshot } from "../compaction-snapshot.js";
|
|
5
|
+
export function executeResume(_params, opts) {
|
|
6
|
+
const snapshot = readCompactionSnapshot(opts.baseDir);
|
|
7
|
+
if (snapshot == null) {
|
|
8
|
+
return {
|
|
9
|
+
content: [
|
|
10
|
+
{
|
|
11
|
+
type: "text",
|
|
12
|
+
text: "No snapshot found at .gsd/last-snapshot.md. The snapshot is written automatically " +
|
|
13
|
+
"on session_before_compact (enabled by default; set context_mode.enabled=false to opt out).",
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
details: { operation: "gsd_resume", found: false },
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
content: [{ type: "text", text: snapshot }],
|
|
21
|
+
details: { operation: "gsd_resume", found: true, bytes: Buffer.byteLength(snapshot, "utf-8") },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -5,6 +5,9 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
5
5
|
const MCP_WORKFLOW_TOOL_SURFACE = new Set([
|
|
6
6
|
"ask_user_questions",
|
|
7
7
|
"gsd_decision_save",
|
|
8
|
+
"gsd_exec",
|
|
9
|
+
"gsd_exec_search",
|
|
10
|
+
"gsd_resume",
|
|
8
11
|
"gsd_complete_milestone",
|
|
9
12
|
"gsd_complete_task",
|
|
10
13
|
"gsd_complete_slice",
|