@opengeni/react-native 1.4.5-canary.37615713321001

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.
Files changed (132) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +74 -0
  3. package/dist/adapters.d.ts +53 -0
  4. package/dist/adapters.js +3 -0
  5. package/dist/adapters.js.map +1 -0
  6. package/dist/attachments.d.ts +75 -0
  7. package/dist/chunk-3VSZAQ7G.js +391 -0
  8. package/dist/chunk-3VSZAQ7G.js.map +1 -0
  9. package/dist/chunk-5ZVK7WKA.js +88 -0
  10. package/dist/chunk-5ZVK7WKA.js.map +1 -0
  11. package/dist/chunk-EEDIMY3L.js +240 -0
  12. package/dist/chunk-EEDIMY3L.js.map +1 -0
  13. package/dist/chunk-M23SDI4R.js +83 -0
  14. package/dist/chunk-M23SDI4R.js.map +1 -0
  15. package/dist/chunk-PHJBSAR3.js +2006 -0
  16. package/dist/chunk-PHJBSAR3.js.map +1 -0
  17. package/dist/environment.d.ts +19 -0
  18. package/dist/expo.d.ts +25 -0
  19. package/dist/expo.js +267 -0
  20. package/dist/expo.js.map +1 -0
  21. package/dist/index.d.ts +13 -0
  22. package/dist/index.js +3345 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/presentation.d.ts +262 -0
  25. package/dist/read-acknowledgement.d.ts +39 -0
  26. package/dist/realtime/call-events.d.ts +11 -0
  27. package/dist/realtime/call-view.d.ts +26 -0
  28. package/dist/realtime/expo-call.d.ts +11 -0
  29. package/dist/realtime/native-call.d.ts +104 -0
  30. package/dist/realtime/native-realtime.d.ts +35 -0
  31. package/dist/realtime/use-native-session-realtime.d.ts +25 -0
  32. package/dist/session-view.d.ts +87 -0
  33. package/dist/timeline/activity.d.ts +34 -0
  34. package/dist/timeline/composer.d.ts +86 -0
  35. package/dist/timeline/controls.d.ts +27 -0
  36. package/dist/timeline/decisions.d.ts +29 -0
  37. package/dist/timeline/feedback.d.ts +26 -0
  38. package/dist/timeline/icon-nodes.generated.d.ts +738 -0
  39. package/dist/timeline/icon.d.ts +11 -0
  40. package/dist/timeline/index.d.ts +32 -0
  41. package/dist/timeline/index.js +5419 -0
  42. package/dist/timeline/index.js.map +1 -0
  43. package/dist/timeline/markdown.d.ts +11 -0
  44. package/dist/timeline/markdown.js +415 -0
  45. package/dist/timeline/markdown.js.map +1 -0
  46. package/dist/timeline/message-attachments.d.ts +13 -0
  47. package/dist/timeline/message-timeline.d.ts +36 -0
  48. package/dist/timeline/model-picker.d.ts +17 -0
  49. package/dist/timeline/primitives.d.ts +85 -0
  50. package/dist/timeline/queue-dock.d.ts +19 -0
  51. package/dist/timeline/session-actions.d.ts +34 -0
  52. package/dist/timeline/session-list.d.ts +50 -0
  53. package/dist/timeline/session-screen.d.ts +35 -0
  54. package/dist/timeline/session-signals.d.ts +37 -0
  55. package/dist/timeline/sheet.d.ts +14 -0
  56. package/dist/timeline/theme.d.ts +58 -0
  57. package/dist/timeline/thinking-orb.d.ts +13 -0
  58. package/dist/timeline/turn.d.ts +80 -0
  59. package/dist/ui/attention.d.ts +14 -0
  60. package/dist/ui/cards.d.ts +21 -0
  61. package/dist/ui/composer.d.ts +21 -0
  62. package/dist/ui/format.d.ts +13 -0
  63. package/dist/ui/icons.d.ts +9 -0
  64. package/dist/ui/index.d.ts +12 -0
  65. package/dist/ui/index.js +1757 -0
  66. package/dist/ui/index.js.map +1 -0
  67. package/dist/ui/steps-sheet.d.ts +10 -0
  68. package/dist/ui/theme.d.ts +63 -0
  69. package/dist/ui/timeline.d.ts +48 -0
  70. package/dist/ui/web-tokens.gen.d.ts +90 -0
  71. package/dist/use-native-session.d.ts +40 -0
  72. package/dist/view-model.d.ts +52 -0
  73. package/dist/voice-input.d.ts +102 -0
  74. package/dist/webrtc.d.ts +9 -0
  75. package/dist/webrtc.js +19 -0
  76. package/dist/webrtc.js.map +1 -0
  77. package/expo-module.config.json +7 -0
  78. package/ios/OpenGeniCall.podspec +22 -0
  79. package/ios/OpenGeniCallAppDelegateSubscriber.swift +29 -0
  80. package/ios/OpenGeniCallCenter.swift +189 -0
  81. package/ios/OpenGeniCallModule.swift +64 -0
  82. package/package.json +93 -0
  83. package/src/adapters.ts +150 -0
  84. package/src/attachments.ts +396 -0
  85. package/src/environment.tsx +214 -0
  86. package/src/expo.ts +295 -0
  87. package/src/index.ts +98 -0
  88. package/src/presentation.ts +285 -0
  89. package/src/read-acknowledgement.ts +72 -0
  90. package/src/realtime/call-events.ts +41 -0
  91. package/src/realtime/call-view.tsx +220 -0
  92. package/src/realtime/expo-call.ts +49 -0
  93. package/src/realtime/native-call.ts +266 -0
  94. package/src/realtime/native-realtime.ts +115 -0
  95. package/src/realtime/use-native-session-realtime.ts +29 -0
  96. package/src/session-view.tsx +2251 -0
  97. package/src/timeline/activity.tsx +736 -0
  98. package/src/timeline/composer.tsx +686 -0
  99. package/src/timeline/controls.tsx +151 -0
  100. package/src/timeline/decisions.tsx +651 -0
  101. package/src/timeline/feedback.tsx +251 -0
  102. package/src/timeline/icon-nodes.generated.ts +1830 -0
  103. package/src/timeline/icon.tsx +44 -0
  104. package/src/timeline/index.ts +67 -0
  105. package/src/timeline/markdown.tsx +510 -0
  106. package/src/timeline/message-attachments.tsx +155 -0
  107. package/src/timeline/message-timeline.tsx +1042 -0
  108. package/src/timeline/model-picker.tsx +450 -0
  109. package/src/timeline/primitives.tsx +561 -0
  110. package/src/timeline/queue-dock.tsx +331 -0
  111. package/src/timeline/session-actions.tsx +379 -0
  112. package/src/timeline/session-list.tsx +338 -0
  113. package/src/timeline/session-screen.tsx +488 -0
  114. package/src/timeline/session-signals.tsx +312 -0
  115. package/src/timeline/sheet.tsx +153 -0
  116. package/src/timeline/theme.tsx +128 -0
  117. package/src/timeline/thinking-orb.tsx +93 -0
  118. package/src/timeline/turn.tsx +569 -0
  119. package/src/ui/attention.tsx +220 -0
  120. package/src/ui/cards.tsx +267 -0
  121. package/src/ui/composer.tsx +296 -0
  122. package/src/ui/format.ts +86 -0
  123. package/src/ui/icons.tsx +131 -0
  124. package/src/ui/index.ts +18 -0
  125. package/src/ui/steps-sheet.tsx +71 -0
  126. package/src/ui/theme.ts +261 -0
  127. package/src/ui/timeline.tsx +837 -0
  128. package/src/ui/web-tokens.gen.ts +94 -0
  129. package/src/use-native-session.ts +219 -0
  130. package/src/view-model.ts +485 -0
  131. package/src/voice-input.ts +382 -0
  132. package/src/webrtc.ts +30 -0
