@lotics/ui 22.2.0 → 22.3.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/docs/ai_patterns.md +5 -3
- package/package.json +1 -1
- package/src/agent_run.tsx +36 -21
package/docs/ai_patterns.md
CHANGED
|
@@ -174,9 +174,11 @@ that tool's `output-error` part and flows like a normal call — the amber dot m
|
|
|
174
174
|
group's header goes amber too), the reason waits in the expanded Error panel; real runs retry and
|
|
175
175
|
move on, so the feed doesn't dramatize it. A BREAKING error that terminates the whole run lives
|
|
176
176
|
OUTSIDE `parts` (chat persists it in the message's `errors`; `useAgentRun().error` carries it) —
|
|
177
|
-
pass it as the `error` prop and it
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
pass it as the `error` prop and it terminates the feed with an error `Callout` — a contained,
|
|
178
|
+
tinted panel rather than another step row, because the run did not advance, it stopped, and it
|
|
179
|
+
carries `role="alert"` so a screen reader announces it. Pass **`onRetry`** alongside it and a Retry
|
|
180
|
+
action (a secondary `Button`) sits INSIDE that panel so the operator can re-fire the run; omit it
|
|
181
|
+
and the panel carries the message alone.
|
|
180
182
|
|
|
181
183
|
**In a bounded container, wrap it in `FollowScroll`.** An `AgentRun` streaming inside a dialog,
|
|
182
184
|
drawer, or fixed-height panel grows BELOW the fold — a plain scroll container doesn't follow. Wrap
|
package/package.json
CHANGED
package/src/agent_run.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { colors } from "./colors";
|
|
|
4
4
|
import { Text } from "./text";
|
|
5
5
|
import { Button } from "./button";
|
|
6
6
|
import { Icon, type IconName } from "./icon";
|
|
7
|
+
import { Callout, CalloutActions, CalloutText } from "./callout";
|
|
7
8
|
import { Markdown } from "./markdown";
|
|
8
9
|
import { JsonPanel, stringifyData } from "./json_panel";
|
|
9
10
|
import { PressableHighlight } from "./pressable_highlight";
|
|
@@ -187,27 +188,44 @@ export function AgentRun(props: AgentRunProps) {
|
|
|
187
188
|
/>
|
|
188
189
|
);
|
|
189
190
|
})}
|
|
190
|
-
{/* A run-level BREAKING error terminates the feed
|
|
191
|
-
|
|
192
|
-
A
|
|
191
|
+
{/* A run-level BREAKING error terminates the feed. It lives outside `parts`
|
|
192
|
+
(the stream failed), so the caller passes it explicitly.
|
|
193
|
+
A CONTAINED surface, not another step row: the run didn't advance, it
|
|
194
|
+
stopped, and a tinted panel says that at a glance where a bare red line
|
|
195
|
+
in the step gutter reads as one more step that happened to fail. It also
|
|
196
|
+
gives the retry a container — free-floating, a full-weight button in a
|
|
197
|
+
column of text reads as a stray control — and `Callout` carries
|
|
198
|
+
`role="alert"`, which the plain row did not.
|
|
199
|
+
FULL WIDTH, unlike `reasoning` / `rowDetail`: those indent to a step's
|
|
200
|
+
text column because they are that step's sub-content. This hangs under
|
|
201
|
+
no step — it is the whole run ending — so indenting it would make a
|
|
202
|
+
run-level failure read as the last step's detail. */}
|
|
193
203
|
{props.error ? (
|
|
194
|
-
<
|
|
195
|
-
<
|
|
196
|
-
<View style={styles.dotCol}>
|
|
197
|
-
<Icon name="circle-alert" size={17} color={colors.red[500]} />
|
|
198
|
-
</View>
|
|
199
|
-
<View style={styles.rowBody}>
|
|
200
|
-
<Text size="sm" color="danger">
|
|
201
|
-
{props.error}
|
|
202
|
-
</Text>
|
|
203
|
-
</View>
|
|
204
|
-
</View>
|
|
204
|
+
<Callout tone="error">
|
|
205
|
+
<CalloutText>{props.error}</CalloutText>
|
|
205
206
|
{onRetry ? (
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
<CalloutActions>
|
|
208
|
+
{/* PRIMARY, deliberately. `Callout` is a calm panel by design (a
|
|
209
|
+
50 tint behind a soft 100 border), so a filled button inside it
|
|
210
|
+
is not emphasis twice — it is the one action on a quiet
|
|
211
|
+
surface. Every unfilled variant loses here: default and muted
|
|
212
|
+
hover to zinc-100, a grey wash over the red tint, and
|
|
213
|
+
danger-secondary puts red ink on a red-50 ground, the weakest
|
|
214
|
+
contrast of the options. The run just died; the only way out
|
|
215
|
+
should be the most legible thing in the panel.
|
|
216
|
+
Still a Button, never a link: a link navigates, this re-fires a
|
|
217
|
+
run, and that distinction is what a screen reader and the
|
|
218
|
+
keyboard both rely on. */}
|
|
219
|
+
<Button
|
|
220
|
+
title={locale.agentRun.retry}
|
|
221
|
+
color="primary"
|
|
222
|
+
icon="rotate-ccw"
|
|
223
|
+
alignSelf="flex-start"
|
|
224
|
+
onPress={onRetry}
|
|
225
|
+
/>
|
|
226
|
+
</CalloutActions>
|
|
209
227
|
) : null}
|
|
210
|
-
</
|
|
228
|
+
</Callout>
|
|
211
229
|
) : null}
|
|
212
230
|
</View>
|
|
213
231
|
);
|
|
@@ -486,7 +504,4 @@ const styles = StyleSheet.create({
|
|
|
486
504
|
reasoning: { paddingLeft: 28, paddingBottom: 4 },
|
|
487
505
|
// A step's expanded I/O panels — same left edge as the reasoning body.
|
|
488
506
|
rowDetail: { paddingLeft: 28, paddingBottom: 6, paddingTop: 2 },
|
|
489
|
-
// The retry action under the terminal error — aligned to the message body
|
|
490
|
-
// (past the dot column + its gap), so it reads as a response to that row.
|
|
491
|
-
retry: { paddingLeft: 28 },
|
|
492
507
|
});
|