@stigmer/sdk 3.0.9-dev.20260615153829 → 3.1.0

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.
Files changed (89) hide show
  1. package/execution/__tests__/approval-provenance.test.d.ts +2 -0
  2. package/execution/__tests__/approval-provenance.test.d.ts.map +1 -0
  3. package/execution/__tests__/approval-provenance.test.js +42 -0
  4. package/execution/__tests__/approval-provenance.test.js.map +1 -0
  5. package/execution/__tests__/file-review-fold.corpus.test.d.ts +2 -0
  6. package/execution/__tests__/file-review-fold.corpus.test.d.ts.map +1 -0
  7. package/execution/__tests__/file-review-fold.corpus.test.js +82 -0
  8. package/execution/__tests__/file-review-fold.corpus.test.js.map +1 -0
  9. package/execution/__tests__/file-review-fold.test.d.ts +2 -0
  10. package/execution/__tests__/file-review-fold.test.d.ts.map +1 -0
  11. package/execution/__tests__/file-review-fold.test.js +184 -0
  12. package/execution/__tests__/file-review-fold.test.js.map +1 -0
  13. package/execution/__tests__/to-display-file-change.test.d.ts +2 -0
  14. package/execution/__tests__/to-display-file-change.test.d.ts.map +1 -0
  15. package/execution/__tests__/to-display-file-change.test.js +69 -0
  16. package/execution/__tests__/to-display-file-change.test.js.map +1 -0
  17. package/execution/__tests__/tool-view.file-changes.test.d.ts +2 -0
  18. package/execution/__tests__/tool-view.file-changes.test.d.ts.map +1 -0
  19. package/execution/__tests__/tool-view.file-changes.test.js +86 -0
  20. package/execution/__tests__/tool-view.file-changes.test.js.map +1 -0
  21. package/execution/__tests__/tool-view.fixtures.test.js +3 -0
  22. package/execution/__tests__/tool-view.fixtures.test.js.map +1 -1
  23. package/execution/__tests__/tool-view.output-ref.test.d.ts +2 -0
  24. package/execution/__tests__/tool-view.output-ref.test.d.ts.map +1 -0
  25. package/execution/__tests__/tool-view.output-ref.test.js +64 -0
  26. package/execution/__tests__/tool-view.output-ref.test.js.map +1 -0
  27. package/execution/__tests__/tool-view.search.test.d.ts +2 -0
  28. package/execution/__tests__/tool-view.search.test.d.ts.map +1 -0
  29. package/execution/__tests__/tool-view.search.test.js +200 -0
  30. package/execution/__tests__/tool-view.search.test.js.map +1 -0
  31. package/execution/__tests__/tool-view.shell.test.d.ts +2 -0
  32. package/execution/__tests__/tool-view.shell.test.d.ts.map +1 -0
  33. package/execution/__tests__/tool-view.shell.test.js +104 -0
  34. package/execution/__tests__/tool-view.shell.test.js.map +1 -0
  35. package/execution/approval-provenance.d.ts +30 -0
  36. package/execution/approval-provenance.d.ts.map +1 -0
  37. package/execution/approval-provenance.js +73 -0
  38. package/execution/approval-provenance.js.map +1 -0
  39. package/execution/execution-phases.d.ts +7 -0
  40. package/execution/execution-phases.d.ts.map +1 -0
  41. package/execution/execution-phases.js +21 -0
  42. package/execution/execution-phases.js.map +1 -0
  43. package/execution/file-review-fold.d.ts +44 -0
  44. package/execution/file-review-fold.d.ts.map +1 -0
  45. package/execution/file-review-fold.js +182 -0
  46. package/execution/file-review-fold.js.map +1 -0
  47. package/execution/to-display-file-change.d.ts +14 -0
  48. package/execution/to-display-file-change.d.ts.map +1 -0
  49. package/execution/to-display-file-change.js +57 -0
  50. package/execution/to-display-file-change.js.map +1 -0
  51. package/execution/tool-view.d.ts +8 -2
  52. package/execution/tool-view.d.ts.map +1 -1
  53. package/execution/tool-view.js +205 -21
  54. package/execution/tool-view.js.map +1 -1
  55. package/gen/agentexecution.d.ts +2 -1
  56. package/gen/agentexecution.d.ts.map +1 -1
  57. package/gen/agentexecution.js +8 -0
  58. package/gen/agentexecution.js.map +1 -1
  59. package/gen/mcpserver.d.ts +1 -0
  60. package/gen/mcpserver.d.ts.map +1 -1
  61. package/gen/mcpserver.js +1 -0
  62. package/gen/mcpserver.js.map +1 -1
  63. package/gen/workflowexecution.d.ts +2 -1
  64. package/gen/workflowexecution.d.ts.map +1 -1
  65. package/gen/workflowexecution.js +8 -0
  66. package/gen/workflowexecution.js.map +1 -1
  67. package/index.d.ts +5 -1
  68. package/index.d.ts.map +1 -1
  69. package/index.js +5 -1
  70. package/index.js.map +1 -1
  71. package/package.json +2 -2
  72. package/src/execution/__tests__/approval-provenance.test.ts +60 -0
  73. package/src/execution/__tests__/file-review-fold.corpus.test.ts +127 -0
  74. package/src/execution/__tests__/file-review-fold.test.ts +281 -0
  75. package/src/execution/__tests__/to-display-file-change.test.ts +91 -0
  76. package/src/execution/__tests__/tool-view.file-changes.test.ts +100 -0
  77. package/src/execution/__tests__/tool-view.fixtures.test.ts +4 -0
  78. package/src/execution/__tests__/tool-view.output-ref.test.ts +76 -0
  79. package/src/execution/__tests__/tool-view.search.test.ts +264 -0
  80. package/src/execution/__tests__/tool-view.shell.test.ts +127 -0
  81. package/src/execution/approval-provenance.ts +80 -0
  82. package/src/execution/execution-phases.ts +23 -0
  83. package/src/execution/file-review-fold.ts +210 -0
  84. package/src/execution/to-display-file-change.ts +66 -0
  85. package/src/execution/tool-view.ts +261 -30
  86. package/src/gen/agentexecution.ts +7 -1
  87. package/src/gen/mcpserver.ts +2 -0
  88. package/src/gen/workflowexecution.ts +7 -1
  89. package/src/index.ts +12 -0
