@molecule/app-ide-react 1.16.0 → 1.17.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.
- package/README.md +7 -1
- package/dist/components/ChatPanel.d.ts.map +1 -1
- package/dist/components/ChatPanel.js +57 -1
- package/dist/components/ChatPanel.js.map +1 -1
- package/dist/components/MarkdownContent.d.ts.map +1 -1
- package/dist/components/MarkdownContent.js +27 -7
- package/dist/components/MarkdownContent.js.map +1 -1
- package/dist/components/TestStatusBar.d.ts +56 -0
- package/dist/components/TestStatusBar.d.ts.map +1 -0
- package/dist/components/TestStatusBar.js +105 -0
- package/dist/components/TestStatusBar.js.map +1 -0
- package/dist/components/ToolCallCard.d.ts.map +1 -1
- package/dist/components/ToolCallCard.js +384 -68
- package/dist/components/ToolCallCard.js.map +1 -1
- package/dist/components/tests-bar-utilities.d.ts +78 -103
- package/dist/components/tests-bar-utilities.d.ts.map +1 -1
- package/dist/components/tests-bar-utilities.js +130 -201
- package/dist/components/tests-bar-utilities.js.map +1 -1
- package/dist/components/tool-call-utilities.d.ts +68 -7
- package/dist/components/tool-call-utilities.d.ts.map +1 -1
- package/dist/components/tool-call-utilities.js +124 -6
- package/dist/components/tool-call-utilities.js.map +1 -1
- package/dist/hooks/useTestsBarVisible.d.ts +16 -0
- package/dist/hooks/useTestsBarVisible.d.ts.map +1 -0
- package/dist/hooks/useTestsBarVisible.js +39 -0
- package/dist/hooks/useTestsBarVisible.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,236 +1,165 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The tests status bar — its visibility preference and the pure summary the bar
|
|
3
|
+
* renders. The component is `TestStatusBar.tsx`; the hook is
|
|
4
|
+
* `hooks/useTestsBarVisible.ts`.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the
|
|
6
|
+
* Visibility is a PER-DEVICE, per-user display preference in localStorage, the
|
|
7
|
+
* same shape as `/timestamps` and `/sounds` — never project settings, so a
|
|
8
|
+
* viewer can hide the bar without changing what a teammate sees. It defaults to
|
|
9
|
+
* SHOWN: a run drives the project's preview as it goes, and a preview that moves
|
|
10
|
+
* on its own with nothing on screen to explain it is the problem this bar
|
|
11
|
+
* exists to remove.
|
|
7
12
|
*
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export const MAX_OUTPUT_LINES = 400;
|
|
12
|
-
/** Display order of the kinds: the preview-driven specs lead, unit tests follow. */
|
|
13
|
-
const KIND_ORDER = ['e2e', 'unit'];
|
|
14
|
-
/**
|
|
15
|
-
* Display order of the project directories within a kind: by path, with the
|
|
16
|
-
* workspace root (`.`) last — it is the least specific place a test can live.
|
|
13
|
+
* Shown, however, still means "once the project HAS tests" — see
|
|
14
|
+
* {@link shouldShowTestsBar}. The preference decides whether the person wants
|
|
15
|
+
* the bar; that predicate decides whether there is anything for it to say.
|
|
17
16
|
*
|
|
18
|
-
* @
|
|
19
|
-
* @param b - The other.
|
|
20
|
-
* @returns The sort order.
|
|
17
|
+
* @module
|
|
21
18
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return 1;
|
|
27
|
-
if (b === '.')
|
|
28
|
-
return -1;
|
|
29
|
-
return a.localeCompare(b);
|
|
30
|
-
}
|
|
19
|
+
/** localStorage key holding `'true'` / `'false'`. Absent = the default (shown). */
|
|
20
|
+
export const TESTS_BAR_STORAGE_KEY = 'mol_chat_show_tests_bar';
|
|
21
|
+
/** Window event dispatched (same tab) whenever the preference changes. */
|
|
22
|
+
export const TESTS_BAR_EVENT = 'mol:tests-bar-changed';
|
|
31
23
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
24
|
+
* Parses the stored preference. Only an explicit `'false'` hides the bar, so a
|
|
25
|
+
* missing or unreadable value keeps the default (shown).
|
|
34
26
|
*
|
|
35
|
-
* @param
|
|
36
|
-
* @returns
|
|
27
|
+
* @param raw - The raw localStorage value.
|
|
28
|
+
* @returns Whether the tests bar is visible.
|
|
37
29
|
*/
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
return item.workspaceLabel;
|
|
41
|
-
return item.workspace === '.' ? null : item.workspace;
|
|
30
|
+
export function parseTestsBarVisible(raw) {
|
|
31
|
+
return raw !== 'false';
|
|
42
32
|
}
|
|
43
|
-
/** A run that has not started. */
|
|
44
|
-
export const EMPTY_RUN_STATE = {
|
|
45
|
-
runId: null,
|
|
46
|
-
running: false,
|
|
47
|
-
queued: [],
|
|
48
|
-
currentId: null,
|
|
49
|
-
output: [],
|
|
50
|
-
results: {},
|
|
51
|
-
outcome: null,
|
|
52
|
-
error: null,
|
|
53
|
-
startedAt: null,
|
|
54
|
-
durationMs: null,
|
|
55
|
-
};
|
|
56
33
|
/**
|
|
57
|
-
*
|
|
58
|
-
* directory (whatever directories are present — `app`, `my-app/app`,
|
|
59
|
-
* `packages/web`, the root last), with the files sorted inside each group.
|
|
34
|
+
* Reads this device's preference.
|
|
60
35
|
*
|
|
61
|
-
* @
|
|
62
|
-
* @returns The groups, in display order. Empty groups are never produced.
|
|
36
|
+
* @returns Whether the tests bar is visible (default `true`).
|
|
63
37
|
*/
|
|
64
|
-
export function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const workspaces = [
|
|
68
|
-
...new Set(tests.filter((t) => t.kind === kind).map((t) => t.workspace)),
|
|
69
|
-
].sort(compareWorkspaces);
|
|
70
|
-
for (const workspace of workspaces) {
|
|
71
|
-
const items = tests
|
|
72
|
-
.filter((t) => t.kind === kind && t.workspace === workspace)
|
|
73
|
-
.slice()
|
|
74
|
-
.sort((a, b) => a.file.localeCompare(b.file));
|
|
75
|
-
if (items.length > 0)
|
|
76
|
-
groups.push({ kind, workspace, label: labelFor(items[0]), items });
|
|
77
|
-
}
|
|
38
|
+
export function getTestsBarVisible() {
|
|
39
|
+
try {
|
|
40
|
+
return parseTestsBarVisible(localStorage.getItem(TESTS_BAR_STORAGE_KEY));
|
|
78
41
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
* How many tests there are of each kind.
|
|
83
|
-
*
|
|
84
|
-
* @param tests - Every discovered test.
|
|
85
|
-
* @returns The per-kind counts.
|
|
86
|
-
*/
|
|
87
|
-
export function countByKind(tests) {
|
|
88
|
-
return {
|
|
89
|
-
e2e: tests.filter((t) => t.kind === 'e2e').length,
|
|
90
|
-
unit: tests.filter((t) => t.kind === 'unit').length,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* The tallies of the last run, over the tests that are still listed. Counted
|
|
95
|
-
* per FILE (one row, one verdict) so the collapsed summary matches the rows.
|
|
96
|
-
*
|
|
97
|
-
* @param tests - The currently listed tests.
|
|
98
|
-
* @param results - The per-id outcomes.
|
|
99
|
-
* @returns Passed/failed/skipped file counts.
|
|
100
|
-
*/
|
|
101
|
-
export function summarizeResults(tests, results) {
|
|
102
|
-
let passed = 0;
|
|
103
|
-
let failed = 0;
|
|
104
|
-
let skipped = 0;
|
|
105
|
-
for (const test of tests) {
|
|
106
|
-
const entry = results[test.id];
|
|
107
|
-
if (!entry)
|
|
108
|
-
continue;
|
|
109
|
-
if (entry.status === 'passed')
|
|
110
|
-
passed += 1;
|
|
111
|
-
else if (entry.status === 'failed')
|
|
112
|
-
failed += 1;
|
|
113
|
-
else
|
|
114
|
-
skipped += 1;
|
|
42
|
+
catch (_error) {
|
|
43
|
+
// localStorage unavailable (private mode, SSR) — fall back to the default.
|
|
44
|
+
return true;
|
|
115
45
|
}
|
|
116
|
-
return { passed, failed, skipped, reported: passed + failed + skipped };
|
|
117
46
|
}
|
|
118
47
|
/**
|
|
119
|
-
*
|
|
48
|
+
* Writes this device's preference and tells every mounted chat in this tab.
|
|
120
49
|
*
|
|
121
|
-
*
|
|
122
|
-
* anyway (a re-list may be in flight), and an unknown event type leaves the
|
|
123
|
-
* state untouched rather than throwing inside a stream handler.
|
|
124
|
-
*
|
|
125
|
-
* @param state - The current state.
|
|
126
|
-
* @param event - The event just received.
|
|
127
|
-
* @returns The next state (a new object whenever anything changed).
|
|
50
|
+
* @param visible - Whether the bar should be shown.
|
|
128
51
|
*/
|
|
129
|
-
export function
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
queued: [...event.ids],
|
|
142
|
-
currentId: null,
|
|
143
|
-
output: [],
|
|
144
|
-
results,
|
|
145
|
-
outcome: null,
|
|
146
|
-
error: null,
|
|
147
|
-
startedAt: Date.now(),
|
|
148
|
-
durationMs: null,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
case 'output': {
|
|
152
|
-
const output = [...state.output, ...event.chunk.split('\n')];
|
|
153
|
-
return {
|
|
154
|
-
...state,
|
|
155
|
-
currentId: event.id ?? state.currentId,
|
|
156
|
-
output: output.length > MAX_OUTPUT_LINES ? output.slice(-MAX_OUTPUT_LINES) : output,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
case 'result': {
|
|
160
|
-
return {
|
|
161
|
-
...state,
|
|
162
|
-
results: {
|
|
163
|
-
...state.results,
|
|
164
|
-
[event.id]: {
|
|
165
|
-
status: event.status,
|
|
166
|
-
...(event.durationMs != null ? { durationMs: event.durationMs } : {}),
|
|
167
|
-
passed: event.passed ?? 0,
|
|
168
|
-
failed: event.failed ?? 0,
|
|
169
|
-
skipped: event.skipped ?? 0,
|
|
170
|
-
...(event.output ? { output: event.output } : {}),
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
case 'done': {
|
|
176
|
-
return {
|
|
177
|
-
...state,
|
|
178
|
-
running: false,
|
|
179
|
-
currentId: null,
|
|
180
|
-
outcome: event.outcome,
|
|
181
|
-
error: event.error ?? null,
|
|
182
|
-
durationMs: event.durationMs ?? (state.startedAt ? Date.now() - state.startedAt : null),
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
default:
|
|
186
|
-
return state;
|
|
52
|
+
export function setTestsBarVisible(visible) {
|
|
53
|
+
try {
|
|
54
|
+
localStorage.setItem(TESTS_BAR_STORAGE_KEY, visible ? 'true' : 'false');
|
|
55
|
+
}
|
|
56
|
+
catch (_error) {
|
|
57
|
+
// Unwritable storage still fires the event, so the current tab follows.
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
window.dispatchEvent(new CustomEvent(TESTS_BAR_EVENT, { detail: { visible } }));
|
|
61
|
+
}
|
|
62
|
+
catch (_error) {
|
|
63
|
+
// No window (SSR) — nothing is mounted to notify.
|
|
187
64
|
}
|
|
188
65
|
}
|
|
189
66
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
67
|
+
* What `/test on|off|toggle` means. Anything else is not a visibility request —
|
|
68
|
+
* bare `/test` opens the tests browser, which is a different thing entirely.
|
|
192
69
|
*
|
|
193
|
-
* @param
|
|
194
|
-
* @param
|
|
195
|
-
* @returns The
|
|
70
|
+
* @param args - The text after `/test`.
|
|
71
|
+
* @param current - The current visibility, for `toggle`.
|
|
72
|
+
* @returns The requested visibility, or null when the argument is not one.
|
|
196
73
|
*/
|
|
197
|
-
export function
|
|
198
|
-
|
|
74
|
+
export function parseTestsBarArg(args, current) {
|
|
75
|
+
const word = args.trim().toLowerCase();
|
|
76
|
+
if (word === 'on' || word === 'show' || word === 'bar on')
|
|
77
|
+
return true;
|
|
78
|
+
if (word === 'off' || word === 'hide' || word === 'bar off')
|
|
79
|
+
return false;
|
|
80
|
+
if (word === 'toggle' || word === 'bar')
|
|
81
|
+
return !current;
|
|
82
|
+
return null;
|
|
199
83
|
}
|
|
200
84
|
/**
|
|
201
|
-
* Whether
|
|
202
|
-
* named this row as current, or it is in the queue and has no verdict yet.
|
|
85
|
+
* Whether there is anything for the bar to report.
|
|
203
86
|
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
87
|
+
* A project with no tests yet gets NO bar. The strip earns its slot above the
|
|
88
|
+
* composer by accounting for something — a suite's verdict, a run driving the
|
|
89
|
+
* preview — and a project that has not been given tests has neither; an empty
|
|
90
|
+
* strip saying "Tests not run yet" is noise in exactly the projects that are
|
|
91
|
+
* least ready for it. It appears on its own the moment discovery finds a spec.
|
|
92
|
+
*
|
|
93
|
+
* The run clauses come second on purpose: a run in flight, a run-level error or
|
|
94
|
+
* a finished outcome all mean tests EXIST, whatever the discovered list happens
|
|
95
|
+
* to hold at that moment (a list can be empty because discovery has not
|
|
96
|
+
* answered yet, not because the project is bare).
|
|
97
|
+
*
|
|
98
|
+
* @param run - The live run state.
|
|
99
|
+
* @param tests - The discovered tests.
|
|
100
|
+
* @returns Whether the bar should render at all.
|
|
207
101
|
*/
|
|
208
|
-
export function
|
|
209
|
-
if (
|
|
210
|
-
return false;
|
|
211
|
-
if (state.currentId === id)
|
|
102
|
+
export function shouldShowTestsBar(run, tests) {
|
|
103
|
+
if (tests.length > 0)
|
|
212
104
|
return true;
|
|
213
|
-
|
|
105
|
+
if (run.running || run.error != null || run.outcome != null)
|
|
106
|
+
return true;
|
|
107
|
+
return Object.keys(run.results).length > 0;
|
|
214
108
|
}
|
|
215
109
|
/**
|
|
216
|
-
*
|
|
110
|
+
* Derive everything the bar shows from the run state.
|
|
217
111
|
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return item.title?.trim() || item.file;
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Whether a written path is a test file, so the bar can re-list the moment the
|
|
226
|
-
* agent writes a NEW spec instead of only on the next run or reload. Matches
|
|
227
|
-
* the same `*.spec.*` / `*.test.*` shape the host's discovery looks for, so a
|
|
228
|
-
* write that cannot change the list never costs a listing.
|
|
112
|
+
* The tone is deliberately NOT "whatever the last file did": a single failing
|
|
113
|
+
* file among twenty passing ones is a failing suite, because that is the thing
|
|
114
|
+
* the person has to act on. Running always wins, since a count that is still
|
|
115
|
+
* moving is not a verdict.
|
|
229
116
|
*
|
|
230
|
-
* @param
|
|
231
|
-
* @
|
|
117
|
+
* @param run - The chat panel's live run state.
|
|
118
|
+
* @param tests - The discovered tests, used to name the file running now.
|
|
119
|
+
* @returns The summary the bar renders.
|
|
232
120
|
*/
|
|
233
|
-
export function
|
|
234
|
-
|
|
121
|
+
export function summariseTestsBar(run, tests) {
|
|
122
|
+
let passed = 0;
|
|
123
|
+
let failed = 0;
|
|
124
|
+
let skipped = 0;
|
|
125
|
+
for (const entry of Object.values(run.results)) {
|
|
126
|
+
if (entry.status === 'passed')
|
|
127
|
+
passed++;
|
|
128
|
+
else if (entry.status === 'failed')
|
|
129
|
+
failed++;
|
|
130
|
+
else if (entry.status === 'skipped')
|
|
131
|
+
skipped++;
|
|
132
|
+
}
|
|
133
|
+
const byId = new Map(tests.map((test) => [test.id, test]));
|
|
134
|
+
const current = run.currentId ? (byId.get(run.currentId) ?? null) : null;
|
|
135
|
+
const progress = run.currentId ? run.cases[run.currentId] : undefined;
|
|
136
|
+
const currentCase = progress?.current ?? null;
|
|
137
|
+
const currentTest = currentCase
|
|
138
|
+
? currentCase.describe
|
|
139
|
+
? `${currentCase.describe} › ${currentCase.title}`
|
|
140
|
+
: currentCase.title
|
|
141
|
+
: null;
|
|
142
|
+
const done = passed + failed + skipped;
|
|
143
|
+
const remaining = run.running ? Math.max(0, run.queued.length - done) : 0;
|
|
144
|
+
const tone = run.running
|
|
145
|
+
? 'running'
|
|
146
|
+
: run.error
|
|
147
|
+
? 'error'
|
|
148
|
+
: run.outcome === 'cancelled' || run.outcome === 'skipped-by-user'
|
|
149
|
+
? 'stopped'
|
|
150
|
+
: failed > 0
|
|
151
|
+
? 'failing'
|
|
152
|
+
: passed > 0
|
|
153
|
+
? 'passing'
|
|
154
|
+
: 'idle';
|
|
155
|
+
return {
|
|
156
|
+
tone,
|
|
157
|
+
passed,
|
|
158
|
+
failed,
|
|
159
|
+
skipped,
|
|
160
|
+
remaining,
|
|
161
|
+
currentFile: current?.title ?? current?.file ?? null,
|
|
162
|
+
currentTest,
|
|
163
|
+
};
|
|
235
164
|
}
|
|
236
165
|
//# sourceMappingURL=tests-bar-utilities.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tests-bar-utilities.js","sourceRoot":"","sources":["../../src/components/tests-bar-utilities.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tests-bar-utilities.js","sourceRoot":"","sources":["../../src/components/tests-bar-utilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -77,33 +77,94 @@ export declare function isSkippedByUser(output: unknown): boolean;
|
|
|
77
77
|
* @returns A brief summary string describing the result.
|
|
78
78
|
*/
|
|
79
79
|
export declare function toolSummary(name: string, output: ToolOutput, status: string): string;
|
|
80
|
+
/** A single `ask_user` option after coercion — label is always safe as a React child. */
|
|
81
|
+
export interface AskUserOption {
|
|
82
|
+
/** The clickable answer text — also the string sent back as the response. */
|
|
83
|
+
label: string;
|
|
84
|
+
/** One-line explanation rendered under the label (rich options only). */
|
|
85
|
+
description?: string;
|
|
86
|
+
/** Markdown artifact shown side-by-side for comparing options (rich options only). */
|
|
87
|
+
preview?: string;
|
|
88
|
+
}
|
|
80
89
|
/** The `ask_user` tool input, after coercion — every field safe to render. */
|
|
81
90
|
export interface AskUserInput {
|
|
82
91
|
/** The question text (markdown). */
|
|
83
92
|
question: string;
|
|
84
|
-
/** Clickable answers
|
|
85
|
-
options:
|
|
93
|
+
/** Clickable answers; a plain string or a rich { label, description?, preview? }. */
|
|
94
|
+
options: AskUserOption[];
|
|
95
|
+
/** Checkboxes — several options may be chosen at once. */
|
|
96
|
+
multiSelect: boolean;
|
|
86
97
|
/** Whether the free-text box is offered. `undefined` means "model didn't say" (defaults on). */
|
|
87
98
|
allowFreeText: boolean | undefined;
|
|
88
99
|
/** Optional hint shown under the options. */
|
|
89
100
|
hint: string;
|
|
101
|
+
/** Present only on the plan-approval card — renders the rich review layout. */
|
|
102
|
+
planReview: AskUserPlanReview | undefined;
|
|
103
|
+
}
|
|
104
|
+
/** Plan-review metadata carried by the plan-approval ask_user card. */
|
|
105
|
+
export interface AskUserPlanReview {
|
|
106
|
+
/** Plan file path relative to the workspace (clickable in the card). */
|
|
107
|
+
path: string | null;
|
|
108
|
+
/** The plan's display name, when the model gave one. */
|
|
109
|
+
name: string | null;
|
|
110
|
+
/** Total checklist steps in the plan. */
|
|
111
|
+
steps: number;
|
|
112
|
+
/** First few checklist step texts, for the in-card preview. */
|
|
113
|
+
preview: string[];
|
|
90
114
|
}
|
|
91
115
|
/**
|
|
92
116
|
* Normalize raw `ask_user` tool input into renderable strings.
|
|
93
117
|
*
|
|
94
|
-
* The model is told `options` is
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
118
|
+
* The model is told `options` is a list of strings or `{ label, description?,
|
|
119
|
+
* preview? }` objects, and weaker models routinely send stranger shapes —
|
|
120
|
+
* `[{ label, value }]`, nested arrays, quote-escaped pseudo-JSON. Rendering one
|
|
121
|
+
* of those directly is React error #31, which crashes the entire IDE at the
|
|
122
|
+
* moment the user submits their first prompt. Everything the card renders goes
|
|
123
|
+
* through here.
|
|
98
124
|
*
|
|
99
125
|
* @param input - The raw tool input, straight off the model.
|
|
100
126
|
* @returns The same fields, coerced so each is safe as a React child.
|
|
101
127
|
*/
|
|
102
128
|
export declare function normalizeAskUserInput(input: unknown): AskUserInput;
|
|
129
|
+
/** One row of an `update_task_list` call, after coercion — safe to render. */
|
|
130
|
+
export interface TaskListRow {
|
|
131
|
+
content: string;
|
|
132
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
133
|
+
priority?: 'high' | 'medium' | 'low';
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Coerce raw `update_task_list` input into renderable rows. The input comes
|
|
137
|
+
* straight off the model — every field is degraded to a safe default rather
|
|
138
|
+
* than rendered raw (same contract as `normalizeAskUserInput`).
|
|
139
|
+
*
|
|
140
|
+
* @param input - The raw tool input.
|
|
141
|
+
* @returns The rows worth rendering; empty when the model sent nothing usable.
|
|
142
|
+
*/
|
|
143
|
+
export declare function normalizeTaskListInput(input: unknown): TaskListRow[];
|
|
144
|
+
/** A parsed judge-subagent verdict. */
|
|
145
|
+
export interface JudgeVerdict {
|
|
146
|
+
verdict: 'PASS' | 'FAIL';
|
|
147
|
+
/** Concrete failure lines (the `- one line per failure` block under ISSUES:). */
|
|
148
|
+
issues: string[];
|
|
149
|
+
/** The report with the verdict scaffold stripped, for the expandable body. */
|
|
150
|
+
rest: string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Parse a judge subagent's report into a structured verdict.
|
|
154
|
+
*
|
|
155
|
+
* The judge system prompt fixes the shape (`VERDICT: PASS|FAIL` then optional
|
|
156
|
+
* `ISSUES:` bullets then per-criterion evidence), but the model is the author —
|
|
157
|
+
* parse defensively (case-insensitive, leading whitespace tolerated) and return
|
|
158
|
+
* `null` when no verdict line is present so the card renders the plain report.
|
|
159
|
+
*
|
|
160
|
+
* @param report - The judge subagent's final report text.
|
|
161
|
+
* @returns The structured verdict, or null when the report carries none.
|
|
162
|
+
*/
|
|
163
|
+
export declare function parseJudgeVerdict(report: string): JudgeVerdict | null;
|
|
103
164
|
/**
|
|
104
165
|
* Count truly added/removed lines between two line arrays using LCS.
|
|
105
166
|
* @param oldLines - The original lines array.
|
|
106
|
-
* @param
|
|
167
|
+
* @param modifiedLines - The modified lines array.
|
|
107
168
|
* @returns An object with the number of added and removed lines.
|
|
108
169
|
*/
|
|
109
170
|
export declare function diffLineCount(oldLines: string[], newLines: string[]): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-call-utilities.d.ts","sourceRoot":"","sources":["../../src/components/tool-call-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,6BAA6B;AAC7B,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;AAE5E;;;;;;;;;;;;GAYG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAItD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOtD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGzD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAK9E;AAOD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"tool-call-utilities.d.ts","sourceRoot":"","sources":["../../src/components/tool-call-utilities.ts"],"names":[],"mappings":"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"}
|