@lotics/ui 7.19.2 → 8.0.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/AGENTS.md +128 -92
- package/examples/tpl_dieline.tsx +3 -3
- package/examples/tpl_documents.tsx +790 -0
- package/examples/tpl_lookup.tsx +37 -10
- package/examples/tpl_task_board.tsx +32 -19
- package/examples/tpl_tasks.tsx +32 -19
- package/package.json +2 -9
- package/src/agent_run.tsx +1 -1
- package/src/change_review.tsx +732 -236
- package/src/composer.tsx +22 -1
- package/src/confidence.tsx +1 -1
- package/src/control_surface.ts +0 -14
- package/src/finding.tsx +112 -80
- package/src/floating_action_bar.tsx +1 -1
- package/src/locale.tsx +22 -16
- package/src/sources.tsx +8 -5
- package/src/use_option_list.test.ts +39 -0
- package/src/use_option_list.ts +5 -2
- package/examples/tpl_assistant.tsx +0 -174
- package/examples/tpl_briefing.tsx +0 -121
- package/examples/tpl_compare.tsx +0 -133
- package/examples/tpl_crosscheck.tsx +0 -120
- package/examples/tpl_draft.tsx +0 -163
- package/examples/tpl_extract.tsx +0 -193
- package/examples/tpl_match.tsx +0 -134
- package/examples/tpl_ratedesk.tsx +0 -386
- package/examples/tpl_triage.tsx +0 -112
- package/src/discrepancy.tsx +0 -114
- package/src/match_sides.tsx +0 -79
- package/src/record_fields.tsx +0 -68
- package/src/review_card.tsx +0 -172
- package/src/scored_option.tsx +0 -138
- package/src/spec_list.tsx +0 -81
- package/src/triage_row.tsx +0 -99
package/examples/tpl_lookup.tsx
CHANGED
|
@@ -7,7 +7,6 @@ import { Callout, CalloutText, CalloutTitle } from "@lotics/ui/callout";
|
|
|
7
7
|
import { PressableHighlight } from "@lotics/ui/pressable_highlight";
|
|
8
8
|
import { Composer } from "@lotics/ui/composer";
|
|
9
9
|
import { AgentRun, type AgentRunStep, type AgentRunItem } from "@lotics/ui/agent_run";
|
|
10
|
-
import { SpecList, type SpecRow } from "@lotics/ui/spec_list";
|
|
11
10
|
import { Confidence, type ConfidenceLevel } from "@lotics/ui/confidence";
|
|
12
11
|
import { Badge } from "@lotics/ui/badge";
|
|
13
12
|
import { Sources, type SourceRef } from "@lotics/ui/sources";
|
|
@@ -19,7 +18,7 @@ import { Sources, type SourceRef } from "@lotics/ui/sources";
|
|
|
19
18
|
// single confident verdict: classification is ambiguous, so the alternatives are
|
|
20
19
|
// first-class (the prep/pack push the goods to a different code with a different
|
|
21
20
|
// duty). The answer is a panel of scannable components — the code, the exact duty
|
|
22
|
-
// breakdown (
|
|
21
|
+
// breakdown (hand-composed spec rows), the policies, the sources. Refine the description ("what
|
|
23
22
|
// if it's pre-cooked?") and the ranking updates. Same shape for any
|
|
24
23
|
// look-up-and-explain: tariff/HS, fee lookup, policy Q&A, a spec/compliance desk.
|
|
25
24
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -46,7 +45,6 @@ interface Candidate {
|
|
|
46
45
|
// One query, several plausible HS codes — the agent RANKS them; the declarant
|
|
47
46
|
// picks. The prep and the pack push the goods to a different code with a
|
|
48
47
|
// different duty, which is exactly why a single confident verdict is wrong.
|
|
49
|
-
const QUERY = "Black tiger shrimp, headless shell-on, IQF frozen, 1 kg retail packs";
|
|
50
48
|
|
|
51
49
|
const CANDIDATES: Candidate[] = [
|
|
52
50
|
{
|
|
@@ -204,9 +202,11 @@ export function TplLookup() {
|
|
|
204
202
|
{/* current run */}
|
|
205
203
|
<AgentRun items={items} state={streaming ? "streaming" : "done"} />
|
|
206
204
|
|
|
205
|
+
{/* Matches surface only once the run settles — the agent's output,
|
|
206
|
+
never a pre-filled list; they sit at the bottom, under the run. */}
|
|
207
|
+
{phase === "ready" ? (
|
|
207
208
|
<View style={{ gap: 8 }}>
|
|
208
209
|
<Text size="xs" color="muted" weight="medium">Nearest matches</Text>
|
|
209
|
-
<Text size="xs" color="muted" numberOfLines={2}>{QUERY}</Text>
|
|
210
210
|
{CANDIDATES.map((c) => (
|
|
211
211
|
<PressableHighlight
|
|
212
212
|
key={c.id}
|
|
@@ -231,6 +231,7 @@ export function TplLookup() {
|
|
|
231
231
|
</PressableHighlight>
|
|
232
232
|
))}
|
|
233
233
|
</View>
|
|
234
|
+
) : null}
|
|
234
235
|
</ScrollView>
|
|
235
236
|
|
|
236
237
|
<View style={{ padding: 12, borderTopWidth: 1, borderTopColor: colors.zinc[200] }}>
|
|
@@ -247,9 +248,9 @@ export function TplLookup() {
|
|
|
247
248
|
{/* ── RIGHT · the pinned structured answer ───────────────────── */}
|
|
248
249
|
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 28, paddingBottom: 48 }}>
|
|
249
250
|
<View style={{ width: "100%", maxWidth: 720, alignSelf: "center", gap: 16 }}>
|
|
250
|
-
<View style={{
|
|
251
|
-
{/* verdict header */}
|
|
252
|
-
<View style={{
|
|
251
|
+
<View style={{ gap: 4 }}>
|
|
252
|
+
{/* verdict header — open, no card box: the panel IS the answer */}
|
|
253
|
+
<View style={{ paddingVertical: 6, gap: 10 }}>
|
|
253
254
|
<View style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
|
|
254
255
|
<Text size="xs" color="muted" weight="medium" style={{ flex: 1 }}>Suggested HS code</Text>
|
|
255
256
|
<Confidence level={active.confidence} />
|
|
@@ -258,21 +259,22 @@ export function TplLookup() {
|
|
|
258
259
|
<Text size="sm" color="muted">{active.heading}</Text>
|
|
259
260
|
</View>
|
|
260
261
|
|
|
261
|
-
<
|
|
262
|
+
<Divider />
|
|
263
|
+
<View style={{ paddingVertical: 16, gap: 18 }}>
|
|
262
264
|
<View style={{ borderLeftWidth: 2, borderLeftColor: colors.zinc[300], paddingLeft: 12 }}>
|
|
263
265
|
<Text size="sm" color="muted">{active.basis}</Text>
|
|
264
266
|
</View>
|
|
265
267
|
|
|
266
268
|
<View style={{ gap: 8 }}>
|
|
267
269
|
<Text size="sm" weight="semibold">Duty & tax</Text>
|
|
268
|
-
<
|
|
270
|
+
<SpecRows rows={active.duty} total={active.dutyTotal} />
|
|
269
271
|
</View>
|
|
270
272
|
|
|
271
273
|
<Divider />
|
|
272
274
|
|
|
273
275
|
<View style={{ gap: 8 }}>
|
|
274
276
|
<Text size="sm" weight="semibold">Classification basis</Text>
|
|
275
|
-
<
|
|
277
|
+
<SpecRows rows={active.specs} dense />
|
|
276
278
|
</View>
|
|
277
279
|
|
|
278
280
|
{active.policies.length > 0 ? (
|
|
@@ -300,3 +302,28 @@ export function TplLookup() {
|
|
|
300
302
|
</View>
|
|
301
303
|
);
|
|
302
304
|
}
|
|
305
|
+
|
|
306
|
+
// The structured label → value breakdown behind the answer — the duty table,
|
|
307
|
+
// the classification basis. Hand-composed two-column rows: hierarchy from
|
|
308
|
+
// weight and tabular figures; the total pins under a divider.
|
|
309
|
+
interface SpecRow { label: string; value: string }
|
|
310
|
+
|
|
311
|
+
function SpecRows({ rows, total, dense }: { rows: SpecRow[]; total?: SpecRow; dense?: boolean }) {
|
|
312
|
+
const line = (row: SpecRow, isTotal?: boolean) => (
|
|
313
|
+
<View key={row.label} style={{ flexDirection: "row", alignItems: "baseline", justifyContent: "space-between", gap: 16, minHeight: dense ? 26 : 32 }}>
|
|
314
|
+
<Text size={dense ? "xs" : "sm"} color={isTotal ? "default" : "muted"} weight={isTotal ? "semibold" : "regular"} numberOfLines={1} style={{ flexShrink: 1 }}>{row.label}</Text>
|
|
315
|
+
<Text size={dense && !isTotal ? "sm" : "md"} weight={isTotal ? "semibold" : "medium"} tabular>{row.value}</Text>
|
|
316
|
+
</View>
|
|
317
|
+
);
|
|
318
|
+
return (
|
|
319
|
+
<View>
|
|
320
|
+
{rows.map((r) => line(r))}
|
|
321
|
+
{total ? (
|
|
322
|
+
<>
|
|
323
|
+
<Divider paddingVertical={dense ? 5 : 7} />
|
|
324
|
+
{line(total, true)}
|
|
325
|
+
</>
|
|
326
|
+
) : null}
|
|
327
|
+
</View>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
@@ -28,7 +28,7 @@ import { DataGrid, gridRowStyle, type DataGridColumn, type DataGridGroup } from
|
|
|
28
28
|
import { cycleSort, sortBy, type SortState } from "@lotics/ui/sort_header";
|
|
29
29
|
import { Composer } from "@lotics/ui/composer";
|
|
30
30
|
import { AgentRun, type AgentRunItem } from "@lotics/ui/agent_run";
|
|
31
|
-
import { ChangeReview, ChangeReviewActions, type
|
|
31
|
+
import { Change, ChangeReview, ChangeReviewActions, ChangeReviewHeader, ChangeSummary, type ChangeStatus } from "@lotics/ui/change_review";
|
|
32
32
|
import { Dialog, DialogHeader, DialogHeaderTitle, DialogScrollArea, DialogFooter } from "@lotics/ui/dialog";
|
|
33
33
|
import { CompletionState } from "@lotics/ui/completion_state";
|
|
34
34
|
import { Confidence, type ConfidenceLevel } from "@lotics/ui/confidence";
|
|
@@ -225,7 +225,7 @@ export function TplTaskBoard() {
|
|
|
225
225
|
const [phase, setPhase] = useState<Phase>("idle");
|
|
226
226
|
const [revealed, setRevealed] = useState(0);
|
|
227
227
|
const [proposals, setProposals] = useState<Proposal[]>([]);
|
|
228
|
-
const [decisions, setDecisions] = useState<Record<string,
|
|
228
|
+
const [decisions, setDecisions] = useState<Record<string, ChangeStatus>>({});
|
|
229
229
|
const [addedCount, setAddedCount] = useState(0);
|
|
230
230
|
|
|
231
231
|
const startDraft = useCallback(() => { setRevealed(0); setPhase("reading"); }, []);
|
|
@@ -233,7 +233,7 @@ export function TplTaskBoard() {
|
|
|
233
233
|
const closeDraft = useCallback(() => { setDraftOpen(false); resetDraft(); }, [resetDraft]);
|
|
234
234
|
const editProposal = useCallback((id: string, p: Partial<Proposal>) =>
|
|
235
235
|
setProposals((ps) => ps.map((x) => (x.id === id ? { ...x, ...p } : x))), []);
|
|
236
|
-
const decide = useCallback((id: string, status:
|
|
236
|
+
const decide = useCallback((id: string, status: ChangeStatus | null) =>
|
|
237
237
|
setDecisions((dec) => { const n = { ...dec }; if (status) n[id] = status; else delete n[id]; return n; }), []);
|
|
238
238
|
const acceptedCount = proposals.filter((p) => decisions[p.id] === "accepted").length;
|
|
239
239
|
const addAccepted = useCallback(() => {
|
|
@@ -371,7 +371,10 @@ export function TplTaskBoard() {
|
|
|
371
371
|
</View>
|
|
372
372
|
</ScrollView>
|
|
373
373
|
|
|
374
|
-
{/* Draft from notes — Composer → AgentRun → ChangeReview → commit (adds tasks).
|
|
374
|
+
{/* Draft from notes — Composer → AgentRun → ChangeReview → commit (adds tasks).
|
|
375
|
+
The review provider wraps the WHOLE dialog so the `Change`s (scroll area)
|
|
376
|
+
and the commit bar (`DialogFooter`) share one review context. */}
|
|
377
|
+
<ChangeReview>
|
|
375
378
|
<Dialog open={draftOpen} onOpenChange={(o) => { if (!o) closeDraft(); }} maxWidth={620}>
|
|
376
379
|
<DialogHeader><DialogHeaderTitle>Draft from notes</DialogHeaderTitle></DialogHeader>
|
|
377
380
|
<DialogScrollArea>
|
|
@@ -383,20 +386,29 @@ export function TplTaskBoard() {
|
|
|
383
386
|
) : null}
|
|
384
387
|
{phase === "reading" ? <AgentRun items={runItems} state={revealed >= DRAFT_STEPS.length ? "done" : "streaming"} /> : null}
|
|
385
388
|
{phase === "review" ? (
|
|
386
|
-
<
|
|
387
|
-
title="Drafted tasks"
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
389
|
+
<View style={{ gap: 8 }}>
|
|
390
|
+
<ChangeReviewHeader title="Drafted tasks" />
|
|
391
|
+
<Text size="sm" color="muted">{`${proposals.length} from your notes — keep, edit, or drop each. A “Low” mark is worth a glance.`}</Text>
|
|
392
|
+
{proposals.map((p) => {
|
|
393
|
+
const status = decisions[p.id] ?? "pending";
|
|
394
|
+
const kept = status === "accepted";
|
|
395
|
+
return (
|
|
396
|
+
<Change
|
|
397
|
+
key={p.id}
|
|
398
|
+
id={p.id}
|
|
399
|
+
status={status}
|
|
400
|
+
onAccept={() => decide(p.id, "accepted")}
|
|
401
|
+
onReject={() => decide(p.id, "rejected")}
|
|
402
|
+
onUndo={() => decide(p.id, null)}
|
|
403
|
+
>
|
|
404
|
+
<TaskProposal proposal={p} onEdit={editProposal} />
|
|
405
|
+
<ChangeSummary>
|
|
406
|
+
<Text size="sm" numberOfLines={1} color={kept ? "default" : "muted"} style={kept ? undefined : { textDecorationLine: "line-through" }}>{p.title}</Text>
|
|
407
|
+
</ChangeSummary>
|
|
408
|
+
</Change>
|
|
409
|
+
);
|
|
410
|
+
})}
|
|
411
|
+
</View>
|
|
400
412
|
) : null}
|
|
401
413
|
{phase === "done" ? (
|
|
402
414
|
<CompletionState title={`${addedCount} ${addedCount === 1 ? "task" : "tasks"} added`} summary="They're on the board now." />
|
|
@@ -404,7 +416,7 @@ export function TplTaskBoard() {
|
|
|
404
416
|
</DialogScrollArea>
|
|
405
417
|
{phase === "review" ? (
|
|
406
418
|
<DialogFooter>
|
|
407
|
-
<ChangeReviewActions
|
|
419
|
+
<ChangeReviewActions onApply={addAccepted} onDiscard={resetDraft} applyLabel={`Add ${acceptedCount} ${acceptedCount === 1 ? "task" : "tasks"}`} />
|
|
408
420
|
</DialogFooter>
|
|
409
421
|
) : phase === "done" ? (
|
|
410
422
|
<DialogFooter>
|
|
@@ -413,6 +425,7 @@ export function TplTaskBoard() {
|
|
|
413
425
|
</DialogFooter>
|
|
414
426
|
) : null}
|
|
415
427
|
</Dialog>
|
|
428
|
+
</ChangeReview>
|
|
416
429
|
</>
|
|
417
430
|
);
|
|
418
431
|
}
|
package/examples/tpl_tasks.tsx
CHANGED
|
@@ -18,7 +18,7 @@ import { FilesEditor } from "@lotics/ui/files_editor";
|
|
|
18
18
|
import type { DisplayFile } from "@lotics/ui/file_thumbnail";
|
|
19
19
|
import { Composer } from "@lotics/ui/composer";
|
|
20
20
|
import { AgentRun, type AgentRunItem } from "@lotics/ui/agent_run";
|
|
21
|
-
import { ChangeReview, ChangeReviewActions, type
|
|
21
|
+
import { Change, ChangeReview, ChangeReviewActions, ChangeReviewHeader, ChangeSummary, type ChangeStatus } from "@lotics/ui/change_review";
|
|
22
22
|
import { Dialog, DialogHeader, DialogHeaderTitle, DialogScrollArea, DialogFooter } from "@lotics/ui/dialog";
|
|
23
23
|
import { CompletionState } from "@lotics/ui/completion_state";
|
|
24
24
|
import { Confidence, type ConfidenceLevel } from "@lotics/ui/confidence";
|
|
@@ -160,7 +160,7 @@ export function TplTasks() {
|
|
|
160
160
|
const [phase, setPhase] = useState<Phase>("idle");
|
|
161
161
|
const [revealed, setRevealed] = useState(0);
|
|
162
162
|
const [proposals, setProposals] = useState<Proposal[]>([]);
|
|
163
|
-
const [decisions, setDecisions] = useState<Record<string,
|
|
163
|
+
const [decisions, setDecisions] = useState<Record<string, ChangeStatus>>({});
|
|
164
164
|
const [addedCount, setAddedCount] = useState(0);
|
|
165
165
|
|
|
166
166
|
const patch = (id: string, next: Partial<Task>) =>
|
|
@@ -182,7 +182,7 @@ export function TplTasks() {
|
|
|
182
182
|
const closeDraft = useCallback(() => { setDraftOpen(false); resetDraft(); }, [resetDraft]);
|
|
183
183
|
const editProposal = useCallback((id: string, p: Partial<Proposal>) =>
|
|
184
184
|
setProposals((ps) => ps.map((x) => (x.id === id ? { ...x, ...p } : x))), []);
|
|
185
|
-
const decide = useCallback((id: string, status:
|
|
185
|
+
const decide = useCallback((id: string, status: ChangeStatus | null) =>
|
|
186
186
|
setDecisions((dec) => { const n = { ...dec }; if (status) n[id] = status; else delete n[id]; return n; }), []);
|
|
187
187
|
const acceptedCount = proposals.filter((p) => decisions[p.id] === "accepted").length;
|
|
188
188
|
const addAccepted = useCallback(() => {
|
|
@@ -345,7 +345,10 @@ export function TplTasks() {
|
|
|
345
345
|
</View>
|
|
346
346
|
</ScrollView>
|
|
347
347
|
|
|
348
|
-
{/* Draft from notes — Composer → AgentRun → ChangeReview → commit.
|
|
348
|
+
{/* Draft from notes — Composer → AgentRun → ChangeReview → commit. The review
|
|
349
|
+
provider wraps the WHOLE dialog so the `Change`s (scroll area) and the
|
|
350
|
+
commit bar (`DialogFooter`) share one review context. */}
|
|
351
|
+
<ChangeReview>
|
|
349
352
|
<Dialog open={draftOpen} onOpenChange={(o) => { if (!o) closeDraft(); }} maxWidth={620}>
|
|
350
353
|
<DialogHeader><DialogHeaderTitle>Draft from notes</DialogHeaderTitle></DialogHeader>
|
|
351
354
|
<DialogScrollArea>
|
|
@@ -357,20 +360,29 @@ export function TplTasks() {
|
|
|
357
360
|
) : null}
|
|
358
361
|
{phase === "reading" ? <AgentRun items={runItems} state={revealed >= DRAFT_STEPS.length ? "done" : "streaming"} /> : null}
|
|
359
362
|
{phase === "review" ? (
|
|
360
|
-
<
|
|
361
|
-
title="Drafted tasks"
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
363
|
+
<View style={{ gap: 8 }}>
|
|
364
|
+
<ChangeReviewHeader title="Drafted tasks" />
|
|
365
|
+
<Text size="sm" color="muted">{`${proposals.length} from your notes — keep, edit, or drop each. A “Low” mark is worth a glance.`}</Text>
|
|
366
|
+
{proposals.map((p) => {
|
|
367
|
+
const status = decisions[p.id] ?? "pending";
|
|
368
|
+
const kept = status === "accepted";
|
|
369
|
+
return (
|
|
370
|
+
<Change
|
|
371
|
+
key={p.id}
|
|
372
|
+
id={p.id}
|
|
373
|
+
status={status}
|
|
374
|
+
onAccept={() => decide(p.id, "accepted")}
|
|
375
|
+
onReject={() => decide(p.id, "rejected")}
|
|
376
|
+
onUndo={() => decide(p.id, null)}
|
|
377
|
+
>
|
|
378
|
+
<TaskProposal proposal={p} onEdit={editProposal} />
|
|
379
|
+
<ChangeSummary>
|
|
380
|
+
<Text size="sm" numberOfLines={1} color={kept ? "default" : "muted"} style={kept ? undefined : { textDecorationLine: "line-through" }}>{p.title}</Text>
|
|
381
|
+
</ChangeSummary>
|
|
382
|
+
</Change>
|
|
383
|
+
);
|
|
384
|
+
})}
|
|
385
|
+
</View>
|
|
374
386
|
) : null}
|
|
375
387
|
{phase === "done" ? (
|
|
376
388
|
<CompletionState title={`${addedCount} ${addedCount === 1 ? "task" : "tasks"} added`} summary="They're in your list, grouped by due date." />
|
|
@@ -378,7 +390,7 @@ export function TplTasks() {
|
|
|
378
390
|
</DialogScrollArea>
|
|
379
391
|
{phase === "review" ? (
|
|
380
392
|
<DialogFooter>
|
|
381
|
-
<ChangeReviewActions
|
|
393
|
+
<ChangeReviewActions onApply={addAccepted} onDiscard={resetDraft} applyLabel={`Add ${acceptedCount} ${acceptedCount === 1 ? "task" : "tasks"}`} />
|
|
382
394
|
</DialogFooter>
|
|
383
395
|
) : phase === "done" ? (
|
|
384
396
|
<DialogFooter>
|
|
@@ -387,6 +399,7 @@ export function TplTasks() {
|
|
|
387
399
|
</DialogFooter>
|
|
388
400
|
) : null}
|
|
389
401
|
</Dialog>
|
|
402
|
+
</ChangeReview>
|
|
390
403
|
</>
|
|
391
404
|
);
|
|
392
405
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lotics/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./tokens": "./src/tokens.ts",
|
|
@@ -81,18 +81,11 @@
|
|
|
81
81
|
},
|
|
82
82
|
"./markdown.css": "./src/markdown.css",
|
|
83
83
|
"./confidence": "./src/confidence.tsx",
|
|
84
|
-
"./review_card": "./src/review_card.tsx",
|
|
85
84
|
"./change_review": "./src/change_review.tsx",
|
|
85
|
+
"./finding": "./src/finding.tsx",
|
|
86
86
|
"./clarify": "./src/clarify.tsx",
|
|
87
87
|
"./choice_list": "./src/choice_list.tsx",
|
|
88
88
|
"./sources": "./src/sources.tsx",
|
|
89
|
-
"./record_fields": "./src/record_fields.tsx",
|
|
90
|
-
"./spec_list": "./src/spec_list.tsx",
|
|
91
|
-
"./match_sides": "./src/match_sides.tsx",
|
|
92
|
-
"./finding": "./src/finding.tsx",
|
|
93
|
-
"./discrepancy": "./src/discrepancy.tsx",
|
|
94
|
-
"./triage_row": "./src/triage_row.tsx",
|
|
95
|
-
"./scored_option": "./src/scored_option.tsx",
|
|
96
89
|
"./icon": "./src/icon.tsx",
|
|
97
90
|
"./dynamic_icon": {
|
|
98
91
|
"react-native": "./src/dynamic_icon.tsx",
|
package/src/agent_run.tsx
CHANGED
|
@@ -147,7 +147,7 @@ const INK = colors.zinc[700];
|
|
|
147
147
|
* fires (not a growing stack of dots); once prose resumes the group settles into
|
|
148
148
|
* one row — "{final action} · {n} steps" — that EXPANDS on press to the steps in
|
|
149
149
|
* between. Text segments render as prose, the last one carrying a live caret. The
|
|
150
|
-
* run always ends on the agent's text. Pair with `Composer` + `
|
|
150
|
+
* run always ends on the agent's text. Pair with `Composer` + `ChangeReview`.
|
|
151
151
|
*/
|
|
152
152
|
export function AgentRun(props: AgentRunProps) {
|
|
153
153
|
const { items, labelForTool, stepsLabel = (n) => `${n} steps`, accessibilityLabel } = props;
|