@@ -0,0 +1,64 @@
1
+ // Covers the offloaded tool-output path: when a result is spilled to artifact
2
+ // storage the runner replaces it with a ToolCallOutputRef. The view must surface
3
+ // the STABLE storageKey (+ contentHash) so consumers resolve the bytes/URL on
4
+ // demand — it must never depend on a persisted (ephemeral) URL.
5
+ import { describe, it, expect } from "vitest";
6
+ import { create } from "@bufbuild/protobuf";
7
+ import { ToolCallSchema, ToolCallOutputRefSchema, } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
8
+ import { ToolCallStatus, ToolKind, } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
9
+ import { normalizeToolResult } from "../tool-view";
10
+ function toolCallWithOutputRef(ref, result = "") {
11
+ return create(ToolCallSchema, {
12
+ id: "tc-1",
13
+ name: "some_tool",
14
+ toolKind: ToolKind.UNSPECIFIED,
15
+ status: ToolCallStatus.TOOL_CALL_COMPLETED,
16
+ args: {},
17
+ result,
18
+ outputRef: ref,
19
+ });
20
+ }
21
+ describe("normalizeToolResult — offloaded output ref", () => {
22
+ it("emits an outputRef view carrying the stable storageKey and contentHash", () => {
23
+ const ref = create(ToolCallOutputRefSchema, {
24
+ storageKey: "artifacts/exec-1/toolcalls/tc-1.txt",
25
+ contentHash: "sha256:abc",
26
+ sizeBytes: 900000n,
27
+ mimeType: "text/plain",
28
+ isImage: false,
29
+ truncatedPreview: "head of the output…",
30
+ });
31
+ const view = normalizeToolResult(toolCallWithOutputRef(ref, "[output truncated]"));
32
+ expect(view.type).toBe("outputRef");
33
+ if (view.type !== "outputRef")
34
+ return;
35
+ expect(view.storageKey).toBe("artifacts/exec-1/toolcalls/tc-1.txt");
36
+ expect(view.contentHash).toBe("sha256:abc");
37
+ expect(view.isImage).toBe(false);
38
+ expect(view.mimeType).toBe("text/plain");
39
+ expect(view.sizeBytes).toBe(900_000);
40
+ expect(view.preview).toBe("head of the output…");
41
+ });
42
+ it("gates on storageKey, not a URL — an image ref renders inline", () => {
43
+ const ref = create(ToolCallOutputRefSchema, {
44
+ storageKey: "artifacts/exec-1/toolcalls/tc-1.png",
45
+ contentHash: "sha256:img",
46
+ sizeBytes: 12345n,
47
+ mimeType: "image/png",
48
+ isImage: true,
49
+ });
50
+ const view = normalizeToolResult(toolCallWithOutputRef(ref));
51
+ expect(view.type).toBe("outputRef");
52
+ if (view.type !== "outputRef")
53
+ return;
54
+ expect(view.isImage).toBe(true);
55
+ expect(view.storageKey).toBe("artifacts/exec-1/toolcalls/tc-1.png");
56
+ });
57
+ it("does not produce an outputRef view when no storageKey is present", () => {
58
+ // A ref with no storageKey is not a usable offload pointer; fall back to text.
59
+ const ref = create(ToolCallOutputRefSchema, { sizeBytes: 10n });
60
+ const view = normalizeToolResult(toolCallWithOutputRef(ref, "plain result"));
61
+ expect(view.type).not.toBe("outputRef");
62
+ });
63
+ });
64
+ //# sourceMappingURL=tool-view.output-ref.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-view.output-ref.test.js","sourceRoot":"","sources":["../../../src/execution/__tests__/tool-view.output-ref.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tool-view.search.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-view.search.test.d.ts","sourceRoot":"","sources":["../../../src/execution/__tests__/tool-view.search.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,200 @@
1
+ // Covers search normalization's envelope handling: the Cursor SDK returns search
2
+ // results as a stringified JSON envelope (file-name search via {status,value} and
3
+ // grep/codebase search via {workspaceResults}), which the original parser dumped
4
+ // as a single fake "match". The cross-language fixture (result-views.json)
5
+ // asserts the happy-path `type`/`count`; these cover the `kind`/`truncated`
6
+ // presentation hints, the multi-workspace flatten, the content-match mapping, and
7
+ // the unrecognized-JSON -> json degradation that is not a shared scalar fact.
8
+ import { describe, it, expect } from "vitest";
9
+ import { create } from "@bufbuild/protobuf";
10
+ import { ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
11
+ import { ToolCallStatus, ToolKind, } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
12
+ import { normalizeToolResult } from "../tool-view";
13
+ function searchCall(args, result) {
14
+ return create(ToolCallSchema, {
15
+ id: "tc-search",
16
+ name: "Grep",
17
+ toolKind: ToolKind.SEARCH,
18
+ status: ToolCallStatus.TOOL_CALL_COMPLETED,
19
+ args: args,
20
+ result,
21
+ });
22
+ }
23
+ describe("normalizeToolResult — Cursor file-name search envelope", () => {
24
+ it("unwraps an empty {status,value} file search (the reported bug: not '1 match')", () => {
25
+ const view = normalizeToolResult(searchCall({ pattern: "**/*.nope" }, JSON.stringify({
26
+ status: "success",
27
+ value: { files: [], totalFiles: 0, clientTruncated: false, ripgrepTruncated: false },
28
+ })));
29
+ expect(view.type).toBe("search");
30
+ if (view.type !== "search")
31
+ return;
32
+ expect(view.kind).toBe("files");
33
+ expect(view.count).toBe(0);
34
+ expect(view.matches).toHaveLength(0);
35
+ expect(view.truncated).toBe(false);
36
+ });
37
+ it("unwraps a non-empty file search into clickable file matches", () => {
38
+ const view = normalizeToolResult(searchCall({ pattern: "Dockerfile" }, JSON.stringify({
39
+ status: "success",
40
+ value: { files: ["Dockerfile"], totalFiles: 1, clientTruncated: false, ripgrepTruncated: false },
41
+ })));
42
+ expect(view.type).toBe("search");
43
+ if (view.type !== "search")
44
+ return;
45
+ expect(view.kind).toBe("files");
46
+ expect(view.count).toBe(1);
47
+ // Both file and text are set so a kind-unaware consumer still shows the path.
48
+ expect(view.matches[0]).toEqual({ file: "Dockerfile", text: "Dockerfile" });
49
+ });
50
+ it("carries the engine's truncation flags and authoritative totalFiles", () => {
51
+ const view = normalizeToolResult(searchCall({ pattern: "*.ts" }, JSON.stringify({
52
+ status: "success",
53
+ value: { files: ["a.ts", "b.ts"], totalFiles: 200, clientTruncated: true, ripgrepTruncated: false },
54
+ })));
55
+ expect(view.type).toBe("search");
56
+ if (view.type !== "search")
57
+ return;
58
+ // totalFiles is authoritative and can exceed the returned page.
59
+ expect(view.count).toBe(200);
60
+ expect(view.matches).toHaveLength(2);
61
+ expect(view.truncated).toBe(true);
62
+ });
63
+ });
64
+ describe("normalizeToolResult — Cursor grep workspaceResults envelope", () => {
65
+ it("unwraps the real {status,value:{workspaceResults}} grep shape (the reported bug)", () => {
66
+ // The grep payload nests workspaceResults INSIDE the {status,value} envelope —
67
+ // the shape the runner actually persists. The original parser only looked at
68
+ // the top level, so this fell through to a raw JSON dump.
69
+ const view = normalizeToolResult(searchCall({ pattern: "pipeline" }, JSON.stringify({
70
+ status: "success",
71
+ value: {
72
+ workspaceResults: {
73
+ "/work/demo": { type: "files", output: { files: [], count: 0 } },
74
+ },
75
+ },
76
+ })));
77
+ expect(view.type).toBe("search");
78
+ if (view.type !== "search")
79
+ return;
80
+ expect(view.kind).toBe("files");
81
+ expect(view.count).toBe(0);
82
+ });
83
+ it("still reads an un-enveloped top-level workspaceResults (defensive)", () => {
84
+ const view = normalizeToolResult(searchCall({ pattern: "pipeline" }, JSON.stringify({
85
+ workspaceResults: { "/work/demo": { type: "files", output: { files: [], count: 0 } } },
86
+ })));
87
+ expect(view.type).toBe("search");
88
+ if (view.type !== "search")
89
+ return;
90
+ expect(view.kind).toBe("files");
91
+ expect(view.count).toBe(0);
92
+ });
93
+ it("flattens file matches across multiple workspaces and sums reported counts", () => {
94
+ const view = normalizeToolResult(searchCall({ pattern: "TODO" }, JSON.stringify({
95
+ status: "success",
96
+ value: {
97
+ workspaceResults: {
98
+ "/work/a": { type: "files", output: { files: ["a/x.ts"], count: 1 } },
99
+ "/work/b": { type: "files", output: { files: ["b/y.ts"], count: 1 } },
100
+ },
101
+ },
102
+ })));
103
+ expect(view.type).toBe("search");
104
+ if (view.type !== "search")
105
+ return;
106
+ expect(view.kind).toBe("files");
107
+ expect(view.count).toBe(2);
108
+ expect(view.matches.map((m) => m.file)).toEqual(["a/x.ts", "b/y.ts"]);
109
+ });
110
+ it("renders a non-empty grep (type:files) as a file list, not 0 files", () => {
111
+ // The real wrapped shape with results present — proves a populated grep is
112
+ // shown (the user's concern that a non-empty response might render as empty).
113
+ const view = normalizeToolResult(searchCall({ pattern: "pipeline" }, JSON.stringify({
114
+ status: "success",
115
+ value: {
116
+ workspaceResults: {
117
+ "/work/demo": {
118
+ type: "files",
119
+ output: { files: [".tekton/pipeline.yaml", "README.md"], count: 2 },
120
+ },
121
+ },
122
+ },
123
+ })));
124
+ expect(view.type).toBe("search");
125
+ if (view.type !== "search")
126
+ return;
127
+ expect(view.kind).toBe("files");
128
+ expect(view.count).toBe(2);
129
+ expect(view.matches.map((m) => m.file)).toEqual([".tekton/pipeline.yaml", "README.md"]);
130
+ });
131
+ it("falls back to JSON (never hides data) when a count is reported but nothing extracts", () => {
132
+ // Shape drift: the engine says count:5 but the matches live under a key we
133
+ // don't recognise. Surfacing the raw JSON beats a misleading "No matches".
134
+ const view = normalizeToolResult(searchCall({ pattern: "x" }, JSON.stringify({
135
+ status: "success",
136
+ value: {
137
+ workspaceResults: {
138
+ "/work/demo": { type: "weird", output: { hits: ["a", "b"], count: 5 } },
139
+ },
140
+ },
141
+ })));
142
+ expect(view.type).toBe("json");
143
+ });
144
+ it("falls back to JSON when a file search reports totalFiles but no extractable paths", () => {
145
+ // files are objects, not strings (a drift) — but totalFiles says 3.
146
+ const view = normalizeToolResult(searchCall({ pattern: "*.ts" }, JSON.stringify({
147
+ status: "success",
148
+ value: { files: [{ path: "a.ts" }], totalFiles: 3 },
149
+ })));
150
+ expect(view.type).toBe("json");
151
+ });
152
+ it("maps line-bearing matches into grouped content matches", () => {
153
+ const view = normalizeToolResult(searchCall({ pattern: "TODO" }, JSON.stringify({
154
+ status: "success",
155
+ value: {
156
+ workspaceResults: {
157
+ "/work/a": {
158
+ type: "matches",
159
+ output: {
160
+ matches: [
161
+ { file: "a/x.ts", line: 12, text: "// TODO: fix" },
162
+ { file: "a/x.ts", line: 30, text: "// TODO: later" },
163
+ ],
164
+ count: 2,
165
+ },
166
+ },
167
+ },
168
+ },
169
+ })));
170
+ expect(view.type).toBe("search");
171
+ if (view.type !== "search")
172
+ return;
173
+ expect(view.kind).toBe("content");
174
+ expect(view.count).toBe(2);
175
+ expect(view.matches[0]).toEqual({ file: "a/x.ts", line: 12, text: "// TODO: fix" });
176
+ });
177
+ });
178
+ describe("normalizeToolResult — search plain text and graceful degradation", () => {
179
+ it("keeps native grep line matches as content (unchanged behavior)", () => {
180
+ const view = normalizeToolResult(searchCall({ pattern: "TODO" }, "\n/workspace/a.go:\n 12: // TODO: fix\n/workspace/b.go:\n 7: // TODO: later"));
181
+ expect(view.type).toBe("search");
182
+ if (view.type !== "search")
183
+ return;
184
+ expect(view.kind).toBe("content");
185
+ expect(view.count).toBe(2);
186
+ });
187
+ it("treats native path/name lines as file matches", () => {
188
+ const view = normalizeToolResult(searchCall({ pattern: "*.go" }, "src/a.go\nsrc/b.go"));
189
+ expect(view.type).toBe("search");
190
+ if (view.type !== "search")
191
+ return;
192
+ expect(view.kind).toBe("files");
193
+ expect(view.count).toBe(2);
194
+ });
195
+ it("degrades an unrecognized JSON shape to a json view, not a fake match", () => {
196
+ const view = normalizeToolResult(searchCall({ pattern: "x" }, JSON.stringify({ somethingElse: true })));
197
+ expect(view.type).toBe("json");
198
+ });
199
+ });
200
+ //# sourceMappingURL=tool-view.search.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-view.search.test.js","sourceRoot":"","sources":["../../../src/execution/__tests__/tool-view.search.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tool-view.shell.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-view.shell.test.d.ts","sourceRoot":"","sources":["../../../src/execution/__tests__/tool-view.shell.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
1
+ // Covers shell normalization's `command` capture and result-shape handling: a
2
+ // terminal view models the whole session (prompt + output), so the command is
3
+ // echoed from args onto the view across every result shape — un-enveloped Cursor
4
+ // JSON, the Cursor {status,value} envelope, the exit-marker form, and plain
5
+ // text. The cross-language fixture (result-views.json) asserts the happy path;
6
+ // these cover the branch matrix, the envelope unwrap (the reported bug), and the
7
+ // missing-command edge.
8
+ import { describe, it, expect } from "vitest";
9
+ import { create } from "@bufbuild/protobuf";
10
+ import { ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
11
+ import { ToolCallStatus, ToolKind, } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
12
+ import { normalizeToolResult } from "../tool-view";
13
+ function shellCall(args, result) {
14
+ return create(ToolCallSchema, {
15
+ id: "tc-shell",
16
+ name: "shell",
17
+ toolKind: ToolKind.SHELL,
18
+ status: ToolCallStatus.TOOL_CALL_COMPLETED,
19
+ args: args,
20
+ result,
21
+ });
22
+ }
23
+ describe("normalizeToolResult — shell command capture", () => {
24
+ it("captures the command on the plain (no-marker) branch", () => {
25
+ const view = normalizeToolResult(shellCall({ command: "echo hi" }, "hi\n"));
26
+ expect(view.type).toBe("terminal");
27
+ if (view.type !== "terminal")
28
+ return;
29
+ expect(view.command).toBe("echo hi");
30
+ expect(view.stdout).toBe("hi\n");
31
+ });
32
+ it("captures the command on the exit-marker branch (success and failure)", () => {
33
+ const ok = normalizeToolResult(shellCall({ command: "ls -la" }, "total 8\n[Command succeeded]"));
34
+ expect(ok.type).toBe("terminal");
35
+ if (ok.type !== "terminal")
36
+ return;
37
+ expect(ok.command).toBe("ls -la");
38
+ expect(ok.exitCode).toBe(0);
39
+ const bad = normalizeToolResult(shellCall({ command: "false" }, "boom\n[Command failed with exit code 2]"));
40
+ expect(bad.type).toBe("terminal");
41
+ if (bad.type !== "terminal")
42
+ return;
43
+ expect(bad.command).toBe("false");
44
+ expect(bad.exitCode).toBe(2);
45
+ });
46
+ it("captures the command on the structured Cursor JSON branch", () => {
47
+ const view = normalizeToolResult(shellCall({ command: "npm test" }, JSON.stringify({ stdout: "ok", stderr: "", exitCode: 0 })));
48
+ expect(view.type).toBe("terminal");
49
+ if (view.type !== "terminal")
50
+ return;
51
+ expect(view.command).toBe("npm test");
52
+ expect(view.stdout).toBe("ok");
53
+ });
54
+ it("unwraps the Cursor {status,value} envelope on success (the reported bug)", () => {
55
+ const view = normalizeToolResult(shellCall({ command: "ls -la" }, JSON.stringify({
56
+ status: "success",
57
+ value: {
58
+ exitCode: 0,
59
+ signal: "",
60
+ stdout: "total 8\ndrwxr-xr-x 2 user user 4096 .\n",
61
+ stderr: "",
62
+ executionTime: 1176,
63
+ },
64
+ })));
65
+ expect(view.type).toBe("terminal");
66
+ if (view.type !== "terminal")
67
+ return;
68
+ expect(view.command).toBe("ls -la");
69
+ // The real stdout surfaces — NOT the raw envelope JSON.
70
+ expect(view.stdout).toBe("total 8\ndrwxr-xr-x 2 user user 4096 .\n");
71
+ expect(view.exitCode).toBe(0);
72
+ // Regression guard: the envelope keys must never leak into the rendered output.
73
+ expect(view.stdout).not.toContain("status");
74
+ expect(view.stdout).not.toContain("value");
75
+ expect(view.stdout).not.toContain("executionTime");
76
+ });
77
+ it("unwraps the Cursor envelope on failure (surfaces stderr and exit code)", () => {
78
+ const view = normalizeToolResult(shellCall({ command: "ls /nope" }, JSON.stringify({
79
+ status: "success",
80
+ value: {
81
+ exitCode: 2,
82
+ signal: "",
83
+ stdout: "",
84
+ stderr: "ls: /nope: No such file or directory\n",
85
+ executionTime: 5,
86
+ },
87
+ })));
88
+ expect(view.type).toBe("terminal");
89
+ if (view.type !== "terminal")
90
+ return;
91
+ expect(view.command).toBe("ls /nope");
92
+ expect(view.stderr).toBe("ls: /nope: No such file or directory\n");
93
+ expect(view.exitCode).toBe(2);
94
+ });
95
+ it("leaves command undefined when args carry no command", () => {
96
+ const view = normalizeToolResult(shellCall({}, "orphan output\n"));
97
+ expect(view.type).toBe("terminal");
98
+ if (view.type !== "terminal")
99
+ return;
100
+ expect(view.command).toBeUndefined();
101
+ expect(view.stdout).toBe("orphan output\n");
102
+ });
103
+ });
104
+ //# sourceMappingURL=tool-view.shell.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-view.shell.test.js","sourceRoot":"","sources":["../../../src/execution/__tests__/tool-view.shell.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { ApprovalPolicySource } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
2
+ export { ApprovalPolicySource };
3
+ /**
4
+ * Returns a short human phrase describing a tool call's authorization
5
+ * provenance, or `null` for {@link ApprovalPolicySource.UNSPECIFIED} — an
6
+ * execution that predates this field, or a tool the gate never evaluated (e.g. a
7
+ * read-only built-in) — so callers render nothing rather than a misleading
8
+ * default.
9
+ */
10
+ export declare function describeApprovalPolicySource(source: ApprovalPolicySource): string | null;
11
+ /**
12
+ * Returns whether a policy source carries information worth surfacing inline at
13
+ * the approval gate, versus the everyday default ("this tool category just
14
+ * requires approval") that is noise next to the action it is already gating.
15
+ *
16
+ * The default gating reasons — {@link ApprovalPolicySource.CLASSIFIER_DEFAULT}
17
+ * and {@link ApprovalPolicySource.BUILTIN_CATEGORY} — explain nothing the user
18
+ * does not already infer from the tool itself, so they are suppressed from the
19
+ * card (the full phrase stays available on hover where a surface chooses to show
20
+ * a chip). The remaining sources each change the user's understanding of *why*
21
+ * this particular call is held — an explicit override, a server tightening a
22
+ * destructive tool, or (post-execution) a bypass/lease that cleared it — and so
23
+ * are worth showing. {@link ApprovalPolicySource.UNSPECIFIED} is never
24
+ * informative (legacy / ungated).
25
+ *
26
+ * This is the headless policy behind the gate's "smart-suppress" provenance
27
+ * chip; rendering lives in the consuming surface.
28
+ */
29
+ export declare function isInformativePolicySource(source: ApprovalPolicySource): boolean;
30
+ //# sourceMappingURL=approval-provenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-provenance.d.ts","sourceRoot":"","sources":["../../src/execution/approval-provenance.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AAEpG,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,oBAAoB,GAC3B,MAAM,GAAG,IAAI,CAoBf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAcT"}
@@ -0,0 +1,73 @@
1
+ // Framework-agnostic authorization-provenance labels for every Stigmer surface.
2
+ //
3
+ // describeApprovalPolicySource maps the wire ApprovalPolicySource — *which policy
4
+ // layer decided a tool call's approval requirement* — to a short human phrase.
5
+ // It is shared by @stigmer/react (the ApprovalCard "why-gated" line and the
6
+ // tool-call detail view) and @stigmer/ink (the terminal approval prompt); the Go
7
+ // CLI mirrors it. The phrasing is intrinsic to the source's semantics so the
8
+ // same label reads correctly whether the call is still waiting (a gating source
9
+ // → "required by …") or already cleared (a bypass source → "auto-approved …").
10
+ import { ApprovalPolicySource } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
11
+ export { ApprovalPolicySource };
12
+ /**
13
+ * Returns a short human phrase describing a tool call's authorization
14
+ * provenance, or `null` for {@link ApprovalPolicySource.UNSPECIFIED} — an
15
+ * execution that predates this field, or a tool the gate never evaluated (e.g. a
16
+ * read-only built-in) — so callers render nothing rather than a misleading
17
+ * default.
18
+ */
19
+ export function describeApprovalPolicySource(source) {
20
+ switch (source) {
21
+ case ApprovalPolicySource.CLASSIFIER_DEFAULT:
22
+ return "required by the tool's default policy";
23
+ case ApprovalPolicySource.PINNED_OVERRIDE:
24
+ return "required by a pinned override";
25
+ case ApprovalPolicySource.AGENT_OVERRIDE:
26
+ return "required by agent override";
27
+ case ApprovalPolicySource.BUILTIN_CATEGORY:
28
+ return "required by built-in tool policy";
29
+ case ApprovalPolicySource.ANNOTATION_DESTRUCTIVE_TIGHTEN:
30
+ return "required: marked destructive by the server";
31
+ case ApprovalPolicySource.AUTO_APPROVE_ALL:
32
+ return "auto-approved by a run-wide bypass";
33
+ case ApprovalPolicySource.APPROVAL_LEASE:
34
+ return "auto-approved by a run lease";
35
+ case ApprovalPolicySource.UNSPECIFIED:
36
+ default:
37
+ return null;
38
+ }
39
+ }
40
+ /**
41
+ * Returns whether a policy source carries information worth surfacing inline at
42
+ * the approval gate, versus the everyday default ("this tool category just
43
+ * requires approval") that is noise next to the action it is already gating.
44
+ *
45
+ * The default gating reasons — {@link ApprovalPolicySource.CLASSIFIER_DEFAULT}
46
+ * and {@link ApprovalPolicySource.BUILTIN_CATEGORY} — explain nothing the user
47
+ * does not already infer from the tool itself, so they are suppressed from the
48
+ * card (the full phrase stays available on hover where a surface chooses to show
49
+ * a chip). The remaining sources each change the user's understanding of *why*
50
+ * this particular call is held — an explicit override, a server tightening a
51
+ * destructive tool, or (post-execution) a bypass/lease that cleared it — and so
52
+ * are worth showing. {@link ApprovalPolicySource.UNSPECIFIED} is never
53
+ * informative (legacy / ungated).
54
+ *
55
+ * This is the headless policy behind the gate's "smart-suppress" provenance
56
+ * chip; rendering lives in the consuming surface.
57
+ */
58
+ export function isInformativePolicySource(source) {
59
+ switch (source) {
60
+ case ApprovalPolicySource.PINNED_OVERRIDE:
61
+ case ApprovalPolicySource.AGENT_OVERRIDE:
62
+ case ApprovalPolicySource.ANNOTATION_DESTRUCTIVE_TIGHTEN:
63
+ case ApprovalPolicySource.AUTO_APPROVE_ALL:
64
+ case ApprovalPolicySource.APPROVAL_LEASE:
65
+ return true;
66
+ case ApprovalPolicySource.CLASSIFIER_DEFAULT:
67
+ case ApprovalPolicySource.BUILTIN_CATEGORY:
68
+ case ApprovalPolicySource.UNSPECIFIED:
69
+ default:
70
+ return false;
71
+ }
72
+ }
73
+ //# sourceMappingURL=approval-provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-provenance.js","sourceRoot":"","sources":["../../src/execution/approval-provenance.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,kFAAkF;AAClF,+EAA+E;AAC/E,4EAA4E;AAC5E,iFAAiF;AACjF,6EAA6E;AAC7E,gFAAgF;AAChF,+EAA+E;AAE/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AAEpG,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B,CAC1C,MAA4B;IAE5B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,oBAAoB,CAAC,kBAAkB;YAC1C,OAAO,uCAAuC,CAAC;QACjD,KAAK,oBAAoB,CAAC,eAAe;YACvC,OAAO,+BAA+B,CAAC;QACzC,KAAK,oBAAoB,CAAC,cAAc;YACtC,OAAO,4BAA4B,CAAC;QACtC,KAAK,oBAAoB,CAAC,gBAAgB;YACxC,OAAO,kCAAkC,CAAC;QAC5C,KAAK,oBAAoB,CAAC,8BAA8B;YACtD,OAAO,4CAA4C,CAAC;QACtD,KAAK,oBAAoB,CAAC,gBAAgB;YACxC,OAAO,oCAAoC,CAAC;QAC9C,KAAK,oBAAoB,CAAC,cAAc;YACtC,OAAO,8BAA8B,CAAC;QACxC,KAAK,oBAAoB,CAAC,WAAW,CAAC;QACtC;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAA4B;IAE5B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,oBAAoB,CAAC,eAAe,CAAC;QAC1C,KAAK,oBAAoB,CAAC,cAAc,CAAC;QACzC,KAAK,oBAAoB,CAAC,8BAA8B,CAAC;QACzD,KAAK,oBAAoB,CAAC,gBAAgB,CAAC;QAC3C,KAAK,oBAAoB,CAAC,cAAc;YACtC,OAAO,IAAI,CAAC;QACd,KAAK,oBAAoB,CAAC,kBAAkB,CAAC;QAC7C,KAAK,oBAAoB,CAAC,gBAAgB,CAAC;QAC3C,KAAK,oBAAoB,CAAC,WAAW,CAAC;QACtC;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
2
+ /**
3
+ * Returns `true` when the given phase represents a final, immutable
4
+ * execution state — no further updates will arrive from the server.
5
+ */
6
+ export declare function isTerminalPhase(phase: ExecutionPhase): boolean;
7
+ //# sourceMappingURL=execution-phases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-phases.d.ts","sourceRoot":"","sources":["../../src/execution/execution-phases.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAS9F;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAE9D"}
@@ -0,0 +1,21 @@
1
+ // Framework-agnostic execution-phase predicates.
2
+ //
3
+ // Lives in @stigmer/sdk (the pure layer) so it is shared by @stigmer/react and
4
+ // @stigmer/ink and usable by pure logic here (e.g. the file-review fold's corpus
5
+ // parity test reproduces the server's terminal-phase gate). @stigmer/react
6
+ // re-exports it so its public API is unchanged.
7
+ import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
8
+ const TERMINAL_PHASES = new Set([
9
+ ExecutionPhase.EXECUTION_COMPLETED,
10
+ ExecutionPhase.EXECUTION_FAILED,
11
+ ExecutionPhase.EXECUTION_CANCELLED,
12
+ ExecutionPhase.EXECUTION_TERMINATED,
13
+ ]);
14
+ /**
15
+ * Returns `true` when the given phase represents a final, immutable
16
+ * execution state — no further updates will arrive from the server.
17
+ */
18
+ export function isTerminalPhase(phase) {
19
+ return TERMINAL_PHASES.has(phase);
20
+ }
21
+ //# sourceMappingURL=execution-phases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-phases.js","sourceRoot":"","sources":["../../src/execution/execution-phases.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,+EAA+E;AAC/E,iFAAiF;AACjF,2EAA2E;AAC3E,gDAAgD;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAE9F,MAAM,eAAe,GAAgC,IAAI,GAAG,CAAC;IAC3D,cAAc,CAAC,mBAAmB;IAClC,cAAc,CAAC,gBAAgB;IAC/B,cAAc,CAAC,mBAAmB;IAClC,cAAc,CAAC,oBAAoB;CACpC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAqB;IACnD,OAAO,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { AgentExecutionStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
2
+ import type { FileChangeSet, FileReviewEventStream } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
3
+ /**
4
+ * Folds a file-review event ledger into its list of {@link FileChangeSet}s,
5
+ * grouped by `change_set_id` in first-seen order.
6
+ *
7
+ * This is the display fold: unlike the server projection it does NOT collapse to
8
+ * an empty list for a terminal execution, so a completed/failed/cancelled
9
+ * execution still yields its settled sets for read-only display. For the LIVE
10
+ * (actionable) view, prefer the server-computed `status.file_change_sets`
11
+ * projection (it is structurally shared across stream frames); this fold is the
12
+ * settled/terminal complement — see {@link displayFileChangeSets}.
13
+ *
14
+ * The fold is a faithful port of the Go/Java projector: scalar and snapshot
15
+ * fields are last-writer-wins, `decisions` accumulate, `changes` are replaced
16
+ * wholesale by the latest `CANDIDATE_CAPTURED`, and terminal `RECONCILED` /
17
+ * `FAILED` statuses are sticky (a later non-terminal event never downgrades
18
+ * them).
19
+ *
20
+ * @param stream - The execution's `file_review_event_stream`, or `undefined`.
21
+ * @returns One {@link FileChangeSet} per `change_set_id`, in first-seen order.
22
+ */
23
+ export declare function foldFileReviewEventStream(stream: FileReviewEventStream | undefined): FileChangeSet[];
24
+ /**
25
+ * The single read seam for displaying an execution's file change sets.
26
+ *
27
+ * Returns the server-computed `status.file_change_sets` projection when it is
28
+ * present (a LIVE execution — the projection is structurally shared across
29
+ * stream frames, so consumers keep stable references and streaming re-renders
30
+ * stay scoped to the actively-changing card), and otherwise folds the ledger
31
+ * (a TERMINAL execution — the server projects nil there, but the ledger is
32
+ * preserved). The fold therefore never runs on the streaming hot path; it only
33
+ * reconstructs the settled sets a dead execution would otherwise not display.
34
+ *
35
+ * The two branches are equivalent by construction for a non-terminal execution
36
+ * (the fold minus its terminal gate IS the server projection — locked by the
37
+ * corpus parity test), so this accessor is a single consistent source whichever
38
+ * branch it takes.
39
+ *
40
+ * @param status - The execution status, or `undefined`.
41
+ * @returns The change sets to display, or an empty array when there are none.
42
+ */
43
+ export declare function displayFileChangeSets(status: AgentExecutionStatus | undefined): FileChangeSet[];
44
+ //# sourceMappingURL=file-review-fold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-review-fold.d.ts","sourceRoot":"","sources":["../../src/execution/file-review-fold.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6DAA6D,CAAC;AACxG,OAAO,KAAK,EACV,aAAa,EAEb,qBAAqB,EACtB,MAAM,oEAAoE,CAAC;AAQ5E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,qBAAqB,GAAG,SAAS,GACxC,aAAa,EAAE,CAsBjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,oBAAoB,GAAG,SAAS,GACvC,aAAa,EAAE,CAIjB"}