@stigmer/ink 3.1.0 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/SessionView.d.ts.map +1 -1
- package/app/SessionView.js +11 -1
- package/app/SessionView.js.map +1 -1
- package/components/FileReviewPrompt.d.ts +43 -0
- package/components/FileReviewPrompt.d.ts.map +1 -0
- package/components/FileReviewPrompt.js +172 -0
- package/components/FileReviewPrompt.js.map +1 -0
- package/components/FileReviewRecord.d.ts +18 -0
- package/components/FileReviewRecord.d.ts.map +1 -0
- package/components/FileReviewRecord.js +32 -0
- package/components/FileReviewRecord.js.map +1 -0
- package/components/MessageThread.d.ts +19 -7
- package/components/MessageThread.d.ts.map +1 -1
- package/components/MessageThread.js +145 -77
- package/components/MessageThread.js.map +1 -1
- package/components/ToolCallGroup.d.ts.map +1 -1
- package/components/ToolCallGroup.js +42 -2
- package/components/ToolCallGroup.js.map +1 -1
- package/components/ToolCallItem.d.ts.map +1 -1
- package/components/ToolCallItem.js +16 -1
- package/components/ToolCallItem.js.map +1 -1
- package/file-review.d.ts +41 -0
- package/file-review.d.ts.map +1 -0
- package/file-review.js +94 -0
- package/file-review.js.map +1 -0
- package/index.d.ts +3 -0
- package/index.d.ts.map +1 -1
- package/index.js +4 -0
- package/index.js.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/file-review.test.tsx +496 -0
- package/src/app/SessionView.tsx +39 -3
- package/src/components/FileReviewPrompt.tsx +328 -0
- package/src/components/FileReviewRecord.tsx +63 -0
- package/src/components/MessageThread.tsx +199 -96
- package/src/components/ToolCallGroup.tsx +50 -1
- package/src/components/ToolCallItem.tsx +25 -0
- package/src/file-review.ts +109 -0
- package/src/index.ts +12 -0
package/app/SessionView.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionView.d.ts","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"
|
|
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"}
|
package/app/SessionView.js
CHANGED
|
@@ -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 { FileReviewPrompt } from "../components/FileReviewPrompt.js";
|
|
11
12
|
/**
|
|
12
13
|
* Full-featured session conversation view for the terminal.
|
|
13
14
|
*
|
|
@@ -59,7 +60,16 @@ export function SessionView({ sessionId, org, mode }) {
|
|
|
59
60
|
];
|
|
60
61
|
const activeTodos = conv.activeStreamExecution?.status?.todos;
|
|
61
62
|
const subject = resolvedSubject(conv.session?.spec?.subject);
|
|
62
|
-
return (_jsxs(Box, { flexDirection: "column", children: [subject && subject !== PENDING_SUBJECT && (_jsx(Box, { paddingLeft: 1, marginBottom: 1, children: _jsx(Text, { dimColor: true, bold: true, children: subject }) })), conv.isConnecting && (_jsxs(Box, { gap: 1, paddingLeft: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: "Connecting to stream..." })] })), conv.isReconnecting && (_jsxs(Box, { gap: 1, paddingLeft: 1, children: [_jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: "Reconnecting..." })] })), conv.streamError && (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, marginBottom: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: "Stream disconnected" }), _jsx(Text, { color: "red", dimColor: true, children: conv.streamError.message })] })), conv.activePhase != null &&
|
|
63
|
+
return (_jsxs(Box, { flexDirection: "column", children: [subject && subject !== PENDING_SUBJECT && (_jsx(Box, { paddingLeft: 1, marginBottom: 1, children: _jsx(Text, { dimColor: true, bold: true, children: subject }) })), conv.isConnecting && (_jsxs(Box, { gap: 1, paddingLeft: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: "Connecting to stream..." })] })), conv.isReconnecting && (_jsxs(Box, { gap: 1, paddingLeft: 1, children: [_jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: "Reconnecting..." })] })), conv.streamError && (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, marginBottom: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: "Stream disconnected" }), _jsx(Text, { color: "red", dimColor: true, children: conv.streamError.message })] })), conv.activePhase != null &&
|
|
64
|
+
conv.activePhase !== 0 &&
|
|
65
|
+
conv.fileChangeSets.length === 0 && (
|
|
66
|
+
// Suppressed while a set awaits review: there is no execution phase
|
|
67
|
+
// for review (it lives on FileChangeSet.status), so the phase would
|
|
68
|
+
// otherwise read as an active "Running" spinner while the agent is
|
|
69
|
+
// 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
|
+
// Single active decision surface: yield to a pending tool approval.
|
|
72
|
+
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"
|
|
63
73
|
? "Plan mode — read-only analysis, no file mutations"
|
|
64
74
|
: "Agent mode — full tool access" }) })), _jsx(FollowUpInput, { onSubmit: (message) => conv.sendFollowUp(message, { interactionMode: activeMode }), isSubmitting: conv.isSending, disabled: !conv.canSendFollowUp, mode: activeMode })] }));
|
|
65
75
|
}
|
package/app/SessionView.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionView.js","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,OAAO,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionView.js","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { FileChangeSet } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
|
|
2
|
+
import { FileDecisionAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
3
|
+
import { type FileDecisionOptions } from "@stigmer/react";
|
|
4
|
+
/** Props for {@link FileReviewPrompt}. */
|
|
5
|
+
export interface FileReviewPromptProps {
|
|
6
|
+
/** The AWAITING_REVIEW change set this prompt decides. */
|
|
7
|
+
readonly changeSet: FileChangeSet;
|
|
8
|
+
/**
|
|
9
|
+
* Submit a decision for this set (or one file within it). Bound to the active
|
|
10
|
+
* execution by the caller; the terminal analogue of the web dock's
|
|
11
|
+
* `submitFileDecision`.
|
|
12
|
+
*/
|
|
13
|
+
readonly onSubmit: (changeSetId: string, action: FileDecisionAction, options?: FileDecisionOptions) => void;
|
|
14
|
+
/** Keys (via `fileDecisionKey`) currently being submitted — drives busy state. */
|
|
15
|
+
readonly submittingDecisionKeys?: ReadonlySet<string>;
|
|
16
|
+
/** Per-decision failures, keyed via `fileDecisionKey`. */
|
|
17
|
+
readonly decisionErrors?: ReadonlyMap<string, Error>;
|
|
18
|
+
/**
|
|
19
|
+
* Whether this prompt owns the keyboard. False renders a read-only view (no
|
|
20
|
+
* `useInput`) so exactly one decision surface is interactive at a time.
|
|
21
|
+
* Defaults to `true`.
|
|
22
|
+
*/
|
|
23
|
+
readonly isActive?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The terminal file-review decision surface — the linear-log analogue of the
|
|
27
|
+
* web's composer-docked `FileReviewDock`/`FileReviewCard`.
|
|
28
|
+
*
|
|
29
|
+
* Renders `N files awaiting review` and, gated by `changeSetReviewability`:
|
|
30
|
+
* bulk Approve/Keep all + Reject all (a complete set is approvable as-is; a
|
|
31
|
+
* binary-only set is kept with an acknowledgement; a blocked set can only be
|
|
32
|
+
* rejected in bulk), plus a per-file mode (`f`) for keeping/discarding each file
|
|
33
|
+
* — the only way to resolve a blocked or mixed set, since the server refuses a
|
|
34
|
+
* whole-set approve unless every file is complete. Decisions carry the same
|
|
35
|
+
* digests (`aggregate_digest` / `file_digest`) and `acknowledge_unreviewable`
|
|
36
|
+
* semantics as the web; no decision-model change.
|
|
37
|
+
*
|
|
38
|
+
* Keyboard: `a` approve/keep all · `r` reject all · `f` per-file mode; in
|
|
39
|
+
* per-file mode ↑/↓ move, `k` keep, `d` discard, `esc` back. Input is gated by
|
|
40
|
+
* `isActive` so only one decision surface owns the keyboard at a time.
|
|
41
|
+
*/
|
|
42
|
+
export declare function FileReviewPrompt({ changeSet, onSubmit, submittingDecisionKeys, decisionErrors, isActive, }: FileReviewPromptProps): import("react/jsx-runtime").JSX.Element;
|
|
43
|
+
//# sourceMappingURL=FileReviewPrompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileReviewPrompt.d.ts","sourceRoot":"","sources":["../../src/components/FileReviewPrompt.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,aAAa,EACd,MAAM,oEAAoE,CAAC;AAC5E,OAAO,EACL,kBAAkB,EAEnB,MAAM,8DAA8D,CAAC;AACtE,OAAO,EAKL,KAAK,mBAAmB,EACzB,MAAM,gBAAgB,CAAC;AAGxB,0CAA0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,CACjB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,kBAAkB,EAC1B,OAAO,CAAC,EAAE,mBAAmB,KAC1B,IAAI,CAAC;IACV,kFAAkF;IAClF,QAAQ,CAAC,sBAAsB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtD,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AA2BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,QAAQ,EACR,sBAAsB,EACtB,cAAc,EACd,QAAe,GAChB,EAAE,qBAAqB,2CAmLvB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import { Box, Text, useInput } from "ink";
|
|
4
|
+
import { FileDecisionAction, FileDecisionScope, } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
5
|
+
import { changeSetReviewability, fileReviewability, deriveEffectiveVerdicts, } from "@stigmer/react";
|
|
6
|
+
import { blockReasonNote, changeDisplayPath, kindLetter } from "../file-review.js";
|
|
7
|
+
/**
|
|
8
|
+
* The bulk approve/reject verb labels for a set, mirroring the web card's
|
|
9
|
+
* `bulkLabels`: "Keep" for a binary-only set (its bytes are applied as-is),
|
|
10
|
+
* "Approve" otherwise; "remaining" when some files are already decided.
|
|
11
|
+
*/
|
|
12
|
+
function bulkLabels(total, decided, binaryOnly) {
|
|
13
|
+
const verb = binaryOnly ? "Keep" : "Approve";
|
|
14
|
+
if (total <= 1)
|
|
15
|
+
return { approve: verb, reject: "Reject" };
|
|
16
|
+
if (decided > 0 && decided < total) {
|
|
17
|
+
return { approve: `${verb} remaining`, reject: "Reject remaining" };
|
|
18
|
+
}
|
|
19
|
+
return { approve: `${verb} all`, reject: "Reject all" };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The terminal file-review decision surface — the linear-log analogue of the
|
|
23
|
+
* web's composer-docked `FileReviewDock`/`FileReviewCard`.
|
|
24
|
+
*
|
|
25
|
+
* Renders `N files awaiting review` and, gated by `changeSetReviewability`:
|
|
26
|
+
* bulk Approve/Keep all + Reject all (a complete set is approvable as-is; a
|
|
27
|
+
* binary-only set is kept with an acknowledgement; a blocked set can only be
|
|
28
|
+
* rejected in bulk), plus a per-file mode (`f`) for keeping/discarding each file
|
|
29
|
+
* — the only way to resolve a blocked or mixed set, since the server refuses a
|
|
30
|
+
* whole-set approve unless every file is complete. Decisions carry the same
|
|
31
|
+
* digests (`aggregate_digest` / `file_digest`) and `acknowledge_unreviewable`
|
|
32
|
+
* semantics as the web; no decision-model change.
|
|
33
|
+
*
|
|
34
|
+
* Keyboard: `a` approve/keep all · `r` reject all · `f` per-file mode; in
|
|
35
|
+
* per-file mode ↑/↓ move, `k` keep, `d` discard, `esc` back. Input is gated by
|
|
36
|
+
* `isActive` so only one decision surface owns the keyboard at a time.
|
|
37
|
+
*/
|
|
38
|
+
export function FileReviewPrompt({ changeSet, onSubmit, submittingDecisionKeys, decisionErrors, isActive = true, }) {
|
|
39
|
+
const [perFile, setPerFile] = useState(false);
|
|
40
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
41
|
+
const changes = changeSet.changes;
|
|
42
|
+
const total = changes.length;
|
|
43
|
+
const reviewability = changeSetReviewability(changeSet);
|
|
44
|
+
const binaryOnly = reviewability === "binary-only";
|
|
45
|
+
const canBulkApprove = reviewability !== "blocked";
|
|
46
|
+
const verdicts = useMemo(() => deriveEffectiveVerdicts(changeSet), [changeSet]);
|
|
47
|
+
const decidedCount = useMemo(() => {
|
|
48
|
+
let n = 0;
|
|
49
|
+
for (const c of changes)
|
|
50
|
+
if (verdicts.has(c.id))
|
|
51
|
+
n++;
|
|
52
|
+
return n;
|
|
53
|
+
}, [changes, verdicts]);
|
|
54
|
+
const labels = bulkLabels(total, decidedCount, binaryOnly);
|
|
55
|
+
// Busy while any decision for THIS set is in flight (whole-set key or any
|
|
56
|
+
// per-file key). Blocks input to avoid a double-submit mid-request.
|
|
57
|
+
const busy = useMemo(() => {
|
|
58
|
+
if (!submittingDecisionKeys)
|
|
59
|
+
return false;
|
|
60
|
+
for (const key of submittingDecisionKeys) {
|
|
61
|
+
if (key === changeSet.id || key.startsWith(`${changeSet.id}:`))
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}, [submittingDecisionKeys, changeSet.id]);
|
|
66
|
+
const errorText = useMemo(() => {
|
|
67
|
+
if (!decisionErrors)
|
|
68
|
+
return null;
|
|
69
|
+
for (const [key, err] of decisionErrors) {
|
|
70
|
+
if (key === changeSet.id || key.startsWith(`${changeSet.id}:`)) {
|
|
71
|
+
return err.message;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}, [decisionErrors, changeSet.id]);
|
|
76
|
+
const submitBulk = (action) => {
|
|
77
|
+
onSubmit(changeSet.id, action, {
|
|
78
|
+
scope: FileDecisionScope.CHANGE_SET,
|
|
79
|
+
expectedDigest: changeSet.aggregateDigest,
|
|
80
|
+
acknowledgeUnreviewable: action === FileDecisionAction.APPROVE && binaryOnly,
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const submitFile = (change, action) => {
|
|
84
|
+
onSubmit(changeSet.id, action, {
|
|
85
|
+
scope: FileDecisionScope.FILE,
|
|
86
|
+
fileChangeId: change.id,
|
|
87
|
+
expectedDigest: change.fileDigest,
|
|
88
|
+
acknowledgeUnreviewable: action === FileDecisionAction.APPROVE &&
|
|
89
|
+
fileReviewability(change).kind === "binary",
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
// Rebuilt each render (cheap; 2-3 options) so the `run` closures always bind
|
|
93
|
+
// the current `changeSet`/`onSubmit` — a memo keyed on the labels would hold
|
|
94
|
+
// a stale submit closure when the set updates without changing its labels.
|
|
95
|
+
const bulkOptions = [];
|
|
96
|
+
if (canBulkApprove) {
|
|
97
|
+
bulkOptions.push({
|
|
98
|
+
label: labels.approve,
|
|
99
|
+
shortcut: "a",
|
|
100
|
+
color: "green",
|
|
101
|
+
run: () => submitBulk(FileDecisionAction.APPROVE),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
bulkOptions.push({
|
|
105
|
+
label: labels.reject,
|
|
106
|
+
shortcut: "r",
|
|
107
|
+
color: "red",
|
|
108
|
+
run: () => submitBulk(FileDecisionAction.REJECT),
|
|
109
|
+
});
|
|
110
|
+
bulkOptions.push({
|
|
111
|
+
label: "Review files",
|
|
112
|
+
shortcut: "f",
|
|
113
|
+
color: "cyan",
|
|
114
|
+
run: () => {
|
|
115
|
+
setSelectedIndex(0);
|
|
116
|
+
setPerFile(true);
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
useInput((input, key) => {
|
|
120
|
+
if (busy)
|
|
121
|
+
return;
|
|
122
|
+
if (perFile) {
|
|
123
|
+
if (key.escape) {
|
|
124
|
+
setPerFile(false);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (key.upArrow) {
|
|
128
|
+
setSelectedIndex((i) => (i > 0 ? i - 1 : total - 1));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (key.downArrow) {
|
|
132
|
+
setSelectedIndex((i) => (i < total - 1 ? i + 1 : 0));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const change = changes[selectedIndex];
|
|
136
|
+
if (!change)
|
|
137
|
+
return;
|
|
138
|
+
if (input === "k") {
|
|
139
|
+
// Keep is refused for a file with no reviewable/keepable bytes.
|
|
140
|
+
if (fileReviewability(change).kind !== "unavailable") {
|
|
141
|
+
submitFile(change, FileDecisionAction.APPROVE);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else if (input === "d") {
|
|
145
|
+
submitFile(change, FileDecisionAction.REJECT);
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Bulk mode.
|
|
150
|
+
const match = bulkOptions.find((o) => o.shortcut === input.toLowerCase());
|
|
151
|
+
if (match)
|
|
152
|
+
match.run();
|
|
153
|
+
}, { isActive: isActive && !busy });
|
|
154
|
+
return (_jsxs(Box, { flexDirection: "column", paddingLeft: 2, paddingTop: 1, paddingBottom: 1, borderStyle: "round", borderColor: "cyan", children: [_jsx(Box, { gap: 1, children: _jsxs(Text, { color: "cyan", bold: true, children: ["\u270E ", total, " file", total === 1 ? "" : "s", " awaiting review"] }) }), perFile ? (_jsx(PerFileList, { changes: changes, verdicts: verdicts, selectedIndex: selectedIndex, interactive: isActive && !busy })) : (_jsx(Box, { gap: 2, marginTop: 1, paddingLeft: 2, children: bulkOptions.map((opt) => (_jsxs(Text, { color: opt.color, children: ["[", opt.shortcut, "] ", opt.label] }, opt.shortcut))) })), busy && (_jsx(Box, { paddingLeft: 2, marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Submitting..." }) })), errorText && (_jsx(Box, { paddingLeft: 2, marginTop: 1, children: _jsxs(Text, { color: "red", children: ["Decision failed: ", errorText] }) })), !isActive && !perFile && (_jsx(Box, { paddingLeft: 2, marginTop: 1, children: _jsx(Text, { dimColor: true, italic: true, children: "Resolve the pending approval first" }) }))] }));
|
|
155
|
+
}
|
|
156
|
+
/** The per-file review list: kind letter, path, verdict/keepability, and a hint. */
|
|
157
|
+
function PerFileList({ changes, verdicts, selectedIndex, interactive, }) {
|
|
158
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, paddingLeft: 2, children: [changes.map((change, idx) => {
|
|
159
|
+
const selected = idx === selectedIndex;
|
|
160
|
+
const verdict = verdicts.get(change.id);
|
|
161
|
+
const note = blockReasonNote(change);
|
|
162
|
+
const decided = verdict === FileDecisionAction.APPROVE
|
|
163
|
+
? "kept"
|
|
164
|
+
: verdict === FileDecisionAction.REJECT
|
|
165
|
+
? "discarded"
|
|
166
|
+
: null;
|
|
167
|
+
return (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: selected ? "cyan" : undefined, children: selected ? "▸" : " " }), _jsx(Text, { dimColor: true, children: kindLetter(change.kind) }), _jsx(Text, { color: selected ? "cyan" : undefined, bold: selected, wrap: "truncate-end", children: changeDisplayPath(change) }), decided && _jsxs(Text, { dimColor: true, children: ["(", decided, ")"] }), !decided && note && _jsxs(Text, { color: "yellow", children: ["\u2014 ", note] })] }, change.id));
|
|
168
|
+
}), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: interactive
|
|
169
|
+
? "↑/↓ move · [k] keep · [d] discard · [esc] back"
|
|
170
|
+
: "read-only" }) })] }));
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=FileReviewPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileReviewPrompt.js","sourceRoot":"","sources":["../../src/components/FileReviewPrompt.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FileChangeSet } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
|
|
2
|
+
/** Props for {@link FileReviewRecord}. */
|
|
3
|
+
export interface FileReviewRecordProps {
|
|
4
|
+
/** A settled (decided / reconciled / failed) change set to record. */
|
|
5
|
+
readonly fileChangeSet: FileChangeSet;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A read-only, append-only record of a SETTLED file-review change set — the
|
|
9
|
+
* terminal analogue of the web's in-thread `FileReviewRecordRow` (DD-27 D2).
|
|
10
|
+
*
|
|
11
|
+
* Its primary job is the no-stamped-row case: a set changed only via shell
|
|
12
|
+
* commands stamps no edit rows, so the per-row badges leave no trace and this
|
|
13
|
+
* record is the only evidence of what was reviewed and decided. Sets with
|
|
14
|
+
* stamped rows already carry their outcome on the (frozen) row badges; this
|
|
15
|
+
* record complements them with a one-line summary and file list.
|
|
16
|
+
*/
|
|
17
|
+
export declare function FileReviewRecord({ fileChangeSet }: FileReviewRecordProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=FileReviewRecord.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileReviewRecord.d.ts","sourceRoot":"","sources":["../../src/components/FileReviewRecord.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oEAAoE,CAAC;AAYxG,0CAA0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,aAAa,EAAE,EAAE,qBAAqB,2CAgCxE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import { FileChangeSetStatus, FileDecisionAction, } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
4
|
+
import { deriveEffectiveVerdicts } from "@stigmer/react";
|
|
5
|
+
import { changeDisplayPath, kindLetter, settledSummary, } from "../file-review.js";
|
|
6
|
+
/**
|
|
7
|
+
* A read-only, append-only record of a SETTLED file-review change set — the
|
|
8
|
+
* terminal analogue of the web's in-thread `FileReviewRecordRow` (DD-27 D2).
|
|
9
|
+
*
|
|
10
|
+
* Its primary job is the no-stamped-row case: a set changed only via shell
|
|
11
|
+
* commands stamps no edit rows, so the per-row badges leave no trace and this
|
|
12
|
+
* record is the only evidence of what was reviewed and decided. Sets with
|
|
13
|
+
* stamped rows already carry their outcome on the (frozen) row badges; this
|
|
14
|
+
* record complements them with a one-line summary and file list.
|
|
15
|
+
*/
|
|
16
|
+
export function FileReviewRecord({ fileChangeSet }) {
|
|
17
|
+
const failed = fileChangeSet.status === FileChangeSetStatus.FAILED;
|
|
18
|
+
const verdicts = deriveEffectiveVerdicts(fileChangeSet);
|
|
19
|
+
const summary = failed ? "review failed" : settledSummary(fileChangeSet);
|
|
20
|
+
return (_jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "\u270E" }), _jsxs(Text, { dimColor: true, children: ["File review \u2014 ", summary] })] }), fileChangeSet.changes.map((change) => {
|
|
21
|
+
const verdict = verdicts.get(change.id);
|
|
22
|
+
const label = failed
|
|
23
|
+
? null
|
|
24
|
+
: verdict === FileDecisionAction.APPROVE
|
|
25
|
+
? "kept"
|
|
26
|
+
: verdict === FileDecisionAction.REJECT
|
|
27
|
+
? "discarded"
|
|
28
|
+
: "not reviewed";
|
|
29
|
+
return (_jsxs(Box, { paddingLeft: 2, gap: 1, children: [_jsx(Text, { dimColor: true, children: kindLetter(change.kind) }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: changeDisplayPath(change) }), label && _jsxs(Text, { dimColor: true, children: ["(", label, ")"] })] }, change.id));
|
|
30
|
+
})] }));
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=FileReviewRecord.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileReviewRecord.js","sourceRoot":"","sources":["../../src/components/FileReviewRecord.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EACL,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,8DAA8D,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,cAAc,GACf,MAAM,mBAAmB,CAAC;AAQ3B;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAE,aAAa,EAAyB;IACvE,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,KAAK,mBAAmB,CAAC,MAAM,CAAC;IACnE,MAAM,QAAQ,GAAG,uBAAuB,CAAC,aAAa,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;IAEzE,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,0CAAgB,OAAO,IAAQ,IACzC,EACL,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;gBACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxC,MAAM,KAAK,GAAG,MAAM;oBAClB,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,OAAO,KAAK,kBAAkB,CAAC,OAAO;wBACtC,CAAC,CAAC,MAAM;wBACR,CAAC,CAAC,OAAO,KAAK,kBAAkB,CAAC,MAAM;4BACrC,CAAC,CAAC,WAAW;4BACb,CAAC,CAAC,cAAc,CAAC;gBACvB,OAAO,CACL,MAAC,GAAG,IAAiB,WAAW,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,aACzC,KAAC,IAAI,IAAC,QAAQ,kBAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAQ,EAC/C,KAAC,IAAI,IAAC,QAAQ,QAAC,IAAI,EAAC,cAAc,YAC/B,iBAAiB,CAAC,MAAM,CAAC,GACrB,EACN,KAAK,IAAI,MAAC,IAAI,IAAC,QAAQ,wBAAG,KAAK,SAAS,KALjC,MAAM,CAAC,EAAE,CAMb,CACP,CAAC;YACJ,CAAC,CAAC,IACE,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -14,18 +14,30 @@ export interface MessageThreadProps {
|
|
|
14
14
|
readonly submittingApprovalIds?: ReadonlySet<string>;
|
|
15
15
|
/** Whether tool call groups should be rendered in expanded mode. Toggled via Ctrl+O. */
|
|
16
16
|
readonly expandToolCalls?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether to render a read-only settled record for each decided/reconciled/
|
|
19
|
+
* failed change set (the terminal analogue of the web's in-thread record,
|
|
20
|
+
* DD-27 D2). Off by default so bare consumers stay minimal; `SessionView`
|
|
21
|
+
* opts in. Pending (AWAITING_REVIEW) sets are never records here — their
|
|
22
|
+
* decision surface is the docked `FileReviewPrompt`.
|
|
23
|
+
*/
|
|
24
|
+
readonly showFileReviewRecords?: boolean;
|
|
17
25
|
}
|
|
18
26
|
/**
|
|
19
27
|
* Renders a continuous conversation thread from one or more
|
|
20
28
|
* `AgentExecution` snapshots in the terminal.
|
|
21
29
|
*
|
|
22
|
-
* Composes {@link MessageEntry}, {@link ToolCallGroup},
|
|
23
|
-
* {@link ExecutionProgress},
|
|
24
|
-
* scrolling terminal log.
|
|
30
|
+
* Composes {@link MessageEntry}, {@link ToolCallGroup}, {@link SubAgentBlock},
|
|
31
|
+
* {@link ExecutionProgress}, {@link ApprovalPrompt}, and (for settled change
|
|
32
|
+
* sets) {@link FileReviewRecord} into a scrolling terminal log.
|
|
25
33
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
34
|
+
* Completed executions are rendered via Ink's `<Static>` component so they are
|
|
35
|
+
* written once and don't re-render, keeping terminal output efficient for long
|
|
36
|
+
* conversations. The active execution renders live so its file-review row
|
|
37
|
+
* badges transition (Pending review → Kept/Discarded) in place, then freeze
|
|
38
|
+
* into `<Static>` when the execution reaches a terminal phase. The thread is
|
|
39
|
+
* wrapped in a `FileReviewContext` provider so every {@link ToolCallItem}
|
|
40
|
+
* can badge its stamped edit rows.
|
|
29
41
|
*/
|
|
30
|
-
export declare function MessageThread({ executions, activeStreamExecution, pendingUserMessage, onApprovalSubmit, submittingApprovalIds, expandToolCalls, }: MessageThreadProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
export declare function MessageThread({ executions, activeStreamExecution, pendingUserMessage, onApprovalSubmit, submittingApprovalIds, expandToolCalls, showFileReviewRecords, }: MessageThreadProps): import("react/jsx-runtime").JSX.Element;
|
|
31
43
|
//# sourceMappingURL=MessageThread.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageThread.d.ts","sourceRoot":"","sources":["../../src/components/MessageThread.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6DAA6D,CAAC;
|
|
1
|
+
{"version":3,"file":"MessageThread.d.ts","sourceRoot":"","sources":["../../src/components/MessageThread.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6DAA6D,CAAC;AASlG,OAAO,EACL,cAAc,EAIf,MAAM,8DAA8D,CAAC;AActE,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,uEAAuE;IACvE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACvD,mEAAmE;IACnE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,sEAAsE;IACtE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,KACnB,IAAI,CAAC;IACV,mEAAmE;IACnE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACrD,wFAAwF;IACxF,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAC1C;AAuMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,EAC5B,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,eAAuB,EACvB,qBAA6B,GAC9B,EAAE,kBAAkB,2CA+CpB"}
|