@stigmer/ink 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.
@@ -15,8 +15,10 @@ export interface ApprovalPromptProps {
15
15
  * Displays the tool name and args preview, then presents
16
16
  * Approve/Approve-all/Reject/Skip options navigable via arrow keys
17
17
  * or shortcut keys (y/a/n/s). Press Enter to confirm the highlighted
18
- * selection. "Approve & don't ask again" (a) maps to APPROVE_ALL, which
19
- * stops gating the rest of the run.
18
+ * selection. The approve-all option (a) maps to APPROVE_ALL, which grants a
19
+ * run-lifetime lease scoped to the clicked tool's CLASS (its MCP server, or its
20
+ * file edit / delete / shell category) — other classes keep prompting. The
21
+ * option label names that class so the scope is never a surprise.
20
22
  */
21
23
  export declare function ApprovalPrompt({ pendingApproval, onSubmit, isSubmitting, }: ApprovalPromptProps): import("react/jsx-runtime").JSX.Element;
22
24
  //# sourceMappingURL=ApprovalPrompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApprovalPrompt.d.ts","sourceRoot":"","sources":["../../src/components/ApprovalPrompt.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kEAAkE,CAAC;AACxG,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAE9F,wCAAwC;AACxC,MAAM,WAAW,mBAAmB;IAClC,8CAA8C;IAC9C,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IACpD,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAoCD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAC7B,eAAe,EACf,QAAQ,EACR,YAAoB,GACrB,EAAE,mBAAmB,2CAmFrB"}
