@stigmer/ink 3.1.2 → 3.1.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"SessionView.d.ts","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"AAWA,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC;AAE/C,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CA8KrE"}
1
+ {"version":3,"file":"SessionView.d.ts","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"AAYA,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC;AAE/C,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAyLrE"}
@@ -8,6 +8,7 @@ import { TodoList } from "../components/TodoList.js";
8
8
  import { FollowUpInput } from "../components/FollowUpInput.js";
9
9
  import { UsageWidget } from "../components/UsageWidget.js";
10
10
  import { ExecutionProgress } from "../components/ExecutionProgress.js";
11
+ import { FileChangeProgressBar } from "../components/FileChangeProgressBar.js";
11
12
  import { FileReviewPrompt } from "../components/FileReviewPrompt.js";
12
13
  /**
13
14
  * Full-featured session conversation view for the terminal.
@@ -67,7 +68,7 @@ export function SessionView({ sessionId, org, mode }) {
67
68
  // for review (it lives on FileChangeSet.status), so the phase would
68
69
  // otherwise read as an active "Running" spinner while the agent is
69
70
  // idle awaiting the reviewer — the FileReviewPrompt is the honest cue.
70
- _jsx(ExecutionProgress, { phase: conv.activePhase })), _jsx(MessageThread, { executions: conv.completedExecutions, activeStreamExecution: conv.activeStreamExecution, pendingUserMessage: conv.pendingUserMessage, onApprovalSubmit: conv.submitApproval, submittingApprovalIds: conv.submittingApprovalIds, expandToolCalls: expandTools, showFileReviewRecords: true }), activeTodos && Object.keys(activeTodos).length > 0 && (_jsx(Box, { marginTop: 1, paddingLeft: 1, children: _jsx(TodoList, { todos: activeTodos }) })), conv.approvalError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["Approval error: ", conv.approvalError.message] }) })), conv.sendError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["Send error: ", conv.sendError.message] }) })), _jsx(UsageWidget, { executions: allExecutions }), conv.fileChangeSets.length > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsx(FileReviewPrompt, { changeSet: conv.fileChangeSets[0], onSubmit: conv.submitFileDecision, submittingDecisionKeys: conv.submittingFileDecisionKeys, decisionErrors: conv.fileDecisionErrors,
71
+ _jsx(ExecutionProgress, { phase: conv.activePhase })), _jsx(MessageThread, { executions: conv.completedExecutions, activeStreamExecution: conv.activeStreamExecution, pendingUserMessage: conv.pendingUserMessage, onApprovalSubmit: conv.submitApproval, submittingApprovalIds: conv.submittingApprovalIds, expandToolCalls: expandTools, showFileReviewRecords: true }), activeTodos && Object.keys(activeTodos).length > 0 && (_jsx(Box, { marginTop: 1, paddingLeft: 1, children: _jsx(TodoList, { todos: activeTodos }) })), conv.approvalError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["Approval error: ", conv.approvalError.message] }) })), conv.sendError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["Send error: ", conv.sendError.message] }) })), _jsx(UsageWidget, { executions: allExecutions }), _jsx(FileChangeProgressBar, { progress: conv.fileChangeProgress, expanded: expandTools }), conv.fileChangeSets.length > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsx(FileReviewPrompt, { changeSet: conv.fileChangeSets[0], onSubmit: conv.submitFileDecision, submittingDecisionKeys: conv.submittingFileDecisionKeys, decisionErrors: conv.fileDecisionErrors,
71
72
  // Single active decision surface: yield to a pending tool approval.
72
73
  isActive: conv.pendingApprovals.length === 0 }), conv.fileChangeSets.length > 1 && (_jsx(Box, { paddingLeft: 2, children: _jsxs(Text, { dimColor: true, children: [conv.fileChangeSets.length - 1, " more awaiting review"] }) }))] })), conv.fileReviewError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["File review error: ", conv.fileReviewError.message] }) })), conv.canSendFollowUp && (_jsx(Box, { paddingLeft: 1, children: _jsx(Text, { color: activeMode === "plan" ? "yellow" : "cyan", dimColor: true, children: activeMode === "plan"
73
74
  ? "Plan mode — read-only analysis, no file mutations"
@@ -1 +1 @@
1
- {"version":3,"file":"SessionView.js","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SessionView.js","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { FileChangeProgress } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
2
+ /** Props for {@link FileChangeProgressBar}. */
3
+ export interface FileChangeProgressBarProps {
4
+ /**
5
+ * The transient mid-run progress snapshot for the active turn (DD-32). Feed
6
+ * this from `useSessionConversation().fileChangeProgress`. Renders nothing when
7
+ * undefined or when no files have changed yet — the server clears it once the
8
+ * turn's change set leaves CAPTURING, so the strip disappears exactly when the
9
+ * decision surface (`FileReviewPrompt`) takes over.
10
+ */
11
+ readonly progress: FileChangeProgress | undefined;
12
+ /**
13
+ * Whether to reveal the per-file list. The compact one-line summary always
14
+ * shows; the list is progressive disclosure. `SessionView` binds this to its
15
+ * existing Ctrl+O "expand" toggle so no new keybinding is introduced. Defaults
16
+ * to `false`.
17
+ */
18
+ readonly expanded?: boolean;
19
+ }
20
+ /**
21
+ * The terminal analogue of the web's non-interactive "N files changing…" strip
22
+ * (`@stigmer/react` `FileChangeProgressBar`), for a turn that is still running.
23
+ *
24
+ * WHY IT EXISTS. The transcript streams per-edit tool rows, but a change made by
25
+ * a shell command (a `sed`, a build step) has no tool row, and there is no
26
+ * running net-of-many-edits rollup until the turn ends. This strip fills that
27
+ * gap: a compact, non-interactive count of the workspace delta accumulating
28
+ * during the turn, sitting where the `FileReviewPrompt` will later appear. The
29
+ * two are mutually exclusive per turn (progress shows while CAPTURING; the prompt
30
+ * once AWAITING_REVIEW), so the strip hands off cleanly to the prompt.
31
+ *
32
+ * NEVER A DECISION SURFACE. Progress is non-authoritative and carries no file
33
+ * bodies — it is never reviewable or decidable, and it owns no keyboard input.
34
+ * The reviewed diff is the turn-boundary candidate (`FileReviewPrompt`). A
35
+ * secret-like path is surfaced by name with its counts withheld (zeroed), so the
36
+ * `+N −M` stat renders nothing for it. The quiet/dim register (no border)
37
+ * distinguishes it from the loud, bordered decision prompt.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * const conv = useSessionConversation(sessionId, org);
42
+ * <FileChangeProgressBar progress={conv.fileChangeProgress} expanded={expandTools} />
43
+ * ```
44
+ */
45
+ export declare function FileChangeProgressBar({ progress, expanded, }: FileChangeProgressBarProps): import("react/jsx-runtime").JSX.Element | null;
46
+ //# sourceMappingURL=FileChangeProgressBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileChangeProgressBar.d.ts","sourceRoot":"","sources":["../../src/components/FileChangeProgressBar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oEAAoE,CAAC;AAG7G,+CAA+C;AAC/C,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAClD;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,QAAgB,GACjB,EAAE,0BAA0B,kDA0C5B"}
@@ -0,0 +1,55 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { kindLetter, progressEntryDisplayPath } from "../file-review.js";
4
+ /**
5
+ * The terminal analogue of the web's non-interactive "N files changing…" strip
6
+ * (`@stigmer/react` `FileChangeProgressBar`), for a turn that is still running.
7
+ *
8
+ * WHY IT EXISTS. The transcript streams per-edit tool rows, but a change made by
9
+ * a shell command (a `sed`, a build step) has no tool row, and there is no
10
+ * running net-of-many-edits rollup until the turn ends. This strip fills that
11
+ * gap: a compact, non-interactive count of the workspace delta accumulating
12
+ * during the turn, sitting where the `FileReviewPrompt` will later appear. The
13
+ * two are mutually exclusive per turn (progress shows while CAPTURING; the prompt
14
+ * once AWAITING_REVIEW), so the strip hands off cleanly to the prompt.
15
+ *
16
+ * NEVER A DECISION SURFACE. Progress is non-authoritative and carries no file
17
+ * bodies — it is never reviewable or decidable, and it owns no keyboard input.
18
+ * The reviewed diff is the turn-boundary candidate (`FileReviewPrompt`). A
19
+ * secret-like path is surfaced by name with its counts withheld (zeroed), so the
20
+ * `+N −M` stat renders nothing for it. The quiet/dim register (no border)
21
+ * distinguishes it from the loud, bordered decision prompt.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * const conv = useSessionConversation(sessionId, org);
26
+ * <FileChangeProgressBar progress={conv.fileChangeProgress} expanded={expandTools} />
27
+ * ```
28
+ */
29
+ export function FileChangeProgressBar({ progress, expanded = false, }) {
30
+ if (!progress || progress.filesChanged === 0)
31
+ return null;
32
+ const { filesChanged, linesAdded, linesRemoved, entries } = progress;
33
+ const hiddenCount = filesChanged - entries.length;
34
+ return (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "\u270E" }), _jsxs(Text, { dimColor: true, children: [filesChanged, " file", filesChanged === 1 ? "" : "s", " changing\u2026"] }), _jsx(LineStats, { linesAdded: linesAdded, linesRemoved: linesRemoved })] }), expanded && (_jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [entries.map((entry, idx) => {
35
+ const path = progressEntryDisplayPath(entry);
36
+ return (_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: kindLetter(entry.kind) }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: path }), _jsx(LineStats, { linesAdded: entry.linesAdded, linesRemoved: entry.linesRemoved })] }, `${path}-${idx}`));
37
+ }), hiddenCount > 0 && (_jsx(Box, { children: _jsxs(Text, { dimColor: true, children: ["\u2026 and ", hiddenCount, " more"] }) }))] }))] }));
38
+ }
39
+ /**
40
+ * The `+N −M` stat for one file (or the whole turn), in the diff colour
41
+ * vocabulary. Renders nothing when both counts are zero — the honest signal that
42
+ * no count exists (binary or secret-withheld changes) — rather than a misleading
43
+ * `+0 -0`, matching the web `FileLineStats` contract.
44
+ *
45
+ * Kept module-local: this is the only consumer today. When `FileReviewPrompt`
46
+ * and `FileReviewRecord` gain `+N −M` (the deferred "CLI +N −M parity"
47
+ * follow-up), lift this into a shared ink atom (the analogue of `sdk/react`'s
48
+ * `FileReviewAtoms`) so the three surfaces cannot drift — do not copy it.
49
+ */
50
+ function LineStats({ linesAdded, linesRemoved, }) {
51
+ if (linesAdded === 0 && linesRemoved === 0)
52
+ return null;
53
+ return (_jsxs(Text, { children: [_jsxs(Text, { color: "green", children: ["+", linesAdded] }), _jsxs(Text, { color: "red", children: [" -", linesRemoved] })] }));
54
+ }
55
+ //# sourceMappingURL=FileChangeProgressBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileChangeProgressBar.js","sourceRoot":"","sources":["../../src/components/FileChangeProgressBar.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAqBzE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,QAAQ,EACR,QAAQ,GAAG,KAAK,GACW;IAC3B,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,YAAY,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1D,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IACrE,MAAM,WAAW,GAAG,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAElD,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAE,CAAC,aACxC,MAAC,GAAG,IAAC,GAAG,EAAE,CAAC,aACT,KAAC,IAAI,IAAC,QAAQ,6BAAS,EACvB,MAAC,IAAI,IAAC,QAAQ,mBACX,YAAY,WAAO,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,uBAC5C,EACP,KAAC,SAAS,IAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,GAAI,IAC7D,EAEL,QAAQ,IAAI,CACX,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAE,CAAC,aACvC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;wBAC1B,MAAM,IAAI,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;wBAC7C,OAAO,CACL,MAAC,GAAG,IAAwB,GAAG,EAAE,CAAC,aAChC,KAAC,IAAI,IAAC,QAAQ,kBAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAQ,EAC9C,KAAC,IAAI,IAAC,QAAQ,QAAC,IAAI,EAAC,cAAc,YAC/B,IAAI,GACA,EACP,KAAC,SAAS,IACR,UAAU,EAAE,KAAK,CAAC,UAAU,EAC5B,YAAY,EAAE,KAAK,CAAC,YAAY,GAChC,KARM,GAAG,IAAI,IAAI,GAAG,EAAE,CASpB,CACP,CAAC;oBACJ,CAAC,CAAC,EACD,WAAW,GAAG,CAAC,IAAI,CAClB,KAAC,GAAG,cACF,MAAC,IAAI,IAAC,QAAQ,kCAAQ,WAAW,aAAa,GAC1C,CACP,IACG,CACP,IACG,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,SAAS,CAAC,EACjB,UAAU,EACV,YAAY,GAIb;IACC,IAAI,UAAU,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,OAAO,CACL,MAAC,IAAI,eACH,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,kBAAG,UAAU,IAAQ,EACxC,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,mBAAI,YAAY,IAAQ,IACpC,CACR,CAAC;AACJ,CAAC"}
package/file-review.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { CapturedFileChange, FileChangeSet } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
1
+ import type { CapturedFileChange, FileChangeProgressEntry, FileChangeSet } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
2
2
  import { FileChangeKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
3
3
  /**
4
4
  * Single-letter badge for a file change's kind, matching the web review card:
@@ -8,10 +8,17 @@ import { FileChangeKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecutio
8
8
  */
9
9
  export declare function kindLetter(kind: FileChangeKind): string;
10
10
  /**
11
- * The path to show for a change: the post-edit path, or the pre-edit path for a
12
- * deletion. A rename shows `before → after` so both sides are visible.
11
+ * The path to show for a reviewable change: the post-edit path, or the pre-edit
12
+ * path for a deletion. A rename shows `before → after` so both sides are visible.
13
13
  */
14
14
  export declare function changeDisplayPath(change: CapturedFileChange): string;
15
+ /**
16
+ * The path to show for a mid-run progress entry (DD-32), using the same
17
+ * rename-aware rule as {@link changeDisplayPath}. The slim entry carries no
18
+ * bodies or digests, only the same before/after/kind triple, so the terminal
19
+ * renders its path identically to the reviewable surfaces.
20
+ */
21
+ export declare function progressEntryDisplayPath(entry: FileChangeProgressEntry): string;
15
22
  /**
16
23
  * The honest, one-line reason a change cannot be kept as-is, or `null` when it
17
24
  * is fully reviewable. Mirrors the web card's per-file block-reason copy so the
@@ -1 +1 @@
1
- {"version":3,"file":"file-review.d.ts","sourceRoot":"","sources":["../src/file-review.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACd,MAAM,oEAAoE,CAAC;AAC5E,OAAO,EACL,cAAc,EAEf,MAAM,8DAA8D,CAAC;AAGtE;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAWvD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAKpE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAiBzE;AAED,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,CAc/D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CASzD"}
1
+ {"version":3,"file":"file-review.d.ts","sourceRoot":"","sources":["../src/file-review.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACd,MAAM,oEAAoE,CAAC;AAC5E,OAAO,EACL,cAAc,EAEf,MAAM,8DAA8D,CAAC;AAGtE;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAWvD;AAoBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAE/E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAiBzE;AAED,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,CAc/D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CASzD"}
package/file-review.js CHANGED
@@ -19,14 +19,33 @@ export function kindLetter(kind) {
19
19
  }
20
20
  }
21
21
  /**
22
- * The path to show for a change: the post-edit path, or the pre-edit path for a
23
- * deletion. A rename shows `before → after` so both sides are visible.
22
+ * The one rename-aware path-display rule for the terminal, over the raw
23
+ * before/after/kind triple shared by every file-change shape (reviewable
24
+ * `CapturedFileChange` and slim `FileChangeProgressEntry` alike). Kept private
25
+ * and fed by the typed adapters below so the two surfaces can never grow
26
+ * divergent rename formatting.
24
27
  */
25
- export function changeDisplayPath(change) {
26
- if (change.kind === FileChangeKind.RENAME && change.pathBefore && change.pathAfter) {
27
- return `${change.pathBefore} → ${change.pathAfter}`;
28
+ function displayChangePath(pathBefore, pathAfter, kind) {
29
+ if (kind === FileChangeKind.RENAME && pathBefore && pathAfter) {
30
+ return `${pathBefore} → ${pathAfter}`;
28
31
  }
29
- return change.pathAfter || change.pathBefore;
32
+ return pathAfter || pathBefore;
33
+ }
34
+ /**
35
+ * The path to show for a reviewable change: the post-edit path, or the pre-edit
36
+ * path for a deletion. A rename shows `before → after` so both sides are visible.
37
+ */
38
+ export function changeDisplayPath(change) {
39
+ return displayChangePath(change.pathBefore, change.pathAfter, change.kind);
40
+ }
41
+ /**
42
+ * The path to show for a mid-run progress entry (DD-32), using the same
43
+ * rename-aware rule as {@link changeDisplayPath}. The slim entry carries no
44
+ * bodies or digests, only the same before/after/kind triple, so the terminal
45
+ * renders its path identically to the reviewable surfaces.
46
+ */
47
+ export function progressEntryDisplayPath(entry) {
48
+ return displayChangePath(entry.pathBefore, entry.pathAfter, entry.kind);
30
49
  }
31
50
  /**
32
51
  * The honest, one-line reason a change cannot be kept as-is, or `null` when it
@@ -1 +1 @@
1
- {"version":3,"file":"file-review.js","sourceRoot":"","sources":["../src/file-review.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-review.js","sourceRoot":"","sources":["../src/file-review.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,cAAc,EACd,kBAAkB,GACnB,MAAM,8DAA8D,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE5E;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAoB;IAC7C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,cAAc,CAAC,GAAG;YACrB,OAAO,GAAG,CAAC;QACb,KAAK,cAAc,CAAC,MAAM;YACxB,OAAO,GAAG,CAAC;QACb,KAAK,cAAc,CAAC,MAAM;YACxB,OAAO,GAAG,CAAC;QACb;YACE,OAAO,GAAG,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CACxB,UAAkB,EAClB,SAAiB,EACjB,IAAoB;IAEpB,IAAI,IAAI,KAAK,cAAc,CAAC,MAAM,IAAI,UAAU,IAAI,SAAS,EAAE,CAAC;QAC9D,OAAO,GAAG,UAAU,MAAM,SAAS,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,SAAS,IAAI,UAAU,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,OAAO,iBAAiB,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAA8B;IACrE,OAAO,iBAAiB,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAA0B;IACxD,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAChD,QAAQ,aAAa,CAAC,IAAI,EAAE,CAAC;QAC3B,KAAK,YAAY;YACf,OAAO,IAAI,CAAC;QACd,KAAK,QAAQ;YACX,OAAO,8CAA8C,CAAC;QACxD,KAAK,aAAa;YAChB,QAAQ,aAAa,CAAC,MAAM,EAAE,CAAC;gBAC7B,KAAK,QAAQ;oBACX,OAAO,wDAAwD,CAAC;gBAClE,KAAK,MAAM;oBACT,OAAO,0CAA0C,CAAC;gBACpD;oBACE,OAAO,iCAAiC,CAAC;YAC7C,CAAC;IACL,CAAC;AACH,CAAC;AAYD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,GAAkB;IAC9C,MAAM,QAAQ,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC9C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,kBAAkB,CAAC,OAAO;YAAE,IAAI,EAAE,CAAC;aAC9C,IAAI,OAAO,KAAK,kBAAkB,CAAC,MAAM;YAAE,SAAS,EAAE,CAAC;IAC9D,CAAC;IACD,OAAO;QACL,IAAI;QACJ,SAAS;QACT,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS;KACnD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAkB;IAC/C,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,CAAC;IACrC,IAAI,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,YAAY,CAAC,CAAC;IACpD,IAAI,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,eAAe,CAAC,CAAC;IAC3D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;AAClD,CAAC"}
package/index.d.ts CHANGED
@@ -10,7 +10,8 @@ export { TodoList, type TodoListProps } from "./components/TodoList.js";
10
10
  export { ApprovalPrompt, type ApprovalPromptProps } from "./components/ApprovalPrompt.js";
11
11
  export { FileReviewPrompt, type FileReviewPromptProps } from "./components/FileReviewPrompt.js";
12
12
  export { FileReviewRecord, type FileReviewRecordProps } from "./components/FileReviewRecord.js";
13
- export { kindLetter, changeDisplayPath, blockReasonNote, settledCounts, settledSummary, type SettledCounts, } from "./file-review.js";
13
+ export { FileChangeProgressBar, type FileChangeProgressBarProps, } from "./components/FileChangeProgressBar.js";
14
+ export { kindLetter, changeDisplayPath, progressEntryDisplayPath, blockReasonNote, settledCounts, settledSummary, type SettledCounts, } from "./file-review.js";
14
15
  export { ExecutionProgress, type ExecutionProgressProps } from "./components/ExecutionProgress.js";
15
16
  export { FollowUpInput, type FollowUpInputProps } from "./components/FollowUpInput.js";
16
17
  export { UsageWidget, type UsageWidgetProps } from "./components/UsageWidget.js";
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGjF,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAGhG,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,cAAc,EACd,KAAK,aAAa,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGpF,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGvF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGjF,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAChG,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,uCAAuC,CAAC;AAG/C,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,aAAa,EACb,cAAc,EACd,KAAK,aAAa,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGpF,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGvF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
package/index.js CHANGED
@@ -14,8 +14,9 @@ export { TodoList } from "./components/TodoList.js";
14
14
  export { ApprovalPrompt } from "./components/ApprovalPrompt.js";
15
15
  export { FileReviewPrompt } from "./components/FileReviewPrompt.js";
16
16
  export { FileReviewRecord } from "./components/FileReviewRecord.js";
17
+ export { FileChangeProgressBar, } from "./components/FileChangeProgressBar.js";
17
18
  // File-review pure helpers (kind letters, paths, block reasons, settled counts)
18
- export { kindLetter, changeDisplayPath, blockReasonNote, settledCounts, settledSummary, } from "./file-review.js";
19
+ export { kindLetter, changeDisplayPath, progressEntryDisplayPath, blockReasonNote, settledCounts, settledSummary, } from "./file-review.js";
19
20
  export { ExecutionProgress } from "./components/ExecutionProgress.js";
20
21
  export { FollowUpInput } from "./components/FollowUpInput.js";
21
22
  export { UsageWidget } from "./components/UsageWidget.js";
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,kBAAkB,EAAgC,MAAM,eAAe,CAAC;AAEjF,iDAAiD;AACjD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAEpB,MAAM,mBAAmB,CAAC;AAE3B,WAAW;AACX,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,aAAa;AACb,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAA4B,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAA8B,MAAM,kCAAkC,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAA8B,MAAM,kCAAkC,CAAC;AAEhG,gFAAgF;AAChF,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,cAAc,GAEf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AAEpF,0CAA0C;AAC1C,OAAO,EAAE,cAAc,EAA6C,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AAEvF,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAA+C,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAwB,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,kBAAkB,EAAgC,MAAM,eAAe,CAAC;AAEjF,iDAAiD;AACjD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAEpB,MAAM,mBAAmB,CAAC;AAE3B,WAAW;AACX,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,aAAa;AACb,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAA4B,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAA8B,MAAM,kCAAkC,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAA8B,MAAM,kCAAkC,CAAC;AAChG,OAAO,EACL,qBAAqB,GAEtB,MAAM,uCAAuC,CAAC;AAE/C,gFAAgF;AAChF,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,aAAa,EACb,cAAc,GAEf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AAEpF,0CAA0C;AAC1C,OAAO,EAAE,cAAc,EAA6C,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AAEvF,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAA+C,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAwB,MAAM,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/ink",
3
- "version": "3.1.2",
3
+ "version": "3.1.3",
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.1.2",
38
+ "@stigmer/react": "3.1.3",
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.1.2",
47
- "@stigmer/sdk": "3.1.2",
46
+ "@stigmer/protos": "3.1.3",
47
+ "@stigmer/sdk": "3.1.3",
48
48
  "ink": "^7.0.0",
49
49
  "react": ">=19.0.0"
50
50
  }
@@ -0,0 +1,295 @@
1
+ import React from "react";
2
+ import { describe, it, expect } from "vitest";
3
+ import { render } from "ink-testing-library";
4
+ import { create } from "@bufbuild/protobuf";
5
+ import {
6
+ FileChangeProgressSchema,
7
+ FileChangeProgressEntrySchema,
8
+ CapturedFileChangeSchema,
9
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
10
+ import type {
11
+ FileChangeProgress,
12
+ FileChangeProgressEntry,
13
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
14
+ import { FileChangeKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
15
+ import { FileChangeProgressBar } from "../components/FileChangeProgressBar.js";
16
+ import { changeDisplayPath, progressEntryDisplayPath } from "../file-review.js";
17
+
18
+ // --- fixtures -------------------------------------------------------------
19
+
20
+ interface EntryOpts {
21
+ readonly pathBefore?: string;
22
+ readonly pathAfter?: string;
23
+ readonly kind?: FileChangeKind;
24
+ readonly linesAdded?: number;
25
+ readonly linesRemoved?: number;
26
+ }
27
+
28
+ function makeEntry(opts: EntryOpts): FileChangeProgressEntry {
29
+ return create(FileChangeProgressEntrySchema, {
30
+ pathBefore: opts.pathBefore ?? "",
31
+ pathAfter: opts.pathAfter ?? "",
32
+ kind: opts.kind ?? FileChangeKind.MODIFY,
33
+ linesAdded: opts.linesAdded ?? 0,
34
+ linesRemoved: opts.linesRemoved ?? 0,
35
+ });
36
+ }
37
+
38
+ interface ProgressOpts {
39
+ readonly filesChanged?: number;
40
+ readonly linesAdded?: number;
41
+ readonly linesRemoved?: number;
42
+ readonly entries?: FileChangeProgressEntry[];
43
+ }
44
+
45
+ function makeProgress(opts: ProgressOpts): FileChangeProgress {
46
+ const entries = opts.entries ?? [];
47
+ return create(FileChangeProgressSchema, {
48
+ changeSetId: "cs-1",
49
+ filesChanged: opts.filesChanged ?? entries.length,
50
+ linesAdded: opts.linesAdded ?? 0,
51
+ linesRemoved: opts.linesRemoved ?? 0,
52
+ entries,
53
+ capturedAt: "2026-07-05T00:00:00Z",
54
+ });
55
+ }
56
+
57
+ // --- FileChangeProgressBar: visibility ------------------------------------
58
+
59
+ describe("FileChangeProgressBar — visibility", () => {
60
+ it("renders nothing when progress is undefined", () => {
61
+ const { lastFrame } = render(<FileChangeProgressBar progress={undefined} />);
62
+ expect((lastFrame() ?? "").trim()).toBe("");
63
+ });
64
+
65
+ it("renders nothing when no files have changed yet", () => {
66
+ const { lastFrame } = render(
67
+ <FileChangeProgressBar progress={makeProgress({ filesChanged: 0 })} />,
68
+ );
69
+ expect((lastFrame() ?? "").trim()).toBe("");
70
+ });
71
+ });
72
+
73
+ // --- FileChangeProgressBar: compact summary -------------------------------
74
+
75
+ describe("FileChangeProgressBar — compact summary", () => {
76
+ it("uses the singular noun for a single file", () => {
77
+ const { lastFrame } = render(
78
+ <FileChangeProgressBar
79
+ progress={makeProgress({
80
+ filesChanged: 1,
81
+ entries: [makeEntry({ pathAfter: "one.ts" })],
82
+ })}
83
+ />,
84
+ );
85
+ expect(lastFrame() ?? "").toContain("1 file changing");
86
+ });
87
+
88
+ it("uses the plural noun for multiple files", () => {
89
+ const { lastFrame } = render(
90
+ <FileChangeProgressBar
91
+ progress={makeProgress({
92
+ filesChanged: 3,
93
+ entries: [makeEntry({ pathAfter: "one.ts" })],
94
+ })}
95
+ />,
96
+ );
97
+ expect(lastFrame() ?? "").toContain("3 files changing");
98
+ });
99
+
100
+ it("shows the aggregate +N -M when counts exist", () => {
101
+ const { lastFrame } = render(
102
+ <FileChangeProgressBar
103
+ progress={makeProgress({
104
+ filesChanged: 2,
105
+ linesAdded: 12,
106
+ linesRemoved: 4,
107
+ entries: [makeEntry({ pathAfter: "one.ts" })],
108
+ })}
109
+ />,
110
+ );
111
+ const out = lastFrame() ?? "";
112
+ expect(out).toContain("+12");
113
+ expect(out).toContain("-4");
114
+ });
115
+
116
+ it("hides the aggregate stat when both counts are zero (never +0 -0)", () => {
117
+ const { lastFrame } = render(
118
+ <FileChangeProgressBar
119
+ progress={makeProgress({
120
+ filesChanged: 1,
121
+ linesAdded: 0,
122
+ linesRemoved: 0,
123
+ entries: [makeEntry({ pathAfter: "one.ts" })],
124
+ })}
125
+ />,
126
+ );
127
+ // No "+" anywhere means no stat rendered; the count copy carries none.
128
+ expect(lastFrame() ?? "").not.toContain("+");
129
+ });
130
+ });
131
+
132
+ // --- FileChangeProgressBar: expansion -------------------------------------
133
+
134
+ describe("FileChangeProgressBar — expansion", () => {
135
+ const progress = makeProgress({
136
+ filesChanged: 2,
137
+ linesAdded: 8,
138
+ linesRemoved: 1,
139
+ entries: [
140
+ makeEntry({ pathAfter: "src/app.ts", linesAdded: 5, linesRemoved: 1 }),
141
+ makeEntry({ pathAfter: "src/util.ts", linesAdded: 3, linesRemoved: 0 }),
142
+ ],
143
+ });
144
+
145
+ it("hides the per-file list when collapsed (default)", () => {
146
+ const { lastFrame } = render(<FileChangeProgressBar progress={progress} />);
147
+ const out = lastFrame() ?? "";
148
+ expect(out).toContain("2 files changing");
149
+ expect(out).not.toContain("src/app.ts");
150
+ expect(out).not.toContain("src/util.ts");
151
+ });
152
+
153
+ it("shows the per-file list with kind letter, path, and stats when expanded", () => {
154
+ const { lastFrame } = render(
155
+ <FileChangeProgressBar progress={progress} expanded />,
156
+ );
157
+ const out = lastFrame() ?? "";
158
+ expect(out).toContain("src/app.ts");
159
+ expect(out).toContain("src/util.ts");
160
+ expect(out).toContain("M"); // MODIFY kind letter
161
+ expect(out).toContain("+5");
162
+ expect(out).toContain("+3");
163
+ });
164
+
165
+ it("shows '… and K more' when the entry list is capped below the true total", () => {
166
+ const capped = makeProgress({
167
+ filesChanged: 5,
168
+ entries: [
169
+ makeEntry({ pathAfter: "a.ts" }),
170
+ makeEntry({ pathAfter: "b.ts" }),
171
+ ],
172
+ });
173
+ const { lastFrame } = render(
174
+ <FileChangeProgressBar progress={capped} expanded />,
175
+ );
176
+ expect(lastFrame() ?? "").toContain("and 3 more");
177
+ });
178
+
179
+ it("renders a rename entry as 'before → after'", () => {
180
+ const renamed = makeProgress({
181
+ filesChanged: 1,
182
+ entries: [
183
+ makeEntry({
184
+ pathBefore: "old/name.ts",
185
+ pathAfter: "new/name.ts",
186
+ kind: FileChangeKind.RENAME,
187
+ }),
188
+ ],
189
+ });
190
+ const { lastFrame } = render(
191
+ <FileChangeProgressBar progress={renamed} expanded />,
192
+ );
193
+ expect(lastFrame() ?? "").toContain("old/name.ts → new/name.ts");
194
+ });
195
+
196
+ it("hides per-file stats for a withheld entry (zero counts)", () => {
197
+ const secretish = makeProgress({
198
+ filesChanged: 1,
199
+ entries: [makeEntry({ pathAfter: ".env", linesAdded: 0, linesRemoved: 0 })],
200
+ });
201
+ const { lastFrame } = render(
202
+ <FileChangeProgressBar progress={secretish} expanded />,
203
+ );
204
+ const out = lastFrame() ?? "";
205
+ expect(out).toContain(".env");
206
+ expect(out).not.toContain("+");
207
+ });
208
+ });
209
+
210
+ // --- path helpers (direct unit coverage) ----------------------------------
211
+
212
+ interface ChangeOpts {
213
+ readonly pathBefore?: string;
214
+ readonly pathAfter?: string;
215
+ readonly kind: FileChangeKind;
216
+ }
217
+
218
+ function makeChange(opts: ChangeOpts) {
219
+ return create(CapturedFileChangeSchema, {
220
+ id: "c-1",
221
+ pathBefore: opts.pathBefore ?? "",
222
+ pathAfter: opts.pathAfter ?? "",
223
+ kind: opts.kind,
224
+ });
225
+ }
226
+
227
+ describe("changeDisplayPath", () => {
228
+ it("shows the after-path for an add", () => {
229
+ expect(
230
+ changeDisplayPath(makeChange({ pathAfter: "new.ts", kind: FileChangeKind.ADD })),
231
+ ).toBe("new.ts");
232
+ });
233
+
234
+ it("shows the after-path for a modify", () => {
235
+ expect(
236
+ changeDisplayPath(
237
+ makeChange({ pathAfter: "app.ts", kind: FileChangeKind.MODIFY }),
238
+ ),
239
+ ).toBe("app.ts");
240
+ });
241
+
242
+ it("falls back to the before-path for a delete", () => {
243
+ expect(
244
+ changeDisplayPath(
245
+ makeChange({ pathBefore: "gone.ts", kind: FileChangeKind.DELETE }),
246
+ ),
247
+ ).toBe("gone.ts");
248
+ });
249
+
250
+ it("shows 'before → after' for a rename", () => {
251
+ expect(
252
+ changeDisplayPath(
253
+ makeChange({
254
+ pathBefore: "old.ts",
255
+ pathAfter: "new.ts",
256
+ kind: FileChangeKind.RENAME,
257
+ }),
258
+ ),
259
+ ).toBe("old.ts → new.ts");
260
+ });
261
+ });
262
+
263
+ describe("progressEntryDisplayPath", () => {
264
+ it("shows the after-path for an add", () => {
265
+ expect(
266
+ progressEntryDisplayPath(makeEntry({ pathAfter: "new.ts", kind: FileChangeKind.ADD })),
267
+ ).toBe("new.ts");
268
+ });
269
+
270
+ it("shows the after-path for a modify", () => {
271
+ expect(
272
+ progressEntryDisplayPath(makeEntry({ pathAfter: "app.ts" })),
273
+ ).toBe("app.ts");
274
+ });
275
+
276
+ it("falls back to the before-path for a delete", () => {
277
+ expect(
278
+ progressEntryDisplayPath(
279
+ makeEntry({ pathBefore: "gone.ts", kind: FileChangeKind.DELETE }),
280
+ ),
281
+ ).toBe("gone.ts");
282
+ });
283
+
284
+ it("shows 'before → after' for a rename — identical to changeDisplayPath", () => {
285
+ expect(
286
+ progressEntryDisplayPath(
287
+ makeEntry({
288
+ pathBefore: "old.ts",
289
+ pathAfter: "new.ts",
290
+ kind: FileChangeKind.RENAME,
291
+ }),
292
+ ),
293
+ ).toBe("old.ts → new.ts");
294
+ });
295
+ });
@@ -7,6 +7,7 @@ import { TodoList } from "../components/TodoList.js";
7
7
  import { FollowUpInput } from "../components/FollowUpInput.js";
8
8
  import { UsageWidget } from "../components/UsageWidget.js";
9
9
  import { ExecutionProgress } from "../components/ExecutionProgress.js";
10
+ import { FileChangeProgressBar } from "../components/FileChangeProgressBar.js";
10
11
  import { FileReviewPrompt } from "../components/FileReviewPrompt.js";
11
12
 
12
13
  /** Interaction mode type used for follow-up executions. */
@@ -180,6 +181,17 @@ export function SessionView({ sessionId, org, mode }: SessionViewProps) {
180
181
 
181
182
  <UsageWidget executions={allExecutions} />
182
183
 
184
+ {/* Mid-run live capture (DD-32): the transient "N files changing…" strip
185
+ for a still-running turn, covering shell-made changes with no tool row.
186
+ Mutually exclusive with the FileReviewPrompt below — progress shows
187
+ while CAPTURING, the prompt once AWAITING_REVIEW — so it hands off
188
+ cleanly when review opens. Non-interactive; the per-file list reuses the
189
+ existing Ctrl+O expand toggle. */}
190
+ <FileChangeProgressBar
191
+ progress={conv.fileChangeProgress}
192
+ expanded={expandTools}
193
+ />
194
+
183
195
  {conv.fileChangeSets.length > 0 && (
184
196
  <Box flexDirection="column">
185
197
  <FileReviewPrompt
@@ -0,0 +1,122 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import type { FileChangeProgress } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
4
+ import { kindLetter, progressEntryDisplayPath } from "../file-review.js";
5
+
6
+ /** Props for {@link FileChangeProgressBar}. */
7
+ export interface FileChangeProgressBarProps {
8
+ /**
9
+ * The transient mid-run progress snapshot for the active turn (DD-32). Feed
10
+ * this from `useSessionConversation().fileChangeProgress`. Renders nothing when
11
+ * undefined or when no files have changed yet — the server clears it once the
12
+ * turn's change set leaves CAPTURING, so the strip disappears exactly when the
13
+ * decision surface (`FileReviewPrompt`) takes over.
14
+ */
15
+ readonly progress: FileChangeProgress | undefined;
16
+ /**
17
+ * Whether to reveal the per-file list. The compact one-line summary always
18
+ * shows; the list is progressive disclosure. `SessionView` binds this to its
19
+ * existing Ctrl+O "expand" toggle so no new keybinding is introduced. Defaults
20
+ * to `false`.
21
+ */
22
+ readonly expanded?: boolean;
23
+ }
24
+
25
+ /**
26
+ * The terminal analogue of the web's non-interactive "N files changing…" strip
27
+ * (`@stigmer/react` `FileChangeProgressBar`), for a turn that is still running.
28
+ *
29
+ * WHY IT EXISTS. The transcript streams per-edit tool rows, but a change made by
30
+ * a shell command (a `sed`, a build step) has no tool row, and there is no
31
+ * running net-of-many-edits rollup until the turn ends. This strip fills that
32
+ * gap: a compact, non-interactive count of the workspace delta accumulating
33
+ * during the turn, sitting where the `FileReviewPrompt` will later appear. The
34
+ * two are mutually exclusive per turn (progress shows while CAPTURING; the prompt
35
+ * once AWAITING_REVIEW), so the strip hands off cleanly to the prompt.
36
+ *
37
+ * NEVER A DECISION SURFACE. Progress is non-authoritative and carries no file
38
+ * bodies — it is never reviewable or decidable, and it owns no keyboard input.
39
+ * The reviewed diff is the turn-boundary candidate (`FileReviewPrompt`). A
40
+ * secret-like path is surfaced by name with its counts withheld (zeroed), so the
41
+ * `+N −M` stat renders nothing for it. The quiet/dim register (no border)
42
+ * distinguishes it from the loud, bordered decision prompt.
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * const conv = useSessionConversation(sessionId, org);
47
+ * <FileChangeProgressBar progress={conv.fileChangeProgress} expanded={expandTools} />
48
+ * ```
49
+ */
50
+ export function FileChangeProgressBar({
51
+ progress,
52
+ expanded = false,
53
+ }: FileChangeProgressBarProps) {
54
+ if (!progress || progress.filesChanged === 0) return null;
55
+
56
+ const { filesChanged, linesAdded, linesRemoved, entries } = progress;
57
+ const hiddenCount = filesChanged - entries.length;
58
+
59
+ return (
60
+ <Box flexDirection="column" paddingLeft={1}>
61
+ <Box gap={1}>
62
+ <Text dimColor>✎</Text>
63
+ <Text dimColor>
64
+ {filesChanged} file{filesChanged === 1 ? "" : "s"} changing…
65
+ </Text>
66
+ <LineStats linesAdded={linesAdded} linesRemoved={linesRemoved} />
67
+ </Box>
68
+
69
+ {expanded && (
70
+ <Box flexDirection="column" paddingLeft={2}>
71
+ {entries.map((entry, idx) => {
72
+ const path = progressEntryDisplayPath(entry);
73
+ return (
74
+ <Box key={`${path}-${idx}`} gap={1}>
75
+ <Text dimColor>{kindLetter(entry.kind)}</Text>
76
+ <Text dimColor wrap="truncate-end">
77
+ {path}
78
+ </Text>
79
+ <LineStats
80
+ linesAdded={entry.linesAdded}
81
+ linesRemoved={entry.linesRemoved}
82
+ />
83
+ </Box>
84
+ );
85
+ })}
86
+ {hiddenCount > 0 && (
87
+ <Box>
88
+ <Text dimColor>… and {hiddenCount} more</Text>
89
+ </Box>
90
+ )}
91
+ </Box>
92
+ )}
93
+ </Box>
94
+ );
95
+ }
96
+
97
+ /**
98
+ * The `+N −M` stat for one file (or the whole turn), in the diff colour
99
+ * vocabulary. Renders nothing when both counts are zero — the honest signal that
100
+ * no count exists (binary or secret-withheld changes) — rather than a misleading
101
+ * `+0 -0`, matching the web `FileLineStats` contract.
102
+ *
103
+ * Kept module-local: this is the only consumer today. When `FileReviewPrompt`
104
+ * and `FileReviewRecord` gain `+N −M` (the deferred "CLI +N −M parity"
105
+ * follow-up), lift this into a shared ink atom (the analogue of `sdk/react`'s
106
+ * `FileReviewAtoms`) so the three surfaces cannot drift — do not copy it.
107
+ */
108
+ function LineStats({
109
+ linesAdded,
110
+ linesRemoved,
111
+ }: {
112
+ readonly linesAdded: number;
113
+ readonly linesRemoved: number;
114
+ }) {
115
+ if (linesAdded === 0 && linesRemoved === 0) return null;
116
+ return (
117
+ <Text>
118
+ <Text color="green">+{linesAdded}</Text>
119
+ <Text color="red"> -{linesRemoved}</Text>
120
+ </Text>
121
+ );
122
+ }
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  CapturedFileChange,
3
+ FileChangeProgressEntry,
3
4
  FileChangeSet,
4
5
  } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
5
6
  import {
@@ -28,14 +29,39 @@ export function kindLetter(kind: FileChangeKind): string {
28
29
  }
29
30
 
30
31
  /**
31
- * The path to show for a change: the post-edit path, or the pre-edit path for a
32
- * deletion. A rename shows `before → after` so both sides are visible.
32
+ * The one rename-aware path-display rule for the terminal, over the raw
33
+ * before/after/kind triple shared by every file-change shape (reviewable
34
+ * `CapturedFileChange` and slim `FileChangeProgressEntry` alike). Kept private
35
+ * and fed by the typed adapters below so the two surfaces can never grow
36
+ * divergent rename formatting.
33
37
  */
34
- export function changeDisplayPath(change: CapturedFileChange): string {
35
- if (change.kind === FileChangeKind.RENAME && change.pathBefore && change.pathAfter) {
36
- return `${change.pathBefore} → ${change.pathAfter}`;
38
+ function displayChangePath(
39
+ pathBefore: string,
40
+ pathAfter: string,
41
+ kind: FileChangeKind,
42
+ ): string {
43
+ if (kind === FileChangeKind.RENAME && pathBefore && pathAfter) {
44
+ return `${pathBefore} → ${pathAfter}`;
37
45
  }
38
- return change.pathAfter || change.pathBefore;
46
+ return pathAfter || pathBefore;
47
+ }
48
+
49
+ /**
50
+ * The path to show for a reviewable change: the post-edit path, or the pre-edit
51
+ * path for a deletion. A rename shows `before → after` so both sides are visible.
52
+ */
53
+ export function changeDisplayPath(change: CapturedFileChange): string {
54
+ return displayChangePath(change.pathBefore, change.pathAfter, change.kind);
55
+ }
56
+
57
+ /**
58
+ * The path to show for a mid-run progress entry (DD-32), using the same
59
+ * rename-aware rule as {@link changeDisplayPath}. The slim entry carries no
60
+ * bodies or digests, only the same before/after/kind triple, so the terminal
61
+ * renders its path identically to the reviewable surfaces.
62
+ */
63
+ export function progressEntryDisplayPath(entry: FileChangeProgressEntry): string {
64
+ return displayChangePath(entry.pathBefore, entry.pathAfter, entry.kind);
39
65
  }
40
66
 
41
67
  /**
package/src/index.ts CHANGED
@@ -21,11 +21,16 @@ export { TodoList, type TodoListProps } from "./components/TodoList.js";
21
21
  export { ApprovalPrompt, type ApprovalPromptProps } from "./components/ApprovalPrompt.js";
22
22
  export { FileReviewPrompt, type FileReviewPromptProps } from "./components/FileReviewPrompt.js";
23
23
  export { FileReviewRecord, type FileReviewRecordProps } from "./components/FileReviewRecord.js";
24
+ export {
25
+ FileChangeProgressBar,
26
+ type FileChangeProgressBarProps,
27
+ } from "./components/FileChangeProgressBar.js";
24
28
 
25
29
  // File-review pure helpers (kind letters, paths, block reasons, settled counts)
26
30
  export {
27
31
  kindLetter,
28
32
  changeDisplayPath,
33
+ progressEntryDisplayPath,
29
34
  blockReasonNote,
30
35
  settledCounts,
31
36
  settledSummary,