@@ -0,0 +1,1757 @@
1
+ import { useState, useMemo, useEffect } from 'react';
2
+ import { Pressable, Text, StyleSheet, View, FlatList, Modal, ScrollView, Platform, TextInput } from 'react-native';
3
+ import Animated, { LinearTransition, FadeInDown, FadeIn, useSharedValue, withRepeat, withTiming, useAnimatedStyle, FadeOutDown } from 'react-native-reanimated';
4
+ import { toolDisplayName } from '@opengeni/react/session';
5
+ import Svg, { Polyline, Path, Circle, Rect } from 'react-native-svg';
6
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
7
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
8
+ import { isLiquidGlassAvailable, GlassView } from 'expo-glass-effect';
9
+
10
+ // src/ui/timeline.tsx
11
+ function AgentIcon({
12
+ name,
13
+ size = 18,
14
+ color,
15
+ strokeWidth = 2
16
+ }) {
17
+ const common = {
18
+ stroke: color,
19
+ strokeWidth,
20
+ strokeLinecap: "round",
21
+ strokeLinejoin: "round",
22
+ fill: "none"
23
+ };
24
+ return /* @__PURE__ */ jsxs(Svg, { width: size, height: size, viewBox: "0 0 24 24", children: [
25
+ name === "terminal" ? /* @__PURE__ */ jsxs(Fragment, { children: [
26
+ /* @__PURE__ */ jsx(Polyline, { points: "4 17 10 11 4 5", ...common }),
27
+ /* @__PURE__ */ jsx(Path, { d: "M 12 19h8", ...common })
28
+ ] }) : null,
29
+ name === "search" ? /* @__PURE__ */ jsxs(Fragment, { children: [
30
+ /* @__PURE__ */ jsx(Circle, { cx: "11", cy: "11", r: "7", ...common }),
31
+ /* @__PURE__ */ jsx(Path, { d: "m20 20-3.5-3.5", ...common })
32
+ ] }) : null,
33
+ name === "edit" ? /* @__PURE__ */ jsxs(Fragment, { children: [
34
+ /* @__PURE__ */ jsx(Path, { d: "M 12 20h9", ...common }),
35
+ /* @__PURE__ */ jsx(Path, { d: "M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z", ...common })
36
+ ] }) : null,
37
+ name === "globe" ? /* @__PURE__ */ jsxs(Fragment, { children: [
38
+ /* @__PURE__ */ jsx(Circle, { cx: "12", cy: "12", r: "9", ...common }),
39
+ /* @__PURE__ */ jsx(Path, { d: "M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18", ...common })
40
+ ] }) : null,
41
+ name === "check" ? /* @__PURE__ */ jsx(Polyline, { points: "20 6 9 17 4 12", ...common }) : null,
42
+ name === "x" ? /* @__PURE__ */ jsx(Path, { d: "M18 6 6 18M6 6l12 12", ...common }) : null,
43
+ name === "chevron-right" ? /* @__PURE__ */ jsx(Polyline, { points: "9 18 15 12 9 6", ...common }) : null,
44
+ name === "chevron-down" ? /* @__PURE__ */ jsx(Polyline, { points: "6 9 12 15 18 9", ...common }) : null,
45
+ name === "sparkle" ? /* @__PURE__ */ jsx(Path, { d: "M 12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9Z", ...common }) : null,
46
+ name === "mic" ? /* @__PURE__ */ jsxs(Fragment, { children: [
47
+ /* @__PURE__ */ jsx(Rect, { x: "9", y: "2", width: "6", height: "12", rx: "3", ...common }),
48
+ /* @__PURE__ */ jsx(Path, { d: "M5 10a7 7 0 0 0 14 0M12 17v5", ...common })
49
+ ] }) : null,
50
+ name === "plus" ? /* @__PURE__ */ jsx(Path, { d: "M 12 5v14M5 12h14", ...common }) : null,
51
+ name === "arrow-up" ? /* @__PURE__ */ jsx(Path, { d: "M 12 19V5M5 12l7-7 7 7", ...common }) : null,
52
+ name === "stop" ? /* @__PURE__ */ jsx(Rect, { x: "6", y: "6", width: "12", height: "12", rx: "2", fill: color }) : null,
53
+ name === "tool" ? /* @__PURE__ */ jsx(
54
+ Path,
55
+ {
56
+ d: "M14.7 6.3a4 4 0 0 0-5.4 5.4L3 18l3 3 6.3-6.3a4 4 0 0 0 5.4-5.4l-2.6 2.6-2.4-.6-.6-2.4Z",
57
+ ...common
58
+ }
59
+ ) : null,
60
+ name === "send" ? /* @__PURE__ */ jsx(Path, { d: "m22 2-7 20-4-9-9-4Z M22 2 11 13", ...common }) : null,
61
+ name === "alert" ? /* @__PURE__ */ jsxs(Fragment, { children: [
62
+ /* @__PURE__ */ jsx(
63
+ Path,
64
+ {
65
+ d: "M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z",
66
+ ...common
67
+ }
68
+ ),
69
+ /* @__PURE__ */ jsx(Path, { d: "M 12 9v4M12 17h.01", ...common })
70
+ ] }) : null,
71
+ name === "question" ? /* @__PURE__ */ jsxs(Fragment, { children: [
72
+ /* @__PURE__ */ jsx(Circle, { cx: "12", cy: "12", r: "9", ...common }),
73
+ /* @__PURE__ */ jsx(Path, { d: "M9.1 9a3 3 0 0 1 5.8 1c0 2-3 3-3 3M12 17h.01", ...common })
74
+ ] }) : null,
75
+ name === "rocket" ? /* @__PURE__ */ jsxs(Fragment, { children: [
76
+ /* @__PURE__ */ jsx(
77
+ Path,
78
+ {
79
+ d: "M4.5 16.5c-1.5 1.3-2 5-2 5s3.7-.5 5-2c.7-.8.7-2.1-.1-2.9a2.2 2.2 0 0 0-2.9-.1Z",
80
+ ...common
81
+ }
82
+ ),
83
+ /* @__PURE__ */ jsx(
84
+ Path,
85
+ {
86
+ d: "m 12 15-3-3a22 22 0 0 1 2-4A13 13 0 0 1 22 2c0 2.7-.8 7.5-6 11a22 22 0 0 1-4 2Z",
87
+ ...common
88
+ }
89
+ )
90
+ ] }) : null
91
+ ] });
92
+ }
93
+ function toolIconName(name) {
94
+ const leaf = name.toLowerCase();
95
+ if (/exec|command|shell|bash|terminal|run/.test(leaf)) return "terminal";
96
+ if (/search|find|grep|list|query|read/.test(leaf)) return "search";
97
+ if (/patch|edit|write|create|update|save/.test(leaf)) return "edit";
98
+ if (/web|browse|fetch|http|url/.test(leaf)) return "globe";
99
+ if (/deploy|release|ship/.test(leaf)) return "rocket";
100
+ return "tool";
101
+ }
102
+ function argumentRows(args) {
103
+ if (!args || typeof args !== "object") return [];
104
+ return Object.entries(args).slice(0, 4).map(([key, value]) => [key, typeof value === "string" ? value : JSON.stringify(value)]);
105
+ }
106
+ function ActionButton(props) {
107
+ const { theme, variant } = props;
108
+ const primary = variant === "primary";
109
+ return /* @__PURE__ */ jsx(
110
+ Pressable,
111
+ {
112
+ accessibilityRole: "button",
113
+ accessibilityState: { disabled: !!props.disabled },
114
+ disabled: props.disabled,
115
+ onPress: props.onPress,
116
+ style: ({ pressed }) => ({
117
+ flex: props.flex ? 1 : void 0,
118
+ minHeight: theme.layout.target,
119
+ paddingHorizontal: 18,
120
+ borderRadius: theme.radius.control,
121
+ alignItems: "center",
122
+ justifyContent: "center",
123
+ backgroundColor: primary ? theme.colors.accent : "transparent",
124
+ borderWidth: primary ? 0 : StyleSheet.hairlineWidth * 2,
125
+ borderColor: variant === "danger" ? theme.colors.danger : theme.colors.border,
126
+ opacity: props.disabled ? 0.4 : pressed ? 0.75 : 1
127
+ }),
128
+ children: /* @__PURE__ */ jsx(
129
+ Text,
130
+ {
131
+ style: {
132
+ color: primary ? theme.colors.onAccent : variant === "danger" ? theme.colors.danger : theme.colors.text,
133
+ fontSize: theme.type.body - 1,
134
+ fontWeight: theme.type.weightStrong
135
+ },
136
+ children: props.label
137
+ }
138
+ )
139
+ }
140
+ );
141
+ }
142
+ function CardShell(props) {
143
+ const { theme } = props;
144
+ return /* @__PURE__ */ jsxs(
145
+ View,
146
+ {
147
+ style: {
148
+ marginVertical: theme.space.row,
149
+ borderRadius: theme.radius.card,
150
+ backgroundColor: theme.colors.surfaceRaised,
151
+ borderWidth: StyleSheet.hairlineWidth * 2,
152
+ borderColor: theme.colors.attention,
153
+ padding: 16,
154
+ gap: 12,
155
+ shadowColor: "#000",
156
+ shadowOpacity: theme.scheme === "light" ? 0.06 : 0,
157
+ shadowRadius: 12,
158
+ shadowOffset: { width: 0, height: 4 }
159
+ },
160
+ children: [
161
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
162
+ /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.attention, name: props.icon, size: 16 }),
163
+ /* @__PURE__ */ jsx(
164
+ Text,
165
+ {
166
+ style: {
167
+ color: theme.colors.attention,
168
+ fontSize: theme.type.small,
169
+ fontWeight: "600",
170
+ letterSpacing: 0.2
171
+ },
172
+ children: props.eyebrow
173
+ }
174
+ )
175
+ ] }),
176
+ /* @__PURE__ */ jsx(
177
+ Text,
178
+ {
179
+ style: {
180
+ color: theme.colors.text,
181
+ fontSize: theme.type.body + 1,
182
+ lineHeight: theme.type.bodyLine + 1,
183
+ fontWeight: theme.type.weightStrong
184
+ },
185
+ children: props.title
186
+ }
187
+ ),
188
+ props.children
189
+ ]
190
+ }
191
+ );
192
+ }
193
+ function ApprovalCard(props) {
194
+ const { approval, theme } = props;
195
+ const rows = argumentRows(approval.arguments);
196
+ return /* @__PURE__ */ jsxs(
197
+ CardShell,
198
+ {
199
+ eyebrow: "Needs your approval",
200
+ icon: "alert",
201
+ theme,
202
+ title: toolDisplayName(approval.name, approval.display),
203
+ children: [
204
+ rows.length ? /* @__PURE__ */ jsx(
205
+ View,
206
+ {
207
+ style: {
208
+ borderRadius: theme.radius.control,
209
+ backgroundColor: theme.colors.codeBackground,
210
+ padding: 10,
211
+ gap: 4
212
+ },
213
+ children: rows.map(([key, value]) => /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: 8 }, children: [
214
+ /* @__PURE__ */ jsx(
215
+ Text,
216
+ {
217
+ style: {
218
+ color: theme.colors.textFaint,
219
+ fontSize: theme.type.small,
220
+ fontFamily: theme.type.mono
221
+ },
222
+ children: key
223
+ }
224
+ ),
225
+ /* @__PURE__ */ jsx(
226
+ Text,
227
+ {
228
+ numberOfLines: 2,
229
+ style: {
230
+ flex: 1,
231
+ color: theme.colors.text,
232
+ fontSize: theme.type.small,
233
+ fontFamily: theme.type.mono
234
+ },
235
+ children: value
236
+ }
237
+ )
238
+ ] }, key))
239
+ }
240
+ ) : null,
241
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: 10 }, children: [
242
+ /* @__PURE__ */ jsx(
243
+ ActionButton,
244
+ {
245
+ flex: true,
246
+ label: "Deny",
247
+ onPress: () => props.onDecision("reject"),
248
+ theme,
249
+ variant: "secondary"
250
+ }
251
+ ),
252
+ /* @__PURE__ */ jsx(
253
+ ActionButton,
254
+ {
255
+ flex: true,
256
+ label: "Approve",
257
+ onPress: () => props.onDecision("approve"),
258
+ theme,
259
+ variant: "primary"
260
+ }
261
+ )
262
+ ] })
263
+ ]
264
+ }
265
+ );
266
+ }
267
+ function QuestionCard(props) {
268
+ const { request, theme } = props;
269
+ const question = request.questions[0];
270
+ const [selected, setSelected] = useState([]);
271
+ if (!question) return null;
272
+ const multi = question.kind === "multi_select";
273
+ const toggle = (id) => setSelected(
274
+ (current) => multi ? current.includes(id) ? current.filter((value) => value !== id) : [...current, id] : [id]
275
+ );
276
+ return /* @__PURE__ */ jsxs(CardShell, { eyebrow: "Question for you", icon: "question", theme, title: question.prompt, children: [
277
+ /* @__PURE__ */ jsx(View, { style: { gap: 8 }, children: question.options.map((option) => {
278
+ const active = selected.includes(option.id);
279
+ return /* @__PURE__ */ jsxs(
280
+ Pressable,
281
+ {
282
+ accessibilityRole: multi ? "checkbox" : "radio",
283
+ accessibilityState: { checked: active },
284
+ onPress: () => toggle(option.id),
285
+ style: {
286
+ minHeight: theme.layout.target,
287
+ borderRadius: theme.radius.control,
288
+ borderWidth: active ? 2 : StyleSheet.hairlineWidth * 2,
289
+ borderColor: active ? theme.colors.accent : theme.colors.border,
290
+ paddingHorizontal: 14,
291
+ paddingVertical: 10,
292
+ justifyContent: "center"
293
+ },
294
+ children: [
295
+ /* @__PURE__ */ jsx(
296
+ Text,
297
+ {
298
+ style: {
299
+ color: theme.colors.text,
300
+ fontSize: theme.type.body - 1,
301
+ fontWeight: "500"
302
+ },
303
+ children: option.label
304
+ }
305
+ ),
306
+ option.description ? /* @__PURE__ */ jsx(
307
+ Text,
308
+ {
309
+ style: {
310
+ color: theme.colors.textMuted,
311
+ fontSize: theme.type.small,
312
+ marginTop: 2
313
+ },
314
+ children: option.description
315
+ }
316
+ ) : null
317
+ ]
318
+ },
319
+ option.id
320
+ );
321
+ }) }),
322
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: 10 }, children: [
323
+ request.allowSkip ? /* @__PURE__ */ jsx(
324
+ ActionButton,
325
+ {
326
+ flex: true,
327
+ label: "Skip",
328
+ onPress: () => props.onAnswer(null),
329
+ theme,
330
+ variant: "secondary"
331
+ }
332
+ ) : null,
333
+ /* @__PURE__ */ jsx(
334
+ ActionButton,
335
+ {
336
+ disabled: selected.length === 0,
337
+ flex: true,
338
+ label: "Send answer",
339
+ onPress: () => props.onAnswer([{ questionId: question.id, values: selected }]),
340
+ theme,
341
+ variant: "primary"
342
+ }
343
+ )
344
+ ] })
345
+ ] });
346
+ }
347
+ function toolTitle(item) {
348
+ return toolDisplayName(item.name, item.display);
349
+ }
350
+ function firstString(record, keys) {
351
+ for (const key of keys) {
352
+ const value = record[key];
353
+ if (typeof value === "string" && value.trim()) return value.trim();
354
+ }
355
+ return null;
356
+ }
357
+ function toolDetail(item) {
358
+ const args = item.arguments;
359
+ if (typeof args === "string") return args.split("\n")[0] ?? null;
360
+ if (!args || typeof args !== "object") return null;
361
+ const record = args;
362
+ const known = firstString(record, [
363
+ "cmd",
364
+ "command",
365
+ "query",
366
+ "q",
367
+ "path",
368
+ "url",
369
+ "title",
370
+ "id",
371
+ "name"
372
+ ]);
373
+ if (known) return known;
374
+ const pairs = Object.entries(record).filter(([, value]) => value !== null && value !== void 0 && value !== "").slice(0, 3).map(
375
+ ([key, value]) => `${key.replace(/[_-]+/g, " ")}: ${typeof value === "string" ? value : JSON.stringify(value)}`
376
+ );
377
+ if (pairs.length === 0) return null;
378
+ const text = pairs.join(" \xB7 ");
379
+ return text.length > 110 ? `${text.slice(0, 109)}\u2026` : text;
380
+ }
381
+ function toolOutputPreview(item, lines = 2) {
382
+ const output = item.output;
383
+ const text = typeof output === "string" ? output : output && typeof output === "object" && typeof output.text === "string" ? String(output.text) : output == null ? null : JSON.stringify(output);
384
+ if (!text) return null;
385
+ return text.split("\n").slice(0, lines).join("\n");
386
+ }
387
+ function formatDuration(ms) {
388
+ if (!Number.isFinite(ms) || ms < 1e3) return "";
389
+ const seconds = Math.round(ms / 1e3);
390
+ if (seconds < 60) return `${seconds}s`;
391
+ const minutes = Math.floor(seconds / 60);
392
+ const rest = seconds % 60;
393
+ return rest ? `${minutes}m ${rest}s` : `${minutes}m`;
394
+ }
395
+ function itemTime(item) {
396
+ return item.occurredAt ? Date.parse(item.occurredAt) : Number.NaN;
397
+ }
398
+ function activityItemsOf(group) {
399
+ if (group.kind === "item") return [];
400
+ if (group.kind === "turn") return group.groups.flatMap(activityItemsOf);
401
+ const nested = group.work?.details.flatMap(activityItemsOf) ?? [];
402
+ return nested.length > 0 ? nested : group.items;
403
+ }
404
+ function toolCallsOf(items) {
405
+ return items.filter((item) => item.kind === "tool-call");
406
+ }
407
+ var plainMarkdown = (text, theme) => /* @__PURE__ */ jsx(
408
+ Text,
409
+ {
410
+ style: { color: theme.colors.text, fontSize: theme.type.body, lineHeight: theme.type.bodyLine },
411
+ children: text
412
+ }
413
+ );
414
+ function groupTurnId(group) {
415
+ if (group.kind === "item")
416
+ return "turnId" in group.item ? group.item.turnId ?? null : null;
417
+ const first = activityItemsOf(group)[0];
418
+ return first?.turnId ?? null;
419
+ }
420
+ function orderWorkBeforeProse(groups) {
421
+ const out = [...groups];
422
+ for (let index = 1; index < out.length; index += 1) {
423
+ const group = out[index];
424
+ if (group.kind === "item") continue;
425
+ const turnId = groupTurnId(group);
426
+ if (!turnId) continue;
427
+ let start = index;
428
+ while (start > 0) {
429
+ const previous = out[start - 1];
430
+ if (previous.kind !== "item" || previous.item.kind !== "agent-message" || groupTurnId(previous) !== turnId)
431
+ break;
432
+ start -= 1;
433
+ }
434
+ if (start < index) {
435
+ out.splice(index, 1);
436
+ out.splice(start, 0, group);
437
+ }
438
+ }
439
+ return out;
440
+ }
441
+ function AgentTimeline(props) {
442
+ const { theme, running } = props;
443
+ const groups = useMemo(() => orderWorkBeforeProse(props.groups), [props.groups]);
444
+ const rows = useMemo(() => {
445
+ let liveTurnId = null;
446
+ for (let index = groups.length - 1; index >= 0 && !liveTurnId; index -= 1)
447
+ liveTurnId = groupTurnId(groups[index]);
448
+ const isLive = (group) => running && group.kind !== "item" && groupTurnId(group) === liveTurnId;
449
+ const failedTurns = new Set(
450
+ groups.flatMap(
451
+ (group) => group.kind === "item" && group.item.kind === "turn-end" && group.item.outcome === "failed" && group.item.turnId ? [group.item.turnId] : []
452
+ )
453
+ );
454
+ const out = groups.map((group, index) => ({
455
+ key: groupKey(group, index),
456
+ kind: "group",
457
+ group,
458
+ live: isLive(group),
459
+ failed: group.kind !== "item" && (group.outcome === "failed" || failedTurns.has(groupTurnId(group) ?? ""))
460
+ }));
461
+ const needsYou = (props.approvals?.length ?? 0) > 0 || (props.humanInput?.length ?? 0) > 0;
462
+ if (running && !needsYou && !groups.some(isLive)) out.push({ key: "working", kind: "working" });
463
+ if (props.attentionPlacement !== "tray") {
464
+ for (const approval of props.approvals ?? [])
465
+ out.push({ key: `approval:${approval.id}`, kind: "approval", approval });
466
+ for (const request of props.humanInput ?? [])
467
+ out.push({ key: `question:${request.id}`, kind: "question", request });
468
+ }
469
+ return out;
470
+ }, [groups, running, props.approvals, props.humanInput, props.attentionPlacement]);
471
+ return /* @__PURE__ */ jsx(
472
+ FlatList,
473
+ {
474
+ contentContainerStyle: {
475
+ paddingTop: props.contentInsetTop ?? 12,
476
+ paddingBottom: props.contentInsetBottom ?? 24,
477
+ paddingHorizontal: theme.space.gutter,
478
+ flexGrow: 1
479
+ },
480
+ data: rows,
481
+ keyboardDismissMode: "interactive",
482
+ keyboardShouldPersistTaps: "handled",
483
+ keyExtractor: (row) => row.key,
484
+ ListEmptyComponent: props.emptyState ? /* @__PURE__ */ jsx(Fragment, { children: props.emptyState }) : void 0,
485
+ renderItem: ({ item: row }) => /* @__PURE__ */ jsx(Animated.View, { entering: FadeInDown.duration(220), layout: LinearTransition.duration(180), children: /* @__PURE__ */ jsx(TimelineRow, { ...props, groups, row }) }),
486
+ style: { backgroundColor: theme.colors.background }
487
+ }
488
+ );
489
+ }
490
+ function groupKey(group, index) {
491
+ if (group.kind === "item") {
492
+ const item = group.item;
493
+ return item.reconciliationKey ?? item.id ?? `item:${index}`;
494
+ }
495
+ return `${group.kind}:${group.id}`;
496
+ }
497
+ function TimelineRow(props) {
498
+ const { row, theme } = props;
499
+ if (row.kind === "working") return /* @__PURE__ */ jsx(WorkingLine, { theme, label: "Thinking" });
500
+ if (row.kind === "approval") {
501
+ return /* @__PURE__ */ jsx(
502
+ ApprovalCard,
503
+ {
504
+ approval: row.approval,
505
+ theme,
506
+ onDecision: (decision) => props.onApproval?.(row.approval.id, decision)
507
+ }
508
+ );
509
+ }
510
+ if (row.kind === "question") {
511
+ return /* @__PURE__ */ jsx(
512
+ QuestionCard,
513
+ {
514
+ request: row.request,
515
+ theme,
516
+ onAnswer: (answers) => props.onAnswer?.(row.request.id, answers)
517
+ }
518
+ );
519
+ }
520
+ const group = row.group;
521
+ if (group.kind === "item") return /* @__PURE__ */ jsx(ItemRow, { item: group.item, ...props });
522
+ const waiting = (props.approvals?.length ?? 0) > 0 || (props.humanInput?.length ?? 0) > 0;
523
+ return /* @__PURE__ */ jsx(
524
+ WorkBlock,
525
+ {
526
+ failed: row.failed,
527
+ group,
528
+ live: row.live,
529
+ waiting: row.live && waiting,
530
+ ...props
531
+ }
532
+ );
533
+ }
534
+ function ItemRow(props) {
535
+ const { item, theme } = props;
536
+ const render = props.renderMarkdown ?? plainMarkdown;
537
+ switch (item.kind) {
538
+ case "user-message":
539
+ return /* @__PURE__ */ jsx(UserMessage, { text: item.text, theme });
540
+ case "agent-message":
541
+ return /* @__PURE__ */ jsx(AssistantMessage, { item, render, theme });
542
+ case "turn-end":
543
+ return item.outcome === "failed" && item.failureText ? /* @__PURE__ */ jsx(Notice, { theme, tone: "danger", text: item.failureText }) : null;
544
+ default:
545
+ return null;
546
+ }
547
+ }
548
+ function UserMessage({ text, theme }) {
549
+ return /* @__PURE__ */ jsx(
550
+ View,
551
+ {
552
+ style: { alignItems: "flex-end", marginTop: theme.space.turn, marginBottom: theme.space.row },
553
+ children: /* @__PURE__ */ jsx(
554
+ View,
555
+ {
556
+ style: {
557
+ maxWidth: "86%",
558
+ backgroundColor: theme.colors.userBubble,
559
+ borderRadius: theme.radius.bubble,
560
+ paddingHorizontal: theme.type.body,
561
+ paddingVertical: theme.type.body * 0.6
562
+ },
563
+ children: /* @__PURE__ */ jsx(
564
+ Text,
565
+ {
566
+ selectable: true,
567
+ style: {
568
+ color: theme.colors.onUserBubble,
569
+ fontSize: theme.type.body,
570
+ lineHeight: theme.type.bodyLine
571
+ },
572
+ children: text
573
+ }
574
+ )
575
+ }
576
+ )
577
+ }
578
+ );
579
+ }
580
+ function AssistantMessage({
581
+ item,
582
+ render,
583
+ theme
584
+ }) {
585
+ if (!item.text.trim()) return null;
586
+ const commentary = item.phase === "commentary";
587
+ return /* @__PURE__ */ jsx(View, { style: { marginVertical: theme.space.row, opacity: commentary ? 0.82 : 1 }, children: render(item.text, theme) });
588
+ }
589
+ function Notice({
590
+ theme,
591
+ tone,
592
+ text
593
+ }) {
594
+ const danger = tone === "danger";
595
+ return /* @__PURE__ */ jsxs(
596
+ View,
597
+ {
598
+ style: {
599
+ flexDirection: "row",
600
+ gap: 10,
601
+ alignItems: "flex-start",
602
+ marginVertical: theme.space.row,
603
+ padding: 12,
604
+ borderRadius: theme.radius.card,
605
+ backgroundColor: danger ? theme.colors.dangerSurface : theme.colors.surface
606
+ },
607
+ children: [
608
+ /* @__PURE__ */ jsx(
609
+ AgentIcon,
610
+ {
611
+ color: danger ? theme.colors.danger : theme.colors.textMuted,
612
+ name: "alert",
613
+ size: 18
614
+ }
615
+ ),
616
+ /* @__PURE__ */ jsx(
617
+ Text,
618
+ {
619
+ style: {
620
+ flex: 1,
621
+ color: danger ? theme.colors.danger : theme.colors.textMuted,
622
+ fontSize: theme.type.small,
623
+ lineHeight: theme.type.smallLine
624
+ },
625
+ children: text
626
+ }
627
+ )
628
+ ]
629
+ }
630
+ );
631
+ }
632
+ function WorkBlock(props) {
633
+ const { group, theme, live, waiting, failed } = props;
634
+ const items = activityItemsOf(group);
635
+ const prose = group.kind === "activity" ? group.items.filter((item) => item.kind === "agent-message") : [];
636
+ const steps = items.filter(
637
+ (item) => item.kind === "tool-call" || item.kind === "reasoning" || item.kind === "worker"
638
+ );
639
+ const tools = toolCallsOf(items);
640
+ const outcome = group.outcome;
641
+ const failureText = group.failureText;
642
+ const started = group.kind === "turn" ? Date.parse(group.startedAt) : itemTime(items[0] ?? {});
643
+ const ended = group.kind === "turn" ? Date.parse(group.endedAt) : itemTime(items[items.length - 1] ?? {});
644
+ const duration = formatDuration(ended - started);
645
+ const running = live && !outcome;
646
+ const current = running && !waiting ? [...tools].reverse().find((tool) => tool.status === "running") : void 0;
647
+ const render = props.renderMarkdown ?? plainMarkdown;
648
+ const work = steps.length === 0 ? null : theme.layout.activity === "rail" ? /* @__PURE__ */ jsx(RailSteps, { items: steps, theme, waiting }) : theme.layout.activity === "cards" ? /* @__PURE__ */ jsx(
649
+ CardSteps,
650
+ {
651
+ current,
652
+ duration,
653
+ failed,
654
+ items: steps,
655
+ onOpen: props.onOpenSteps,
656
+ running,
657
+ theme,
658
+ toolCount: tools.length,
659
+ waiting
660
+ }
661
+ ) : /* @__PURE__ */ jsx(
662
+ FoldSteps,
663
+ {
664
+ current,
665
+ duration,
666
+ failed,
667
+ items: steps,
668
+ onOpen: props.onOpenSteps,
669
+ running,
670
+ theme,
671
+ toolCount: tools.length,
672
+ waiting
673
+ }
674
+ );
675
+ return /* @__PURE__ */ jsxs(View, { style: { marginVertical: theme.space.row }, children: [
676
+ work,
677
+ prose.map((item) => /* @__PURE__ */ jsx(View, { style: { marginTop: theme.space.row }, children: render(item.text, theme) }, item.id)),
678
+ outcome === "failed" && failureText ? /* @__PURE__ */ jsx(Notice, { text: failureText, theme, tone: "danger" }) : null
679
+ ] });
680
+ }
681
+ function stepLabel(item) {
682
+ if (item.kind === "tool-call") return toolTitle(item);
683
+ if (item.kind === "reasoning") return "Thought";
684
+ if (item.kind === "worker") return "Worker";
685
+ return "Step";
686
+ }
687
+ var LIVE_VERBS = {
688
+ terminal: "Running",
689
+ search: "Searching",
690
+ edit: "Editing",
691
+ globe: "Browsing",
692
+ rocket: "Deploying"
693
+ };
694
+ function liveLabel(tool) {
695
+ const verb = LIVE_VERBS[toolIconName(tool.name)];
696
+ const detail = toolDetail(tool);
697
+ if (!verb) return detail ? `${toolTitle(tool)} \xB7 ${detail}` : toolTitle(tool);
698
+ return detail ? `${verb} ${detail}` : verb;
699
+ }
700
+ function StatusDot({
701
+ item,
702
+ theme,
703
+ size = 8,
704
+ waiting
705
+ }) {
706
+ const status = item.kind === "tool-call" ? item.status : "complete";
707
+ const color = status === "failed" ? theme.colors.danger : status === "running" ? waiting ? theme.colors.attention : theme.colors.accent : theme.colors.textFaint;
708
+ return /* @__PURE__ */ jsx(View, { style: { width: size, height: size, borderRadius: size / 2, backgroundColor: color } });
709
+ }
710
+ function FoldSteps(props) {
711
+ const { theme, running } = props;
712
+ const [open, setOpen] = useState(false);
713
+ const steps = props.toolCount ? `${props.toolCount} ${props.toolCount === 1 ? "step" : "steps"}` : "";
714
+ const label = props.waiting ? "Waiting for you" : running ? props.current ? liveLabel(props.current) : "Working" : props.failed ? `Stopped${steps ? ` after ${steps}` : ""}` : [props.duration ? `Worked for ${props.duration}` : "Worked", steps].filter(Boolean).join(" \xB7 ");
715
+ return /* @__PURE__ */ jsxs(View, { children: [
716
+ /* @__PURE__ */ jsxs(
717
+ Pressable,
718
+ {
719
+ accessibilityRole: "button",
720
+ accessibilityState: { expanded: open },
721
+ hitSlop: 8,
722
+ onPress: () => props.onOpen ? props.onOpen(props.items, label) : setOpen((value) => !value),
723
+ style: { flexDirection: "row", alignItems: "center", gap: 6, minHeight: 32 },
724
+ children: [
725
+ props.waiting ? /* @__PURE__ */ jsx(
726
+ View,
727
+ {
728
+ style: {
729
+ width: 8,
730
+ height: 8,
731
+ borderRadius: 4,
732
+ backgroundColor: theme.colors.attention
733
+ }
734
+ }
735
+ ) : running ? /* @__PURE__ */ jsx(Pulse, { theme }) : null,
736
+ /* @__PURE__ */ jsx(
737
+ Text,
738
+ {
739
+ numberOfLines: 1,
740
+ style: {
741
+ flexShrink: 1,
742
+ color: props.waiting ? theme.colors.attention : theme.colors.textMuted,
743
+ fontSize: theme.type.small + 1
744
+ },
745
+ children: label
746
+ }
747
+ ),
748
+ /* @__PURE__ */ jsx(
749
+ AgentIcon,
750
+ {
751
+ color: theme.colors.textFaint,
752
+ name: open ? "chevron-down" : "chevron-right",
753
+ size: 14
754
+ }
755
+ )
756
+ ]
757
+ }
758
+ ),
759
+ open ? /* @__PURE__ */ jsx(
760
+ Animated.View,
761
+ {
762
+ entering: FadeIn.duration(160),
763
+ style: { marginTop: 4, marginLeft: 2, gap: 10, paddingVertical: 4 },
764
+ children: props.items.map((item) => /* @__PURE__ */ jsx(CompactStep, { item, theme }, item.id))
765
+ }
766
+ ) : null
767
+ ] });
768
+ }
769
+ function CompactStep({ item, theme }) {
770
+ const detail = item.kind === "tool-call" ? toolDetail(item) : item.kind === "reasoning" ? item.text : null;
771
+ return /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: 10 }, children: [
772
+ /* @__PURE__ */ jsx(View, { style: { paddingTop: 2 }, children: /* @__PURE__ */ jsx(
773
+ AgentIcon,
774
+ {
775
+ color: theme.colors.textFaint,
776
+ name: item.kind === "tool-call" ? toolIconName(item.name) : "sparkle",
777
+ size: 15
778
+ }
779
+ ) }),
780
+ /* @__PURE__ */ jsxs(View, { style: { flex: 1 }, children: [
781
+ /* @__PURE__ */ jsx(
782
+ Text,
783
+ {
784
+ style: {
785
+ color: theme.colors.text,
786
+ fontSize: theme.type.small,
787
+ lineHeight: theme.type.smallLine
788
+ },
789
+ children: stepLabel(item)
790
+ }
791
+ ),
792
+ detail ? /* @__PURE__ */ jsx(
793
+ Text,
794
+ {
795
+ numberOfLines: 2,
796
+ style: {
797
+ color: theme.colors.textMuted,
798
+ fontSize: theme.type.small,
799
+ lineHeight: theme.type.smallLine
800
+ },
801
+ children: detail
802
+ }
803
+ ) : null
804
+ ] })
805
+ ] });
806
+ }
807
+ function AgentStepList(props) {
808
+ return /* @__PURE__ */ jsx(RailSteps, { items: props.items, theme: props.theme, waiting: props.waiting ?? false });
809
+ }
810
+ function RailSteps({
811
+ items,
812
+ theme,
813
+ waiting
814
+ }) {
815
+ return /* @__PURE__ */ jsx(View, { style: { paddingLeft: 4 }, children: items.map((item, index) => {
816
+ const detail = item.kind === "tool-call" ? toolDetail(item) : null;
817
+ const output = item.kind === "tool-call" && item.status !== "running" ? toolOutputPreview(item) : null;
818
+ const reasoning = item.kind === "reasoning" ? item.text : null;
819
+ const last = index === items.length - 1;
820
+ return /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: 12 }, children: [
821
+ /* @__PURE__ */ jsxs(View, { style: { alignItems: "center", width: 10 }, children: [
822
+ /* @__PURE__ */ jsx(View, { style: { height: 6 } }),
823
+ /* @__PURE__ */ jsx(StatusDot, { item, theme, waiting }),
824
+ last ? null : /* @__PURE__ */ jsx(
825
+ View,
826
+ {
827
+ style: {
828
+ flex: 1,
829
+ width: StyleSheet.hairlineWidth * 2,
830
+ backgroundColor: theme.colors.rail,
831
+ marginTop: 4
832
+ }
833
+ }
834
+ )
835
+ ] }),
836
+ /* @__PURE__ */ jsxs(View, { style: { flex: 1, paddingBottom: last ? 0 : 14 }, children: [
837
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: 6 }, children: [
838
+ /* @__PURE__ */ jsx(
839
+ AgentIcon,
840
+ {
841
+ color: theme.colors.textMuted,
842
+ name: item.kind === "tool-call" ? toolIconName(item.name) : "sparkle",
843
+ size: 14
844
+ }
845
+ ),
846
+ /* @__PURE__ */ jsx(
847
+ Text,
848
+ {
849
+ style: {
850
+ color: theme.colors.text,
851
+ fontSize: theme.type.small + 1,
852
+ fontWeight: "500"
853
+ },
854
+ children: stepLabel(item)
855
+ }
856
+ ),
857
+ item.kind === "tool-call" && item.status === "running" ? waiting ? /* @__PURE__ */ jsx(
858
+ Text,
859
+ {
860
+ style: {
861
+ color: theme.colors.attention,
862
+ fontSize: theme.type.small,
863
+ fontWeight: "600"
864
+ },
865
+ children: "Waiting for you"
866
+ }
867
+ ) : /* @__PURE__ */ jsx(Pulse, { theme }) : null
868
+ ] }),
869
+ detail ? /* @__PURE__ */ jsx(
870
+ Text,
871
+ {
872
+ numberOfLines: 1,
873
+ style: {
874
+ marginTop: 3,
875
+ color: theme.colors.textMuted,
876
+ fontFamily: theme.type.mono,
877
+ fontSize: theme.type.small - 0.5
878
+ },
879
+ children: detail
880
+ }
881
+ ) : null,
882
+ reasoning ? /* @__PURE__ */ jsx(
883
+ Text,
884
+ {
885
+ numberOfLines: 3,
886
+ style: {
887
+ marginTop: 3,
888
+ color: theme.colors.textMuted,
889
+ fontSize: theme.type.small,
890
+ lineHeight: theme.type.smallLine,
891
+ fontStyle: "italic"
892
+ },
893
+ children: reasoning
894
+ }
895
+ ) : null,
896
+ output ? /* @__PURE__ */ jsx(
897
+ View,
898
+ {
899
+ style: {
900
+ marginTop: 6,
901
+ padding: 8,
902
+ borderRadius: theme.radius.control,
903
+ backgroundColor: theme.colors.codeBackground
904
+ },
905
+ children: /* @__PURE__ */ jsx(
906
+ Text,
907
+ {
908
+ numberOfLines: 3,
909
+ style: {
910
+ color: theme.colors.textMuted,
911
+ fontFamily: theme.type.mono,
912
+ fontSize: theme.type.small - 1,
913
+ lineHeight: theme.type.smallLine - 1
914
+ },
915
+ children: output
916
+ }
917
+ )
918
+ }
919
+ ) : null
920
+ ] })
921
+ ] }, item.id);
922
+ }) });
923
+ }
924
+ function CardSteps(props) {
925
+ const { theme, running } = props;
926
+ const [open, setOpen] = useState(false);
927
+ const headline = props.waiting ? "Waiting for you" : running ? props.current ? LIVE_VERBS[toolIconName(props.current.name)] ?? toolTitle(props.current) : "Working on it" : props.failed ? "Couldn't finish" : `Done \xB7 ${props.toolCount} ${props.toolCount === 1 ? "step" : "steps"}`;
928
+ const sub = props.waiting ? "Answer below to continue" : running ? props.current ? toolDetail(props.current) : null : props.duration ? `Took ${props.duration}` : null;
929
+ return /* @__PURE__ */ jsxs(
930
+ Pressable,
931
+ {
932
+ accessibilityRole: "button",
933
+ accessibilityState: { expanded: open },
934
+ onPress: () => props.onOpen ? props.onOpen(props.items, headline) : setOpen((value) => !value),
935
+ style: {
936
+ borderRadius: theme.radius.card,
937
+ backgroundColor: theme.colors.surface,
938
+ borderWidth: StyleSheet.hairlineWidth,
939
+ borderColor: theme.colors.border,
940
+ padding: 16,
941
+ minHeight: theme.layout.target
942
+ },
943
+ children: [
944
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
945
+ /* @__PURE__ */ jsx(
946
+ View,
947
+ {
948
+ style: {
949
+ width: 36,
950
+ height: 36,
951
+ borderRadius: 18,
952
+ alignItems: "center",
953
+ justifyContent: "center",
954
+ backgroundColor: props.waiting ? theme.colors.attention : running ? theme.colors.accent : props.failed ? theme.colors.dangerSurface : theme.colors.background
955
+ },
956
+ children: props.waiting ? /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.onAccent, name: "alert", size: 18 }) : running ? /* @__PURE__ */ jsx(Pulse, { color: theme.colors.onAccent, theme }) : props.failed ? /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.danger, name: "x", size: 18, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.success, name: "check", size: 18, strokeWidth: 2.5 })
957
+ }
958
+ ),
959
+ /* @__PURE__ */ jsxs(View, { style: { flex: 1 }, children: [
960
+ /* @__PURE__ */ jsx(
961
+ Text,
962
+ {
963
+ style: {
964
+ color: theme.colors.text,
965
+ fontSize: theme.type.body,
966
+ fontWeight: theme.type.weightStrong
967
+ },
968
+ children: headline
969
+ }
970
+ ),
971
+ sub ? /* @__PURE__ */ jsx(
972
+ Text,
973
+ {
974
+ numberOfLines: 1,
975
+ style: { color: theme.colors.textMuted, fontSize: theme.type.small, marginTop: 2 },
976
+ children: sub
977
+ }
978
+ ) : null
979
+ ] }),
980
+ /* @__PURE__ */ jsx(
981
+ AgentIcon,
982
+ {
983
+ color: theme.colors.textFaint,
984
+ name: open ? "chevron-down" : "chevron-right",
985
+ size: 20
986
+ }
987
+ )
988
+ ] }),
989
+ open ? /* @__PURE__ */ jsx(Animated.View, { entering: FadeIn.duration(160), style: { marginTop: 14, gap: 12 }, children: props.items.map((item) => /* @__PURE__ */ jsx(CompactStep, { item, theme }, item.id)) }) : null
990
+ ]
991
+ }
992
+ );
993
+ }
994
+ function WorkingLine({ theme, label }) {
995
+ return /* @__PURE__ */ jsxs(
996
+ View,
997
+ {
998
+ style: {
999
+ flexDirection: "row",
1000
+ alignItems: "center",
1001
+ gap: 8,
1002
+ marginVertical: theme.space.row,
1003
+ minHeight: 32
1004
+ },
1005
+ children: [
1006
+ /* @__PURE__ */ jsx(Pulse, { theme }),
1007
+ /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.textMuted, fontSize: theme.type.small + 1 }, children: label })
1008
+ ]
1009
+ }
1010
+ );
1011
+ }
1012
+ function Pulse({ theme, color }) {
1013
+ const opacity = useSharedValue(0.35);
1014
+ useEffect(() => {
1015
+ opacity.value = withRepeat(withTiming(1, { duration: 700 }), -1, true);
1016
+ }, [opacity]);
1017
+ const style = useAnimatedStyle(() => ({ opacity: opacity.value }));
1018
+ return /* @__PURE__ */ jsx(
1019
+ Animated.View,
1020
+ {
1021
+ style: [
1022
+ { width: 8, height: 8, borderRadius: 4, backgroundColor: color ?? theme.colors.accent },
1023
+ style
1024
+ ]
1025
+ }
1026
+ );
1027
+ }
1028
+ function AgentStepsSheet(props) {
1029
+ const { theme } = props;
1030
+ const insets = useSafeAreaInsets();
1031
+ return /* @__PURE__ */ jsx(
1032
+ Modal,
1033
+ {
1034
+ animationType: "slide",
1035
+ onRequestClose: props.onClose,
1036
+ presentationStyle: Platform.OS === "ios" ? "pageSheet" : "fullScreen",
1037
+ visible: props.visible,
1038
+ children: /* @__PURE__ */ jsxs(
1039
+ View,
1040
+ {
1041
+ style: {
1042
+ flex: 1,
1043
+ backgroundColor: theme.colors.background,
1044
+ paddingTop: Platform.OS === "ios" ? 0 : insets.top
1045
+ },
1046
+ children: [
1047
+ /* @__PURE__ */ jsxs(
1048
+ View,
1049
+ {
1050
+ style: {
1051
+ height: 56,
1052
+ flexDirection: "row",
1053
+ alignItems: "center",
1054
+ paddingHorizontal: theme.space.gutter
1055
+ },
1056
+ children: [
1057
+ /* @__PURE__ */ jsx(
1058
+ Text,
1059
+ {
1060
+ numberOfLines: 1,
1061
+ style: {
1062
+ flex: 1,
1063
+ color: theme.colors.text,
1064
+ fontSize: theme.type.body + 1,
1065
+ fontWeight: theme.type.weightStrong
1066
+ },
1067
+ children: props.title
1068
+ }
1069
+ ),
1070
+ /* @__PURE__ */ jsx(
1071
+ Pressable,
1072
+ {
1073
+ accessibilityRole: "button",
1074
+ hitSlop: 12,
1075
+ onPress: props.onClose,
1076
+ style: { minHeight: 44, justifyContent: "center" },
1077
+ children: /* @__PURE__ */ jsx(
1078
+ Text,
1079
+ {
1080
+ style: { color: theme.colors.accent, fontSize: theme.type.body, fontWeight: "600" },
1081
+ children: "Done"
1082
+ }
1083
+ )
1084
+ }
1085
+ )
1086
+ ]
1087
+ }
1088
+ ),
1089
+ /* @__PURE__ */ jsx(
1090
+ ScrollView,
1091
+ {
1092
+ contentContainerStyle: { padding: theme.space.gutter, paddingBottom: insets.bottom + 24 },
1093
+ children: /* @__PURE__ */ jsx(AgentStepList, { items: props.steps, theme })
1094
+ }
1095
+ )
1096
+ ]
1097
+ }
1098
+ )
1099
+ }
1100
+ );
1101
+ }
1102
+ function approvalSummary(approval) {
1103
+ return toolDetail({
1104
+ id: approval.id,
1105
+ name: approval.name,
1106
+ arguments: approval.arguments});
1107
+ }
1108
+ function AgentAttentionTray(props) {
1109
+ const { theme } = props;
1110
+ const items = [
1111
+ ...props.approvals.map((approval) => ({ kind: "approval", approval })),
1112
+ ...props.humanInput.map((request) => ({ kind: "question", request }))
1113
+ ];
1114
+ const [selected, setSelected] = useState([]);
1115
+ const current = items[0];
1116
+ if (!current) return null;
1117
+ const key = current.kind === "approval" ? `a:${current.approval.id}` : `q:${current.request.id}`;
1118
+ const question = current.kind === "question" ? current.request.questions[0] : void 0;
1119
+ const multi = question?.kind === "multi_select";
1120
+ return /* @__PURE__ */ jsxs(
1121
+ Animated.View,
1122
+ {
1123
+ entering: FadeInDown.duration(220),
1124
+ exiting: FadeOutDown.duration(160),
1125
+ layout: LinearTransition.duration(180),
1126
+ style: {
1127
+ marginHorizontal: 12,
1128
+ marginBottom: 6,
1129
+ borderRadius: theme.radius.card,
1130
+ backgroundColor: theme.colors.surfaceRaised,
1131
+ borderWidth: StyleSheet.hairlineWidth * 2,
1132
+ borderColor: theme.colors.attention,
1133
+ padding: 14,
1134
+ gap: 10,
1135
+ shadowColor: "#000",
1136
+ shadowOpacity: theme.scheme === "light" ? 0.1 : 0,
1137
+ shadowRadius: 18,
1138
+ shadowOffset: { width: 0, height: 6 }
1139
+ },
1140
+ children: [
1141
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
1142
+ /* @__PURE__ */ jsx(
1143
+ AgentIcon,
1144
+ {
1145
+ color: theme.colors.attention,
1146
+ name: current.kind === "approval" ? "alert" : "question",
1147
+ size: 15
1148
+ }
1149
+ ),
1150
+ /* @__PURE__ */ jsx(
1151
+ Text,
1152
+ {
1153
+ style: {
1154
+ flex: 1,
1155
+ color: theme.colors.attention,
1156
+ fontSize: theme.type.small,
1157
+ fontWeight: "600"
1158
+ },
1159
+ children: current.kind === "approval" ? "Approve to continue" : "Answer to continue"
1160
+ }
1161
+ ),
1162
+ items.length > 1 ? /* @__PURE__ */ jsxs(Text, { style: { color: theme.colors.textFaint, fontSize: theme.type.small }, children: [
1163
+ "1 of ",
1164
+ items.length
1165
+ ] }) : null
1166
+ ] }),
1167
+ current.kind === "approval" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1168
+ /* @__PURE__ */ jsxs(View, { children: [
1169
+ /* @__PURE__ */ jsx(
1170
+ Text,
1171
+ {
1172
+ style: {
1173
+ color: theme.colors.text,
1174
+ fontSize: theme.type.body,
1175
+ fontWeight: theme.type.weightStrong
1176
+ },
1177
+ children: toolDisplayName(current.approval.name, current.approval.display)
1178
+ }
1179
+ ),
1180
+ approvalSummary(current.approval) ? /* @__PURE__ */ jsx(
1181
+ Text,
1182
+ {
1183
+ numberOfLines: 2,
1184
+ style: {
1185
+ marginTop: 2,
1186
+ color: theme.colors.textMuted,
1187
+ fontSize: theme.type.small,
1188
+ lineHeight: theme.type.smallLine
1189
+ },
1190
+ children: approvalSummary(current.approval)
1191
+ }
1192
+ ) : null
1193
+ ] }),
1194
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: 10 }, children: [
1195
+ /* @__PURE__ */ jsx(
1196
+ ActionButton,
1197
+ {
1198
+ flex: true,
1199
+ label: "Deny",
1200
+ onPress: () => props.onApproval(current.approval.id, "reject"),
1201
+ theme,
1202
+ variant: "secondary"
1203
+ }
1204
+ ),
1205
+ /* @__PURE__ */ jsx(
1206
+ ActionButton,
1207
+ {
1208
+ flex: true,
1209
+ label: "Approve",
1210
+ onPress: () => props.onApproval(current.approval.id, "approve"),
1211
+ theme,
1212
+ variant: "primary"
1213
+ }
1214
+ )
1215
+ ] })
1216
+ ] }) : question ? /* @__PURE__ */ jsxs(Fragment, { children: [
1217
+ /* @__PURE__ */ jsx(
1218
+ Text,
1219
+ {
1220
+ style: {
1221
+ color: theme.colors.text,
1222
+ fontSize: theme.type.body,
1223
+ fontWeight: theme.type.weightStrong
1224
+ },
1225
+ children: question.prompt
1226
+ }
1227
+ ),
1228
+ /* @__PURE__ */ jsx(
1229
+ ScrollView,
1230
+ {
1231
+ contentContainerStyle: { gap: 8 },
1232
+ horizontal: true,
1233
+ keyboardShouldPersistTaps: "handled",
1234
+ showsHorizontalScrollIndicator: false,
1235
+ children: question.options.map((option) => {
1236
+ const active = selected.includes(option.id);
1237
+ return /* @__PURE__ */ jsx(
1238
+ Pressable,
1239
+ {
1240
+ accessibilityRole: multi ? "checkbox" : "radio",
1241
+ accessibilityState: { checked: active },
1242
+ onPress: () => setSelected(
1243
+ (values) => multi ? values.includes(option.id) ? values.filter((value) => value !== option.id) : [...values, option.id] : [option.id]
1244
+ ),
1245
+ style: {
1246
+ minHeight: theme.layout.target - 4,
1247
+ paddingHorizontal: 14,
1248
+ borderRadius: theme.radius.control,
1249
+ justifyContent: "center",
1250
+ backgroundColor: active ? theme.colors.accent : theme.colors.surface
1251
+ },
1252
+ children: /* @__PURE__ */ jsx(
1253
+ Text,
1254
+ {
1255
+ style: {
1256
+ color: active ? theme.colors.onAccent : theme.colors.text,
1257
+ fontSize: theme.type.body - 1,
1258
+ fontWeight: "600"
1259
+ },
1260
+ children: option.label
1261
+ }
1262
+ )
1263
+ },
1264
+ option.id
1265
+ );
1266
+ })
1267
+ }
1268
+ ),
1269
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: 10 }, children: [
1270
+ current.request.allowSkip ? /* @__PURE__ */ jsx(
1271
+ ActionButton,
1272
+ {
1273
+ flex: true,
1274
+ label: "Skip",
1275
+ onPress: () => props.onAnswer(current.request.id, null),
1276
+ theme,
1277
+ variant: "secondary"
1278
+ }
1279
+ ) : null,
1280
+ /* @__PURE__ */ jsx(
1281
+ ActionButton,
1282
+ {
1283
+ disabled: selected.length === 0,
1284
+ flex: true,
1285
+ label: "Send",
1286
+ onPress: () => {
1287
+ props.onAnswer(current.request.id, [{ questionId: question.id, values: selected }]);
1288
+ setSelected([]);
1289
+ },
1290
+ theme,
1291
+ variant: "primary"
1292
+ }
1293
+ )
1294
+ ] })
1295
+ ] }) : null
1296
+ ]
1297
+ },
1298
+ key
1299
+ );
1300
+ }
1301
+ function RoundButton(props) {
1302
+ return /* @__PURE__ */ jsx(
1303
+ Pressable,
1304
+ {
1305
+ accessibilityLabel: props.label,
1306
+ accessibilityRole: "button",
1307
+ disabled: props.disabled,
1308
+ hitSlop: 6,
1309
+ onPress: props.onPress,
1310
+ style: ({ pressed }) => ({
1311
+ width: props.size,
1312
+ height: props.size,
1313
+ borderRadius: props.size / 2,
1314
+ alignItems: "center",
1315
+ justifyContent: "center",
1316
+ backgroundColor: props.background,
1317
+ opacity: props.disabled ? 0.35 : pressed ? 0.7 : 1
1318
+ }),
1319
+ children: props.children
1320
+ }
1321
+ );
1322
+ }
1323
+ function AgentComposer(props) {
1324
+ const { theme } = props;
1325
+ if (theme.layout.composer === "bar") return /* @__PURE__ */ jsx(BarComposer, { ...props });
1326
+ if (theme.layout.composer === "voice") return /* @__PURE__ */ jsx(VoiceComposer, { ...props });
1327
+ return /* @__PURE__ */ jsx(PillComposer, { ...props });
1328
+ }
1329
+ function SendOrStop(props) {
1330
+ const { theme, running, value } = props;
1331
+ if (running && !value.trim()) {
1332
+ return /* @__PURE__ */ jsx(
1333
+ RoundButton,
1334
+ {
1335
+ background: theme.colors.accent,
1336
+ label: "Stop",
1337
+ onPress: props.onStop,
1338
+ size: props.size,
1339
+ children: /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.onAccent, name: "stop", size: props.size * 0.4 })
1340
+ }
1341
+ );
1342
+ }
1343
+ return /* @__PURE__ */ jsx(
1344
+ RoundButton,
1345
+ {
1346
+ background: theme.colors.accent,
1347
+ disabled: !value.trim(),
1348
+ label: "Send",
1349
+ onPress: props.onSend,
1350
+ size: props.size,
1351
+ children: /* @__PURE__ */ jsx(
1352
+ AgentIcon,
1353
+ {
1354
+ color: theme.colors.onAccent,
1355
+ name: "arrow-up",
1356
+ size: props.size * 0.5,
1357
+ strokeWidth: 2.4
1358
+ }
1359
+ )
1360
+ }
1361
+ );
1362
+ }
1363
+ function Input(props) {
1364
+ return /* @__PURE__ */ jsx(
1365
+ TextInput,
1366
+ {
1367
+ accessibilityLabel: props.placeholder,
1368
+ multiline: true,
1369
+ onChangeText: props.onChangeText,
1370
+ placeholder: props.placeholder,
1371
+ placeholderTextColor: props.theme.colors.textFaint,
1372
+ style: {
1373
+ flex: 1,
1374
+ color: props.theme.colors.text,
1375
+ fontSize: props.fontSize,
1376
+ minHeight: 40,
1377
+ maxHeight: 160,
1378
+ paddingTop: Platform.OS === "ios" ? 10 : 8,
1379
+ paddingBottom: Platform.OS === "ios" ? 10 : 8
1380
+ },
1381
+ value: props.value
1382
+ }
1383
+ );
1384
+ }
1385
+ function PillComposer(props) {
1386
+ const { theme } = props;
1387
+ const glass = Platform.OS === "ios" && isLiquidGlassAvailable();
1388
+ const inner = /* @__PURE__ */ jsxs(
1389
+ View,
1390
+ {
1391
+ style: {
1392
+ flexDirection: "row",
1393
+ alignItems: "flex-end",
1394
+ gap: 6,
1395
+ paddingHorizontal: 6,
1396
+ paddingVertical: 6
1397
+ },
1398
+ children: [
1399
+ /* @__PURE__ */ jsx(
1400
+ RoundButton,
1401
+ {
1402
+ background: "transparent",
1403
+ label: "Add attachment",
1404
+ onPress: props.onAttach,
1405
+ size: 36,
1406
+ children: /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.text, name: "plus", size: 20 })
1407
+ }
1408
+ ),
1409
+ /* @__PURE__ */ jsx(Input, { ...props, fontSize: theme.type.body }),
1410
+ props.value.trim() || props.running ? /* @__PURE__ */ jsx(SendOrStop, { ...props, size: 36 }) : /* @__PURE__ */ jsx(RoundButton, { background: "transparent", label: "Dictate", onPress: props.onVoice, size: 36, children: /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.text, name: "mic", size: 19 }) })
1411
+ ]
1412
+ }
1413
+ );
1414
+ const shell = {
1415
+ borderRadius: theme.radius.composer,
1416
+ overflow: "hidden",
1417
+ borderWidth: glass ? 0 : StyleSheet.hairlineWidth * 2,
1418
+ borderColor: theme.colors.border,
1419
+ backgroundColor: glass ? void 0 : theme.colors.surfaceRaised,
1420
+ shadowColor: "#000",
1421
+ shadowOpacity: theme.scheme === "light" ? 0.08 : 0,
1422
+ shadowRadius: 16,
1423
+ shadowOffset: { width: 0, height: 6 }
1424
+ };
1425
+ return /* @__PURE__ */ jsx(
1426
+ View,
1427
+ {
1428
+ style: {
1429
+ paddingHorizontal: 12,
1430
+ paddingTop: 6,
1431
+ paddingBottom: Math.max(props.bottomInset, 10)
1432
+ },
1433
+ children: glass ? /* @__PURE__ */ jsx(GlassView, { glassEffectStyle: "regular", isInteractive: true, style: shell, children: inner }) : /* @__PURE__ */ jsx(View, { style: shell, children: inner })
1434
+ }
1435
+ );
1436
+ }
1437
+ function BarComposer(props) {
1438
+ const { theme } = props;
1439
+ return /* @__PURE__ */ jsxs(
1440
+ View,
1441
+ {
1442
+ style: {
1443
+ borderTopWidth: StyleSheet.hairlineWidth,
1444
+ borderColor: theme.colors.border,
1445
+ backgroundColor: theme.colors.surfaceRaised,
1446
+ paddingHorizontal: 12,
1447
+ paddingTop: 8,
1448
+ paddingBottom: Math.max(props.bottomInset, 8),
1449
+ gap: 6
1450
+ },
1451
+ children: [
1452
+ /* @__PURE__ */ jsx(
1453
+ View,
1454
+ {
1455
+ style: {
1456
+ borderRadius: theme.radius.composer,
1457
+ borderWidth: StyleSheet.hairlineWidth * 2,
1458
+ borderColor: theme.colors.border,
1459
+ backgroundColor: theme.colors.background,
1460
+ paddingHorizontal: 12
1461
+ },
1462
+ children: /* @__PURE__ */ jsx(Input, { ...props, fontSize: theme.type.body })
1463
+ }
1464
+ ),
1465
+ /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
1466
+ /* @__PURE__ */ jsx(
1467
+ RoundButton,
1468
+ {
1469
+ background: theme.colors.surface,
1470
+ label: "Add attachment",
1471
+ onPress: props.onAttach,
1472
+ size: 34,
1473
+ children: /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.text, name: "plus", size: 18 })
1474
+ }
1475
+ ),
1476
+ /* @__PURE__ */ jsx(
1477
+ RoundButton,
1478
+ {
1479
+ background: theme.colors.surface,
1480
+ label: "Dictate",
1481
+ onPress: props.onVoice,
1482
+ size: 34,
1483
+ children: /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.text, name: "mic", size: 17 })
1484
+ }
1485
+ ),
1486
+ /* @__PURE__ */ jsx(View, { style: { flex: 1, flexDirection: "row", gap: 6 }, children: props.accessories }),
1487
+ /* @__PURE__ */ jsx(SendOrStop, { ...props, size: 34 })
1488
+ ] })
1489
+ ]
1490
+ }
1491
+ );
1492
+ }
1493
+ function VoiceComposer(props) {
1494
+ const { theme } = props;
1495
+ const hasText = props.value.trim().length > 0;
1496
+ return /* @__PURE__ */ jsxs(
1497
+ View,
1498
+ {
1499
+ style: {
1500
+ flexDirection: "row",
1501
+ alignItems: "flex-end",
1502
+ gap: 10,
1503
+ paddingHorizontal: 14,
1504
+ paddingTop: 8,
1505
+ paddingBottom: Math.max(props.bottomInset, 12)
1506
+ },
1507
+ children: [
1508
+ /* @__PURE__ */ jsxs(
1509
+ View,
1510
+ {
1511
+ style: {
1512
+ flex: 1,
1513
+ flexDirection: "row",
1514
+ alignItems: "flex-end",
1515
+ minHeight: 56,
1516
+ borderRadius: theme.radius.composer,
1517
+ backgroundColor: theme.colors.surface,
1518
+ borderWidth: StyleSheet.hairlineWidth * 2,
1519
+ borderColor: theme.colors.border,
1520
+ paddingLeft: 6,
1521
+ paddingRight: 14
1522
+ },
1523
+ children: [
1524
+ /* @__PURE__ */ jsx(
1525
+ RoundButton,
1526
+ {
1527
+ background: "transparent",
1528
+ label: "Add photo or file",
1529
+ onPress: props.onAttach,
1530
+ size: 44,
1531
+ children: /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.text, name: "plus", size: 24 })
1532
+ }
1533
+ ),
1534
+ /* @__PURE__ */ jsx(Input, { ...props, fontSize: theme.type.body })
1535
+ ]
1536
+ }
1537
+ ),
1538
+ hasText || props.running ? /* @__PURE__ */ jsx(SendOrStop, { ...props, size: 56 }) : /* @__PURE__ */ jsx(
1539
+ RoundButton,
1540
+ {
1541
+ background: theme.colors.accent,
1542
+ label: "Talk",
1543
+ onPress: props.onVoice,
1544
+ size: 56,
1545
+ children: /* @__PURE__ */ jsx(AgentIcon, { color: theme.colors.onAccent, name: "mic", size: 26 })
1546
+ }
1547
+ )
1548
+ ]
1549
+ }
1550
+ );
1551
+ }
1552
+ function ComposerChip({ theme, label }) {
1553
+ return /* @__PURE__ */ jsx(
1554
+ View,
1555
+ {
1556
+ style: {
1557
+ height: 28,
1558
+ paddingHorizontal: 10,
1559
+ borderRadius: 14,
1560
+ backgroundColor: theme.colors.surface,
1561
+ justifyContent: "center"
1562
+ },
1563
+ children: /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.textMuted, fontSize: 12, fontWeight: "500" }, children: label })
1564
+ }
1565
+ );
1566
+ }
1567
+
1568
+ // src/ui/theme.ts
1569
+ var mono = "Menlo";
1570
+ var calm = {
1571
+ id: "calm",
1572
+ name: "Calm",
1573
+ summary: "Prose-first conversation; agent work folds into one quiet line.",
1574
+ theme: (scheme) => ({
1575
+ id: "calm",
1576
+ scheme,
1577
+ colors: scheme === "light" ? {
1578
+ background: "#FFFFFF",
1579
+ surface: "#F6F6F4",
1580
+ surfaceRaised: "#FFFFFF",
1581
+ border: "#E7E6E2",
1582
+ text: "#1A1A19",
1583
+ textMuted: "#6B6A66",
1584
+ textFaint: "#A3A19C",
1585
+ accent: "#1A1A19",
1586
+ onAccent: "#FFFFFF",
1587
+ userBubble: "#F0EFEC",
1588
+ onUserBubble: "#1A1A19",
1589
+ attention: "#C2410C",
1590
+ attentionSurface: "#FFF4ED",
1591
+ success: "#15803D",
1592
+ danger: "#B42318",
1593
+ dangerSurface: "#FEF3F2",
1594
+ codeBackground: "#F6F6F4",
1595
+ rail: "#E7E6E2"
1596
+ } : {
1597
+ background: "#161615",
1598
+ surface: "#21211F",
1599
+ surfaceRaised: "#2A2A28",
1600
+ border: "#33332F",
1601
+ text: "#F2F1EE",
1602
+ textMuted: "#A3A19C",
1603
+ textFaint: "#6B6A66",
1604
+ accent: "#F2F1EE",
1605
+ onAccent: "#161615",
1606
+ userBubble: "#2A2A28",
1607
+ onUserBubble: "#F2F1EE",
1608
+ attention: "#FB923C",
1609
+ attentionSurface: "#2B1D14",
1610
+ success: "#4ADE80",
1611
+ danger: "#F97066",
1612
+ dangerSurface: "#2D1715",
1613
+ codeBackground: "#21211F",
1614
+ rail: "#33332F"
1615
+ },
1616
+ type: {
1617
+ body: 16,
1618
+ bodyLine: 24,
1619
+ small: 13,
1620
+ smallLine: 18,
1621
+ title: 20,
1622
+ mono,
1623
+ weightStrong: "600"
1624
+ },
1625
+ radius: { bubble: 20, card: 16, composer: 26, control: 18 },
1626
+ space: { gutter: 20, row: 10, turn: 28 },
1627
+ layout: { activity: "fold", composer: "pill", userMessage: "bubble", target: 44 }
1628
+ })
1629
+ };
1630
+ var workbench = {
1631
+ id: "workbench",
1632
+ name: "Workbench",
1633
+ summary: "Every step on a visible rail; dense, inspectable, built for long agent runs.",
1634
+ theme: (scheme) => ({
1635
+ id: "workbench",
1636
+ scheme,
1637
+ colors: scheme === "light" ? {
1638
+ background: "#FBFBFC",
1639
+ surface: "#F1F2F5",
1640
+ surfaceRaised: "#FFFFFF",
1641
+ border: "#E2E4EA",
1642
+ text: "#0F1115",
1643
+ textMuted: "#5B6170",
1644
+ textFaint: "#9AA0AD",
1645
+ accent: "#3B5BDB",
1646
+ onAccent: "#FFFFFF",
1647
+ userBubble: "#3B5BDB",
1648
+ onUserBubble: "#FFFFFF",
1649
+ attention: "#D97706",
1650
+ attentionSurface: "#FFF8EB",
1651
+ success: "#12B76A",
1652
+ danger: "#E5484D",
1653
+ dangerSurface: "#FFF0F0",
1654
+ codeBackground: "#F1F2F5",
1655
+ rail: "#D5D8E0"
1656
+ } : {
1657
+ background: "#0D0F13",
1658
+ surface: "#161920",
1659
+ surfaceRaised: "#1C2029",
1660
+ border: "#262A35",
1661
+ text: "#E8EAF0",
1662
+ textMuted: "#9AA0AD",
1663
+ textFaint: "#5B6170",
1664
+ accent: "#7C93FF",
1665
+ onAccent: "#0D0F13",
1666
+ userBubble: "#2A3566",
1667
+ onUserBubble: "#E8EAF0",
1668
+ attention: "#FBBF24",
1669
+ attentionSurface: "#2A2110",
1670
+ success: "#3DD68C",
1671
+ danger: "#FF6369",
1672
+ dangerSurface: "#2A1416",
1673
+ codeBackground: "#161920",
1674
+ rail: "#2E3340"
1675
+ },
1676
+ type: {
1677
+ body: 15,
1678
+ bodyLine: 22,
1679
+ small: 12,
1680
+ smallLine: 16,
1681
+ title: 18,
1682
+ mono,
1683
+ weightStrong: "600"
1684
+ },
1685
+ radius: { bubble: 14, card: 12, composer: 14, control: 10 },
1686
+ space: { gutter: 16, row: 8, turn: 22 },
1687
+ layout: { activity: "rail", composer: "bar", userMessage: "bubble", target: 44 }
1688
+ })
1689
+ };
1690
+ var field = {
1691
+ id: "field",
1692
+ name: "Field",
1693
+ summary: "Large type and targets, decisions as bold cards, voice-first. Usable with gloves.",
1694
+ theme: (scheme) => ({
1695
+ id: "field",
1696
+ scheme,
1697
+ colors: scheme === "light" ? {
1698
+ background: "#F4F3EF",
1699
+ surface: "#FFFFFF",
1700
+ surfaceRaised: "#FFFFFF",
1701
+ border: "#E3E1DA",
1702
+ text: "#121212",
1703
+ textMuted: "#5C5A55",
1704
+ textFaint: "#97948C",
1705
+ accent: "#1F5FD6",
1706
+ onAccent: "#FFFFFF",
1707
+ userBubble: "#121212",
1708
+ onUserBubble: "#FFFFFF",
1709
+ attention: "#E8590C",
1710
+ attentionSurface: "#FFF1E6",
1711
+ success: "#2F9E44",
1712
+ danger: "#C92A2A",
1713
+ dangerSurface: "#FFF0F0",
1714
+ codeBackground: "#EFEDE7",
1715
+ rail: "#E3E1DA"
1716
+ } : {
1717
+ background: "#111110",
1718
+ surface: "#1D1C1A",
1719
+ surfaceRaised: "#252421",
1720
+ border: "#302E2A",
1721
+ text: "#F5F4F0",
1722
+ textMuted: "#B1AEA6",
1723
+ textFaint: "#77746D",
1724
+ accent: "#5C8DF6",
1725
+ onAccent: "#0B0B0A",
1726
+ userBubble: "#F5F4F0",
1727
+ onUserBubble: "#111110",
1728
+ attention: "#FF8A3D",
1729
+ attentionSurface: "#2E1F13",
1730
+ success: "#51CF66",
1731
+ danger: "#FF6B6B",
1732
+ dangerSurface: "#2E1616",
1733
+ codeBackground: "#1D1C1A",
1734
+ rail: "#302E2A"
1735
+ },
1736
+ type: {
1737
+ body: 18,
1738
+ bodyLine: 27,
1739
+ small: 15,
1740
+ smallLine: 20,
1741
+ title: 23,
1742
+ mono,
1743
+ weightStrong: "700"
1744
+ },
1745
+ radius: { bubble: 22, card: 20, composer: 30, control: 22 },
1746
+ space: { gutter: 18, row: 12, turn: 30 },
1747
+ layout: { activity: "cards", composer: "voice", userMessage: "bubble", target: 56 }
1748
+ })
1749
+ };
1750
+ var agentDirections = [calm, workbench, field];
1751
+ function agentTheme(direction, scheme) {
1752
+ return (agentDirections.find((entry) => entry.id === direction) ?? calm).theme(scheme);
1753
+ }
1754
+
1755
+ export { ActionButton, AgentAttentionTray, AgentComposer, AgentIcon, AgentStepList, AgentStepsSheet, AgentTimeline, ApprovalCard, ComposerChip, QuestionCard, UserMessage, WorkingLine, agentDirections, agentTheme, formatDuration, toolDetail, toolIconName, toolOutputPreview, toolTitle };
1756
+ //# sourceMappingURL=index.js.map
1757
+ //# sourceMappingURL=index.js.map