1
+ {"version":3,"file":"ApprovalPrompt.d.ts","sourceRoot":"","sources":["../../src/components/ApprovalPrompt.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kEAAkE,CAAC;AACxG,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAO9F,wCAAwC;AACxC,MAAM,WAAW,mBAAmB;IAClC,8CAA8C;IAC9C,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IACpD,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAuCD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,EAC7B,eAAe,EACf,QAAQ,EACR,YAAoB,GACrB,EAAE,mBAAmB,2CAmIrB"}
@@ -1,60 +1,89 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { useMemo, useState } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
4
  import { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
- const OPTIONS = [
6
- {
7
- label: "Approve",
8
- action: ApprovalAction.APPROVE,
9
- color: "green",
10
- shortcut: "y",
11
- },
12
- {
13
- label: "Approve & don't ask again",
14
- action: ApprovalAction.APPROVE_ALL,
15
- color: "green",
16
- shortcut: "a",
17
- },
18
- {
19
- label: "Reject",
20
- action: ApprovalAction.REJECT,
21
- color: "red",
22
- shortcut: "n",
23
- },
24
- {
25
- label: "Skip",
26
- action: ApprovalAction.SKIP,
27
- color: "yellow",
28
- shortcut: "s",
29
- },
30
- ];
5
+ import { ToolKind, resolveToolKindByName, describeApprovalPolicySource, } from "@stigmer/sdk";
6
+ /**
7
+ * Builds the truthful APPROVE_ALL option label for a pending approval's lease
8
+ * class — the terminal mirror of the React card's buildApproveAllLabel.
9
+ *
10
+ * APPROVE_ALL grants a run-lifetime lease scoped to ONE class: the MCP server
11
+ * for an MCP tool, otherwise the approval category (write/delete/shell), where
12
+ * FILE_WRITE and FILE_EDIT collapse to one "file edits" class exactly as the
13
+ * runner's toolApprovalCategory collapses them. The label names that class so it
14
+ * never implies a broader, run-wide bypass.
15
+ */
16
+ function buildApproveAllLabel(toolName, mcpServerSlug) {
17
+ if (mcpServerSlug) {
18
+ return `Approve all ${mcpServerSlug} tools`;
19
+ }
20
+ switch (resolveToolKindByName(toolName, mcpServerSlug)) {
21
+ case ToolKind.SHELL:
22
+ return "Approve all shell commands";
23
+ case ToolKind.FILE_DELETE:
24
+ return "Approve all file deletions";
25
+ case ToolKind.FILE_WRITE:
26
+ case ToolKind.FILE_EDIT:
27
+ return "Approve all file edits";
28
+ default:
29
+ return "Approve all of this kind";
30
+ }
31
+ }
31
32
  /**
32
33
  * HITL approval prompt for tool call authorization.
33
34
  *
34
35
  * Displays the tool name and args preview, then presents
35
36
  * Approve/Approve-all/Reject/Skip options navigable via arrow keys
36
37
  * or shortcut keys (y/a/n/s). Press Enter to confirm the highlighted
37
- * selection. "Approve & don't ask again" (a) maps to APPROVE_ALL, which
38
- * stops gating the rest of the run.
38
+ * selection. The approve-all option (a) maps to APPROVE_ALL, which grants a
39
+ * run-lifetime lease scoped to the clicked tool's CLASS (its MCP server, or its
40
+ * file edit / delete / shell category) — other classes keep prompting. The
41
+ * option label names that class so the scope is never a surprise.
39
42
  */
40
43
  export function ApprovalPrompt({ pendingApproval, onSubmit, isSubmitting = false, }) {
41
44
  const [selectedIndex, setSelectedIndex] = useState(0);
45
+ const options = useMemo(() => [
46
+ {
47
+ label: "Approve",
48
+ action: ApprovalAction.APPROVE,
49
+ color: "green",
50
+ shortcut: "y",
51
+ },
52
+ {
53
+ label: buildApproveAllLabel(pendingApproval.toolName, pendingApproval.mcpServerSlug),
54
+ action: ApprovalAction.APPROVE_ALL,
55
+ color: "green",
56
+ shortcut: "a",
57
+ },
58
+ {
59
+ label: "Reject",
60
+ action: ApprovalAction.REJECT,
61
+ color: "red",
62
+ shortcut: "n",
63
+ },
64
+ {
65
+ label: "Skip",
66
+ action: ApprovalAction.SKIP,
67
+ color: "yellow",
68
+ shortcut: "s",
69
+ },
70
+ ], [pendingApproval.toolName, pendingApproval.mcpServerSlug]);
42
71
  useInput((input, key) => {
43
72
  if (isSubmitting)
44
73
  return;
45
74
  if (key.upArrow || key.leftArrow) {
46
- setSelectedIndex((i) => (i > 0 ? i - 1 : OPTIONS.length - 1));
75
+ setSelectedIndex((i) => (i > 0 ? i - 1 : options.length - 1));
47
76
  }
48
77
  else if (key.downArrow || key.rightArrow) {
49
- setSelectedIndex((i) => (i < OPTIONS.length - 1 ? i + 1 : 0));
78
+ setSelectedIndex((i) => (i < options.length - 1 ? i + 1 : 0));
50
79
  }
51
80
  else if (key.return) {
52
- onSubmit(OPTIONS[selectedIndex].action);
81
+ onSubmit(options[selectedIndex].action);
53
82
  }
54
83
  else {
55
- const shortcutMatch = OPTIONS.findIndex((o) => o.shortcut === input.toLowerCase());
84
+ const shortcutMatch = options.findIndex((o) => o.shortcut === input.toLowerCase());
56
85
  if (shortcutMatch >= 0) {
57
- onSubmit(OPTIONS[shortcutMatch].action);
86
+ onSubmit(options[shortcutMatch].action);
58
87
  }
59
88
  }
60
89
  });
@@ -62,6 +91,10 @@ export function ApprovalPrompt({ pendingApproval, onSubmit, isSubmitting = false
62
91
  const toolLabel = serverSlug
63
92
  ? `${serverSlug}/${pendingApproval.toolName}`
64
93
  : pendingApproval.toolName;
65
- return (_jsxs(Box, { flexDirection: "column", paddingLeft: 2, paddingTop: 1, paddingBottom: 1, borderStyle: "round", borderColor: "yellow", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: "\u26A0 Approval required" }), pendingApproval.fromSubAgent && (_jsxs(Text, { dimColor: true, children: ["via ", pendingApproval.subAgentSubject || pendingApproval.subAgentName] }))] }), _jsxs(Box, { paddingLeft: 2, marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "Tool:" }), _jsx(Text, { bold: true, children: toolLabel })] }), pendingApproval.argsPreview && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "Args:" }), _jsx(Text, { wrap: "truncate-end", children: pendingApproval.argsPreview })] }))] }), _jsx(Box, { gap: 2, marginTop: 1, paddingLeft: 2, children: OPTIONS.map((opt, idx) => (_jsxs(Text, { color: idx === selectedIndex ? opt.color : undefined, dimColor: idx !== selectedIndex, bold: idx === selectedIndex, children: [idx === selectedIndex ? "▸ " : " ", "[", opt.shortcut, "] ", opt.label] }, opt.shortcut))) }), isSubmitting && (_jsx(Box, { paddingLeft: 2, marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Submitting..." }) }))] }));
94
+ // Why-gated: the authorization provenance the server projected onto the
95
+ // PendingApproval. Mirrors the React card's gate-reason line so the terminal
96
+ // surface explains the gate at parity. Empty for legacy executions.
97
+ const gateReason = describeApprovalPolicySource(pendingApproval.approvalPolicySource);
98
+ return (_jsxs(Box, { flexDirection: "column", paddingLeft: 2, paddingTop: 1, paddingBottom: 1, borderStyle: "round", borderColor: "yellow", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: "\u26A0 Approval required" }), pendingApproval.fromSubAgent && (_jsxs(Text, { dimColor: true, children: ["via ", pendingApproval.subAgentSubject || pendingApproval.subAgentName] }))] }), _jsxs(Box, { paddingLeft: 2, marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "Tool:" }), _jsx(Text, { bold: true, children: toolLabel })] }), pendingApproval.argsPreview && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "Args:" }), _jsx(Text, { wrap: "truncate-end", children: pendingApproval.argsPreview })] })), gateReason && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "Why:" }), _jsx(Text, { dimColor: true, italic: true, children: gateReason })] }))] }), _jsx(Box, { gap: 2, marginTop: 1, paddingLeft: 2, children: options.map((opt, idx) => (_jsxs(Text, { color: idx === selectedIndex ? opt.color : undefined, dimColor: idx !== selectedIndex, bold: idx === selectedIndex, children: [idx === selectedIndex ? "▸ " : " ", "[", opt.shortcut, "] ", opt.label] }, opt.shortcut))) }), isSubmitting && (_jsx(Box, { paddingLeft: 2, marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Submitting..." }) }))] }));
66
99
  }
67
100
  //# sourceMappingURL=ApprovalPrompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApprovalPrompt.js","sourceRoot":"","sources":["../../src/components/ApprovalPrompt.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ApprovalPrompt.js","sourceRoot":"","sources":["../../src/components/ApprovalPrompt.tsx"],"names":[],"mappings":"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"}
@@ -54,11 +54,18 @@ function describeResultView(view) {
54
54
  return `${view.path}${stats}`;
55
55
  }
56
56
  case "terminal": {
57
+ // Lead with the command prompt line so the CLI reads as one terminal
58
+ // session, matching the web console.
59
+ const prompt = view.command ? `$ ${view.command}\n` : "";
57
60
  const exit = view.exitCode !== undefined && view.exitCode !== 0 ? `[exit ${view.exitCode}] ` : "";
58
- return exit + truncate(view.stdout || view.stderr);
61
+ return prompt + exit + truncate(view.stdout || view.stderr);
62
+ }
63
+ case "search": {
64
+ const noun = view.kind === "files"
65
+ ? view.count === 1 ? "file" : "files"
66
+ : view.count === 1 ? "match" : "matches";
67
+ return `${view.count} ${noun}${view.truncated ? " (truncated)" : ""}`;
59
68
  }
60
- case "search":
61
- return `${view.count} ${view.count === 1 ? "match" : "matches"}`;
62
69
  case "list":
63
70
  return `${view.count} ${view.count === 1 ? "item" : "items"}`;
64
71
  case "file":
@@ -70,11 +77,14 @@ function describeResultView(view) {
70
77
  case "json":
71
78
  return truncate(JSON.stringify(view.value));
72
79
  case "outputRef": {
80
+ // The full bytes were offloaded to artifact storage. A terminal formatter
81
+ // can't fetch them inline, so we surface the stable storage key rather
82
+ // than a baked URL (which expired after an hour and is no longer present).
73
83
  const size = view.sizeBytes ? ` (${formatBytes(view.sizeBytes)})` : "";
74
84
  if (view.isImage)
75
- return `image${size}: ${view.downloadUrl}`;
85
+ return `[image output${size}] ${view.storageKey}`;
76
86
  const preview = view.preview ? `${truncate(view.preview)}\n` : "";
77
- return `${preview}full output${size}: ${view.downloadUrl}`;
87
+ return `${preview}[full output offloaded${size}] ${view.storageKey}`;
78
88
  }
79
89
  case "error":
80
90
  return view.message;
@@ -1 +1 @@
1
- {"version":3,"file":"ToolCallItem.js","sourceRoot":"","sources":["../../src/components/ToolCallItem.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAW9E,MAAM,gBAAgB,GAAuD;IAC3E,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpE,CAAC,cAAc,CAAC,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE;IACrE,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE;CACjE,CAAC;AAEF,8EAA8E;AAC9E,wEAAwE;AACxE,qEAAqE;AACrE,MAAM,UAAU,GAAsC;IACpD,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM;IAC5B,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO;IAC9B,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM;IAC5B,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ;IAChC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IACzB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ;IAC3B,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM;IACvB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IACzB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,YAAY;IACnC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU;IAC5B,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO;IACxB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW;CACjC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,KAAK,EAAqB;IAC5E,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAEvE,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9D,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,MAAC,GAAG,IAAC,GAAG,EAAE,CAAC,aACT,KAAC,IAAI,IAAC,KAAK,EAAE,SAAS,CAAC,KAAK,YAAG,SAAS,CAAC,MAAM,GAAQ,EACvD,KAAC,IAAI,cAAE,KAAK,GAAQ,EACnB,QAAQ,CAAC,MAAM,KAAK,cAAc,CAAC,iBAAiB,IAAI,CACvD,KAAC,IAAI,IAAC,QAAQ,8BAAe,CAC9B,IACG,EACL,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CACvB,QAAQ,IAAI,CACV,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,YACjB,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,cAAc,YAClC,IAAI,CAAC,OAAO,GACR,GACH,CACP,CACF,CAAC,CAAC,CAAC,CACF,UAAU,IAAI,CACZ,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,YACjB,KAAC,IAAI,IAAC,QAAQ,QAAC,IAAI,EAAC,cAAc,YAC/B,UAAU,GACN,GACH,CACP,CACF,IACG,CACP,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,QAAkB,EAAE,IAAc;IACnD,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3B,OAAO,GAAG,QAAQ,CAAC,aAAa,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;IACtD,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC;AAC3C,CAAC;AAED,gFAAgF;AAChF,SAAS,kBAAkB,CAAC,IAAoB;IAC9C,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,KAAK,GACT,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;gBAC9D,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,IAAI,CAAC,YAAY,IAAI,CAAC,GAAG;gBAC1D,CAAC,CAAC,EAAE,CAAC;YACT,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,EAAE,CAAC;QAChC,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,IAAI,GACR,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACvF,OAAO,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC;QACrD,CAAC;QACD,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QACnE,KAAK,MAAM;YACT,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAChE,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;QAC3B,KAAK,eAAe;YAClB,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7E,KAAK,MAAM;YACT,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,KAAK,MAAM;YACT,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9C,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,IAAI,IAAI,CAAC,OAAO;gBAAE,OAAO,QAAQ,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAClE,OAAO,GAAG,OAAO,cAAc,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7D,CAAC;QACD,KAAK,OAAO;YACV,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,KAAK,OAAO;YACV,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,CAAS;IAC5B,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IACpE,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IACpD,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS,EAAE,QAAQ,GAAG,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,CAAC,CAAC;IACvC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,UAAU,KAAK,CAAC,MAAM,GAAG,QAAQ,cAAc,CAAC;AAC/F,CAAC"}
1
+ {"version":3,"file":"ToolCallItem.js","sourceRoot":"","sources":["../../src/components/ToolCallItem.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/ink",
3
- "version": "3.0.9-dev.20260615153829",
3
+ "version": "3.1.0",
4
4
  "description": "Ink (React for terminals) components for rendering Stigmer agent sessions in the terminal",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@connectrpc/connect-node": "^2.1.1",
38
- "@stigmer/react": "3.0.9-dev.20260615153829",
38
+ "@stigmer/react": "3.1.0",
39
39
  "ink-spinner": "^5.0.0",
40
40
  "ink-text-input": "^6.0.0",
41
41
  "marked": "^15.0.7",
@@ -43,8 +43,8 @@
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@bufbuild/protobuf": "^2.0.0",
46
- "@stigmer/protos": "3.0.9-dev.20260615153829",
47
- "@stigmer/sdk": "3.0.9-dev.20260615153829",
46
+ "@stigmer/protos": "3.1.0",
47
+ "@stigmer/sdk": "3.1.0",
48
48
  "ink": "^7.0.0",
49
49
  "react": ">=19.0.0"
50
50
  }
@@ -4,7 +4,7 @@ import { render } from "ink-testing-library";
4
4
  import { Text, Box } from "ink";
5
5
  import { create } from "@bufbuild/protobuf";
6
6
  import { AgentMessageSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
7
- import { MessageType, ExecutionPhase, ToolCallStatus, ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
7
+ import { MessageType, ExecutionPhase, ToolCallStatus, ApprovalAction, ApprovalPolicySource } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
8
8
  import { ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
9
9
  import { PendingApprovalSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
10
10
  import { MessageEntry } from "../components/MessageEntry.js";
@@ -164,7 +164,7 @@ describe("ToolCallItem", () => {
164
164
  });
165
165
 
166
166
  describe("ApprovalPrompt", () => {
167
- it("offers Approve, Approve & don't ask again, Reject, and Skip", () => {
167
+ it("offers Approve, scope-truthful approve-all, Reject, and Skip", () => {
168
168
  const pending = create(PendingApprovalSchema);
169
169
  pending.toolCallId = "tc-1";
170
170
  pending.toolName = "write_file";
@@ -174,11 +174,26 @@ describe("ApprovalPrompt", () => {
174
174
  );
175
175
  const output = lastFrame() ?? "";
176
176
  expect(output).toContain("[y] Approve");
177
- expect(output).toContain("[a] Approve & don't ask again");
177
+ // write_file leases the "file edits" class — the label names that class.
178
+ expect(output).toContain("[a] Approve all file edits");
178
179
  expect(output).toContain("[n] Reject");
179
180
  expect(output).toContain("[s] Skip");
180
181
  });
181
182
 
183
+ it("renders the why-gated line from the projected approval_policy_source", () => {
184
+ const pending = create(PendingApprovalSchema);
185
+ pending.toolCallId = "tc-1";
186
+ pending.toolName = "write_file";
187
+ pending.approvalPolicySource = ApprovalPolicySource.AGENT_OVERRIDE;
188
+
189
+ const { lastFrame } = render(
190
+ <ApprovalPrompt pendingApproval={pending} onSubmit={() => {}} />,
191
+ );
192
+ const output = lastFrame() ?? "";
193
+ expect(output).toContain("Why:");
194
+ expect(output).toContain("required by agent override");
195
+ });
196
+
182
197
  it("submits APPROVE_ALL when the 'a' shortcut is pressed", () => {
183
198
  const pending = create(PendingApprovalSchema);
184
199
  pending.toolCallId = "tc-1";
@@ -1,7 +1,12 @@
1
- import React, { useState } from "react";
1
+ import React, { useMemo, useState } from "react";
2
2
  import { Box, Text, useInput } from "ink";
3
3
  import type { PendingApproval } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
4
4
  import { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
+ import {
6
+ ToolKind,
7
+ resolveToolKindByName,
8
+ describeApprovalPolicySource,
9
+ } from "@stigmer/sdk";
5
10
 
6
11
  /** Props for {@link ApprovalPrompt}. */
7
12
  export interface ApprovalPromptProps {
@@ -20,32 +25,35 @@ interface ActionOption {
20
25
  readonly shortcut: string;
21
26
  }
22
27
 
23
- const OPTIONS: readonly ActionOption[] = [
24
- {
25
- label: "Approve",
26
- action: ApprovalAction.APPROVE,
27
- color: "green",
28
- shortcut: "y",
29
- },
30
- {
31
- label: "Approve & don't ask again",
32
- action: ApprovalAction.APPROVE_ALL,
33
- color: "green",
34
- shortcut: "a",
35
- },
36
- {
37
- label: "Reject",
38
- action: ApprovalAction.REJECT,
39
- color: "red",
40
- shortcut: "n",
41
- },
42
- {
43
- label: "Skip",
44
- action: ApprovalAction.SKIP,
45
- color: "yellow",
46
- shortcut: "s",
47
- },
48
- ];
28
+ /**
29
+ * Builds the truthful APPROVE_ALL option label for a pending approval's lease
30
+ * class — the terminal mirror of the React card's buildApproveAllLabel.
31
+ *
32
+ * APPROVE_ALL grants a run-lifetime lease scoped to ONE class: the MCP server
33
+ * for an MCP tool, otherwise the approval category (write/delete/shell), where
34
+ * FILE_WRITE and FILE_EDIT collapse to one "file edits" class exactly as the
35
+ * runner's toolApprovalCategory collapses them. The label names that class so it
36
+ * never implies a broader, run-wide bypass.
37
+ */
38
+ function buildApproveAllLabel(
39
+ toolName: string,
40
+ mcpServerSlug: string,
41
+ ): string {
42
+ if (mcpServerSlug) {
43
+ return `Approve all ${mcpServerSlug} tools`;
44
+ }
45
+ switch (resolveToolKindByName(toolName, mcpServerSlug)) {
46
+ case ToolKind.SHELL:
47
+ return "Approve all shell commands";
48
+ case ToolKind.FILE_DELETE:
49
+ return "Approve all file deletions";
50
+ case ToolKind.FILE_WRITE:
51
+ case ToolKind.FILE_EDIT:
52
+ return "Approve all file edits";
53
+ default:
54
+ return "Approve all of this kind";
55
+ }
56
+ }
49
57
 
50
58
  /**
51
59
  * HITL approval prompt for tool call authorization.
@@ -53,8 +61,10 @@ const OPTIONS: readonly ActionOption[] = [
53
61
  * Displays the tool name and args preview, then presents
54
62
  * Approve/Approve-all/Reject/Skip options navigable via arrow keys
55
63
  * or shortcut keys (y/a/n/s). Press Enter to confirm the highlighted
56
- * selection. "Approve & don't ask again" (a) maps to APPROVE_ALL, which
57
- * stops gating the rest of the run.
64
+ * selection. The approve-all option (a) maps to APPROVE_ALL, which grants a
65
+ * run-lifetime lease scoped to the clicked tool's CLASS (its MCP server, or its
66
+ * file edit / delete / shell category) — other classes keep prompting. The
67
+ * option label names that class so the scope is never a surprise.
58
68
  */
59
69
  export function ApprovalPrompt({
60
70
  pendingApproval,
@@ -63,22 +73,55 @@ export function ApprovalPrompt({
63
73
  }: ApprovalPromptProps) {
64
74
  const [selectedIndex, setSelectedIndex] = useState(0);
65
75
 
76
+ const options = useMemo<readonly ActionOption[]>(
77
+ () => [
78
+ {
79
+ label: "Approve",
80
+ action: ApprovalAction.APPROVE,
81
+ color: "green",
82
+ shortcut: "y",
83
+ },
84
+ {
85
+ label: buildApproveAllLabel(
86
+ pendingApproval.toolName,
87
+ pendingApproval.mcpServerSlug,
88
+ ),
89
+ action: ApprovalAction.APPROVE_ALL,
90
+ color: "green",
91
+ shortcut: "a",
92
+ },
93
+ {
94
+ label: "Reject",
95
+ action: ApprovalAction.REJECT,
96
+ color: "red",
97
+ shortcut: "n",
98
+ },
99
+ {
100
+ label: "Skip",
101
+ action: ApprovalAction.SKIP,
102
+ color: "yellow",
103
+ shortcut: "s",
104
+ },
105
+ ],
106
+ [pendingApproval.toolName, pendingApproval.mcpServerSlug],
107
+ );
108
+
66
109
  useInput(
67
110
  (input, key) => {
68
111
  if (isSubmitting) return;
69
112
 
70
113
  if (key.upArrow || key.leftArrow) {
71
- setSelectedIndex((i) => (i > 0 ? i - 1 : OPTIONS.length - 1));
114
+ setSelectedIndex((i) => (i > 0 ? i - 1 : options.length - 1));
72
115
  } else if (key.downArrow || key.rightArrow) {
73
- setSelectedIndex((i) => (i < OPTIONS.length - 1 ? i + 1 : 0));
116
+ setSelectedIndex((i) => (i < options.length - 1 ? i + 1 : 0));
74
117
  } else if (key.return) {
75
- onSubmit(OPTIONS[selectedIndex].action);
118
+ onSubmit(options[selectedIndex].action);
76
119
  } else {
77
- const shortcutMatch = OPTIONS.findIndex(
120
+ const shortcutMatch = options.findIndex(
78
121
  (o) => o.shortcut === input.toLowerCase(),
79
122
  );
80
123
  if (shortcutMatch >= 0) {
81
- onSubmit(OPTIONS[shortcutMatch].action);
124
+ onSubmit(options[shortcutMatch].action);
82
125
  }
83
126
  }
84
127
  },
@@ -89,6 +132,13 @@ export function ApprovalPrompt({
89
132
  ? `${serverSlug}/${pendingApproval.toolName}`
90
133
  : pendingApproval.toolName;
91
134
 
135
+ // Why-gated: the authorization provenance the server projected onto the
136
+ // PendingApproval. Mirrors the React card's gate-reason line so the terminal
137
+ // surface explains the gate at parity. Empty for legacy executions.
138
+ const gateReason = describeApprovalPolicySource(
139
+ pendingApproval.approvalPolicySource,
140
+ );
141
+
92
142
  return (
93
143
  <Box
94
144
  flexDirection="column"
@@ -120,10 +170,18 @@ export function ApprovalPrompt({
120
170
  <Text wrap="truncate-end">{pendingApproval.argsPreview}</Text>
121
171
  </Box>
122
172
  )}
173
+ {gateReason && (
174
+ <Box gap={1}>
175
+ <Text dimColor>Why:</Text>
176
+ <Text dimColor italic>
177
+ {gateReason}
178
+ </Text>
179
+ </Box>
180
+ )}
123
181
  </Box>
124
182
 
125
183
  <Box gap={2} marginTop={1} paddingLeft={2}>
126
- {OPTIONS.map((opt, idx) => (
184
+ {options.map((opt, idx) => (
127
185
  <Text
128
186
  key={opt.shortcut}
129
187
  color={idx === selectedIndex ? opt.color : undefined}
@@ -99,12 +99,20 @@ function describeResultView(view: ToolResultView): string | null {
99
99
  return `${view.path}${stats}`;
100
100
  }
101
101
  case "terminal": {
102
+ // Lead with the command prompt line so the CLI reads as one terminal
103
+ // session, matching the web console.
104
+ const prompt = view.command ? `$ ${view.command}\n` : "";
102
105
  const exit =
103
106
  view.exitCode !== undefined && view.exitCode !== 0 ? `[exit ${view.exitCode}] ` : "";
104
- return exit + truncate(view.stdout || view.stderr);
107
+ return prompt + exit + truncate(view.stdout || view.stderr);
108
+ }
109
+ case "search": {
110
+ const noun =
111
+ view.kind === "files"
112
+ ? view.count === 1 ? "file" : "files"
113
+ : view.count === 1 ? "match" : "matches";
114
+ return `${view.count} ${noun}${view.truncated ? " (truncated)" : ""}`;
105
115
  }
106
- case "search":
107
- return `${view.count} ${view.count === 1 ? "match" : "matches"}`;
108
116
  case "list":
109
117
  return `${view.count} ${view.count === 1 ? "item" : "items"}`;
110
118
  case "file":
@@ -116,10 +124,13 @@ function describeResultView(view: ToolResultView): string | null {
116
124
  case "json":
117
125
  return truncate(JSON.stringify(view.value));
118
126
  case "outputRef": {
127
+ // The full bytes were offloaded to artifact storage. A terminal formatter
128
+ // can't fetch them inline, so we surface the stable storage key rather
129
+ // than a baked URL (which expired after an hour and is no longer present).
119
130
  const size = view.sizeBytes ? ` (${formatBytes(view.sizeBytes)})` : "";
120
- if (view.isImage) return `image${size}: ${view.downloadUrl}`;
131
+ if (view.isImage) return `[image output${size}] ${view.storageKey}`;
121
132
  const preview = view.preview ? `${truncate(view.preview)}\n` : "";
122
- return `${preview}full output${size}: ${view.downloadUrl}`;
133
+ return `${preview}[full output offloaded${size}] ${view.storageKey}`;
123
134
  }
124
135
  case "error":
125
136
  return view.message;