@buoy-gg/ask-buoy 7.0.35 → 7.0.38

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 (286) hide show
  1. package/README.md +73 -15
  2. package/lib/commonjs/blocks/AskBlocks.js +1 -338
  3. package/lib/commonjs/blocks/BlockRenderer.js +1 -250
  4. package/lib/commonjs/blocks/ChromePrototypes.js +1 -514
  5. package/lib/commonjs/blocks/DataBlocks.js +1 -688
  6. package/lib/commonjs/blocks/ExtraBlocks.js +1 -1854
  7. package/lib/commonjs/blocks/MediaBlocks.js +1 -140
  8. package/lib/commonjs/blocks/ReceiptBlocks.js +1 -586
  9. package/lib/commonjs/blocks/blockText.js +1 -0
  10. package/lib/commonjs/blocks/blockText.test.js +1 -0
  11. package/lib/commonjs/blocks/context.js +1 -42
  12. package/lib/commonjs/blocks/icons.js +1 -96
  13. package/lib/commonjs/blocks/index.js +1 -95
  14. package/lib/commonjs/blocks/listRow.test.js +1 -55
  15. package/lib/commonjs/blocks/pageState.js +1 -34
  16. package/lib/commonjs/blocks/pageState.test.js +1 -57
  17. package/lib/commonjs/blocks/primitives.js +1 -401
  18. package/lib/commonjs/blocks/primitivesIndex.js +1 -62
  19. package/lib/commonjs/components/ApprovalCard.js +1 -140
  20. package/lib/commonjs/components/AskBuoyHeader.js +1 -164
  21. package/lib/commonjs/components/AskBuoyIcon.js +1 -19
  22. package/lib/commonjs/components/AskBuoyModal.js +1 -353
  23. package/lib/commonjs/components/AskBuoySettings.js +1 -69
  24. package/lib/commonjs/components/ChangesBar.js +1 -211
  25. package/lib/commonjs/components/Composer.js +1 -175
  26. package/lib/commonjs/components/EmptyState.js +1 -154
  27. package/lib/commonjs/components/KeyboardPad.js +1 -0
  28. package/lib/commonjs/components/Markdown.js +1 -252
  29. package/lib/commonjs/components/MessageList.js +1 -683
  30. package/lib/commonjs/components/QueuedMessages.js +1 -0
  31. package/lib/commonjs/components/ThinkingStrip.js +1 -223
  32. package/lib/commonjs/components/TypingDots.js +1 -63
  33. package/lib/commonjs/components/markdownParse.js +1 -0
  34. package/lib/commonjs/components/markdownParse.test.js +1 -0
  35. package/lib/commonjs/components/useCopyAction.js +1 -50
  36. package/lib/commonjs/index.js +1 -252
  37. package/lib/commonjs/preset.js +1 -90
  38. package/lib/commonjs/store/activityGroups.js +1 -0
  39. package/lib/commonjs/store/activityGroups.test.js +1 -0
  40. package/lib/commonjs/store/askBuoySettings.js +1 -67
  41. package/lib/commonjs/store/askBuoyStore.js +1 -365
  42. package/lib/commonjs/store/blockPlacement.js +1 -0
  43. package/lib/commonjs/store/blockPlacement.test.js +1 -0
  44. package/lib/commonjs/store/queue.test.js +1 -0
  45. package/lib/commonjs/store/resetConversation.js +1 -0
  46. package/lib/commonjs/store/restorePending.test.js +1 -0
  47. package/lib/commonjs/store/restoredIds.test.js +1 -47
  48. package/lib/commonjs/store/suggestions.js +1 -0
  49. package/lib/commonjs/store/suggestions.test.js +1 -0
  50. package/lib/commonjs/store/systemLine.test.js +1 -0
  51. package/lib/commonjs/store/ticketPrompt.js +1 -0
  52. package/lib/commonjs/store/traceText.js +1 -81
  53. package/lib/commonjs/store/traceText.test.js +1 -112
  54. package/lib/commonjs/store/transcriptPersistence.js +1 -208
  55. package/lib/commonjs/store/transcriptPersistence.test.js +1 -185
  56. package/lib/commonjs/store/turnRendering.test.js +1 -0
  57. package/lib/commonjs/store/useAskBuoy.js +1 -400
  58. package/lib/commonjs/store/useAskBuoySettings.js +1 -14
  59. package/lib/commonjs/sync/askBuoySyncAdapter.js +1 -119
  60. package/lib/commonjs/sync/askBuoySyncAdapter.test.js +1 -141
  61. package/lib/commonjs/sync/wire.js +1 -58
  62. package/lib/commonjs/types.js +1 -6
  63. package/lib/module/blocks/AskBlocks.js +1 -331
  64. package/lib/module/blocks/BlockRenderer.js +1 -245
  65. package/lib/module/blocks/ChromePrototypes.js +1 -503
  66. package/lib/module/blocks/DataBlocks.js +1 -674
  67. package/lib/module/blocks/ExtraBlocks.js +1 -1827
  68. package/lib/module/blocks/MediaBlocks.js +1 -135
  69. package/lib/module/blocks/ReceiptBlocks.js +1 -574
  70. package/lib/module/blocks/blockText.js +1 -0
  71. package/lib/module/blocks/blockText.test.js +1 -0
  72. package/lib/module/blocks/context.js +1 -35
  73. package/lib/module/blocks/icons.js +1 -91
  74. package/lib/module/blocks/index.js +1 -8
  75. package/lib/module/blocks/listRow.test.js +1 -56
  76. package/lib/module/blocks/pageState.js +1 -30
  77. package/lib/module/blocks/pageState.test.js +1 -56
  78. package/lib/module/blocks/primitives.js +1 -389
  79. package/lib/module/blocks/primitivesIndex.js +1 -5
  80. package/lib/module/components/ApprovalCard.js +1 -135
  81. package/lib/module/components/AskBuoyHeader.js +1 -161
  82. package/lib/module/components/AskBuoyIcon.js +1 -8
  83. package/lib/module/components/AskBuoyModal.js +1 -348
  84. package/lib/module/components/AskBuoySettings.js +1 -64
  85. package/lib/module/components/ChangesBar.js +1 -206
  86. package/lib/module/components/Composer.js +1 -170
  87. package/lib/module/components/EmptyState.js +1 -149
  88. package/lib/module/components/KeyboardPad.js +1 -0
  89. package/lib/module/components/Markdown.js +1 -246
  90. package/lib/module/components/MessageList.js +1 -677
  91. package/lib/module/components/QueuedMessages.js +1 -0
  92. package/lib/module/components/ThinkingStrip.js +1 -218
  93. package/lib/module/components/TypingDots.js +1 -58
  94. package/lib/module/components/markdownParse.js +1 -0
  95. package/lib/module/components/markdownParse.test.js +1 -0
  96. package/lib/module/components/useCopyAction.js +1 -46
  97. package/lib/module/index.js +1 -34
  98. package/lib/module/preset.js +1 -73
  99. package/lib/module/store/activityGroups.js +1 -0
  100. package/lib/module/store/activityGroups.test.js +1 -0
  101. package/lib/module/store/askBuoySettings.js +1 -62
  102. package/lib/module/store/askBuoyStore.js +1 -361
  103. package/lib/module/store/blockPlacement.js +1 -0
  104. package/lib/module/store/blockPlacement.test.js +1 -0
  105. package/lib/module/store/queue.test.js +1 -0
  106. package/lib/module/store/resetConversation.js +1 -0
  107. package/lib/module/store/restorePending.test.js +1 -0
  108. package/lib/module/store/restoredIds.test.js +1 -46
  109. package/lib/module/store/suggestions.js +1 -0
  110. package/lib/module/store/suggestions.test.js +1 -0
  111. package/lib/module/store/systemLine.test.js +1 -0
  112. package/lib/module/store/ticketPrompt.js +1 -0
  113. package/lib/module/store/traceText.js +1 -75
  114. package/lib/module/store/traceText.test.js +1 -111
  115. package/lib/module/store/transcriptPersistence.js +1 -198
  116. package/lib/module/store/transcriptPersistence.test.js +1 -184
  117. package/lib/module/store/turnRendering.test.js +1 -0
  118. package/lib/module/store/useAskBuoy.js +1 -394
  119. package/lib/module/store/useAskBuoySettings.js +1 -9
  120. package/lib/module/sync/askBuoySyncAdapter.js +1 -114
  121. package/lib/module/sync/askBuoySyncAdapter.test.js +1 -140
  122. package/lib/module/sync/wire.js +1 -47
  123. package/lib/module/types.js +1 -4
  124. package/lib/typescript/blocks/DataBlocks.d.ts +11 -0
  125. package/lib/typescript/blocks/ExtraBlocks.d.ts +18 -2
  126. package/lib/typescript/blocks/blockText.d.ts +14 -0
  127. package/lib/typescript/blocks/blockText.test.d.ts +2 -0
  128. package/lib/typescript/blocks/primitives.d.ts +16 -1
  129. package/lib/typescript/components/ApprovalCard.d.ts +9 -1
  130. package/lib/typescript/components/AskBuoyHeader.d.ts +31 -1
  131. package/lib/typescript/components/Composer.d.ts +16 -1
  132. package/lib/typescript/components/EmptyState.d.ts +5 -1
  133. package/lib/typescript/components/KeyboardPad.d.ts +33 -0
  134. package/lib/typescript/components/Markdown.d.ts +0 -10
  135. package/lib/typescript/components/MessageList.d.ts +7 -2
  136. package/lib/typescript/components/QueuedMessages.d.ts +10 -0
  137. package/lib/typescript/components/markdownParse.d.ts +49 -0
  138. package/lib/typescript/components/markdownParse.test.d.ts +2 -0
  139. package/lib/typescript/preset.d.ts +4 -2
  140. package/lib/typescript/store/activityGroups.d.ts +29 -0
  141. package/lib/typescript/store/activityGroups.test.d.ts +2 -0
  142. package/lib/typescript/store/askBuoySettings.d.ts +22 -0
  143. package/lib/typescript/store/askBuoyStore.d.ts +174 -9
  144. package/lib/typescript/store/blockPlacement.d.ts +30 -0
  145. package/lib/typescript/store/blockPlacement.test.d.ts +2 -0
  146. package/lib/typescript/store/queue.test.d.ts +2 -0
  147. package/lib/typescript/store/resetConversation.d.ts +38 -0
  148. package/lib/typescript/store/restorePending.test.d.ts +2 -0
  149. package/lib/typescript/store/suggestions.d.ts +32 -0
  150. package/lib/typescript/store/suggestions.test.d.ts +2 -0
  151. package/lib/typescript/store/systemLine.test.d.ts +2 -0
  152. package/lib/typescript/store/ticketPrompt.d.ts +11 -0
  153. package/lib/typescript/store/transcriptPersistence.d.ts +41 -2
  154. package/lib/typescript/store/turnRendering.test.d.ts +2 -0
  155. package/lib/typescript/store/useAskBuoy.d.ts +26 -3
  156. package/lib/typescript/sync/askBuoySyncAdapter.d.ts +29 -6
  157. package/package.json +10 -10
  158. package/lib/commonjs/blocks/AskBlocks.js.map +0 -1
  159. package/lib/commonjs/blocks/BlockRenderer.js.map +0 -1
  160. package/lib/commonjs/blocks/ChromePrototypes.js.map +0 -1
  161. package/lib/commonjs/blocks/DataBlocks.js.map +0 -1
  162. package/lib/commonjs/blocks/ExtraBlocks.js.map +0 -1
  163. package/lib/commonjs/blocks/MediaBlocks.js.map +0 -1
  164. package/lib/commonjs/blocks/ReceiptBlocks.js.map +0 -1
  165. package/lib/commonjs/blocks/context.js.map +0 -1
  166. package/lib/commonjs/blocks/icons.js.map +0 -1
  167. package/lib/commonjs/blocks/index.js.map +0 -1
  168. package/lib/commonjs/blocks/listRow.test.js.map +0 -1
  169. package/lib/commonjs/blocks/pageState.js.map +0 -1
  170. package/lib/commonjs/blocks/pageState.test.js.map +0 -1
  171. package/lib/commonjs/blocks/primitives.js.map +0 -1
  172. package/lib/commonjs/blocks/primitivesIndex.js.map +0 -1
  173. package/lib/commonjs/components/ApprovalCard.js.map +0 -1
  174. package/lib/commonjs/components/AskBuoyHeader.js.map +0 -1
  175. package/lib/commonjs/components/AskBuoyIcon.js.map +0 -1
  176. package/lib/commonjs/components/AskBuoyModal.js.map +0 -1
  177. package/lib/commonjs/components/AskBuoySettings.js.map +0 -1
  178. package/lib/commonjs/components/ChangesBar.js.map +0 -1
  179. package/lib/commonjs/components/Composer.js.map +0 -1
  180. package/lib/commonjs/components/EmptyState.js.map +0 -1
  181. package/lib/commonjs/components/Markdown.js.map +0 -1
  182. package/lib/commonjs/components/MessageList.js.map +0 -1
  183. package/lib/commonjs/components/ThinkingStrip.js.map +0 -1
  184. package/lib/commonjs/components/TypingDots.js.map +0 -1
  185. package/lib/commonjs/components/useCopyAction.js.map +0 -1
  186. package/lib/commonjs/index.js.map +0 -1
  187. package/lib/commonjs/preset.js.map +0 -1
  188. package/lib/commonjs/store/askBuoySettings.js.map +0 -1
  189. package/lib/commonjs/store/askBuoyStore.js.map +0 -1
  190. package/lib/commonjs/store/restoredIds.test.js.map +0 -1
  191. package/lib/commonjs/store/traceText.js.map +0 -1
  192. package/lib/commonjs/store/traceText.test.js.map +0 -1
  193. package/lib/commonjs/store/transcriptPersistence.js.map +0 -1
  194. package/lib/commonjs/store/transcriptPersistence.test.js.map +0 -1
  195. package/lib/commonjs/store/useAskBuoy.js.map +0 -1
  196. package/lib/commonjs/store/useAskBuoySettings.js.map +0 -1
  197. package/lib/commonjs/sync/askBuoySyncAdapter.js.map +0 -1
  198. package/lib/commonjs/sync/askBuoySyncAdapter.test.js.map +0 -1
  199. package/lib/commonjs/sync/wire.js.map +0 -1
  200. package/lib/commonjs/types.js.map +0 -1
  201. package/lib/module/blocks/AskBlocks.js.map +0 -1
  202. package/lib/module/blocks/BlockRenderer.js.map +0 -1
  203. package/lib/module/blocks/ChromePrototypes.js.map +0 -1
  204. package/lib/module/blocks/DataBlocks.js.map +0 -1
  205. package/lib/module/blocks/ExtraBlocks.js.map +0 -1
  206. package/lib/module/blocks/MediaBlocks.js.map +0 -1
  207. package/lib/module/blocks/ReceiptBlocks.js.map +0 -1
  208. package/lib/module/blocks/context.js.map +0 -1
  209. package/lib/module/blocks/icons.js.map +0 -1
  210. package/lib/module/blocks/index.js.map +0 -1
  211. package/lib/module/blocks/listRow.test.js.map +0 -1
  212. package/lib/module/blocks/pageState.js.map +0 -1
  213. package/lib/module/blocks/pageState.test.js.map +0 -1
  214. package/lib/module/blocks/primitives.js.map +0 -1
  215. package/lib/module/blocks/primitivesIndex.js.map +0 -1
  216. package/lib/module/components/ApprovalCard.js.map +0 -1
  217. package/lib/module/components/AskBuoyHeader.js.map +0 -1
  218. package/lib/module/components/AskBuoyIcon.js.map +0 -1
  219. package/lib/module/components/AskBuoyModal.js.map +0 -1
  220. package/lib/module/components/AskBuoySettings.js.map +0 -1
  221. package/lib/module/components/ChangesBar.js.map +0 -1
  222. package/lib/module/components/Composer.js.map +0 -1
  223. package/lib/module/components/EmptyState.js.map +0 -1
  224. package/lib/module/components/Markdown.js.map +0 -1
  225. package/lib/module/components/MessageList.js.map +0 -1
  226. package/lib/module/components/ThinkingStrip.js.map +0 -1
  227. package/lib/module/components/TypingDots.js.map +0 -1
  228. package/lib/module/components/useCopyAction.js.map +0 -1
  229. package/lib/module/index.js.map +0 -1
  230. package/lib/module/preset.js.map +0 -1
  231. package/lib/module/store/askBuoySettings.js.map +0 -1
  232. package/lib/module/store/askBuoyStore.js.map +0 -1
  233. package/lib/module/store/restoredIds.test.js.map +0 -1
  234. package/lib/module/store/traceText.js.map +0 -1
  235. package/lib/module/store/traceText.test.js.map +0 -1
  236. package/lib/module/store/transcriptPersistence.js.map +0 -1
  237. package/lib/module/store/transcriptPersistence.test.js.map +0 -1
  238. package/lib/module/store/useAskBuoy.js.map +0 -1
  239. package/lib/module/store/useAskBuoySettings.js.map +0 -1
  240. package/lib/module/sync/askBuoySyncAdapter.js.map +0 -1
  241. package/lib/module/sync/askBuoySyncAdapter.test.js.map +0 -1
  242. package/lib/module/sync/wire.js.map +0 -1
  243. package/lib/module/types.js.map +0 -1
  244. package/lib/typescript/blocks/AskBlocks.d.ts.map +0 -1
  245. package/lib/typescript/blocks/BlockRenderer.d.ts.map +0 -1
  246. package/lib/typescript/blocks/ChromePrototypes.d.ts.map +0 -1
  247. package/lib/typescript/blocks/DataBlocks.d.ts.map +0 -1
  248. package/lib/typescript/blocks/ExtraBlocks.d.ts.map +0 -1
  249. package/lib/typescript/blocks/MediaBlocks.d.ts.map +0 -1
  250. package/lib/typescript/blocks/ReceiptBlocks.d.ts.map +0 -1
  251. package/lib/typescript/blocks/context.d.ts.map +0 -1
  252. package/lib/typescript/blocks/icons.d.ts.map +0 -1
  253. package/lib/typescript/blocks/index.d.ts.map +0 -1
  254. package/lib/typescript/blocks/listRow.test.d.ts.map +0 -1
  255. package/lib/typescript/blocks/pageState.d.ts.map +0 -1
  256. package/lib/typescript/blocks/pageState.test.d.ts.map +0 -1
  257. package/lib/typescript/blocks/primitives.d.ts.map +0 -1
  258. package/lib/typescript/blocks/primitivesIndex.d.ts.map +0 -1
  259. package/lib/typescript/components/ApprovalCard.d.ts.map +0 -1
  260. package/lib/typescript/components/AskBuoyHeader.d.ts.map +0 -1
  261. package/lib/typescript/components/AskBuoyIcon.d.ts.map +0 -1
  262. package/lib/typescript/components/AskBuoyModal.d.ts.map +0 -1
  263. package/lib/typescript/components/AskBuoySettings.d.ts.map +0 -1
  264. package/lib/typescript/components/ChangesBar.d.ts.map +0 -1
  265. package/lib/typescript/components/Composer.d.ts.map +0 -1
  266. package/lib/typescript/components/EmptyState.d.ts.map +0 -1
  267. package/lib/typescript/components/Markdown.d.ts.map +0 -1
  268. package/lib/typescript/components/MessageList.d.ts.map +0 -1
  269. package/lib/typescript/components/ThinkingStrip.d.ts.map +0 -1
  270. package/lib/typescript/components/TypingDots.d.ts.map +0 -1
  271. package/lib/typescript/components/useCopyAction.d.ts.map +0 -1
  272. package/lib/typescript/index.d.ts.map +0 -1
  273. package/lib/typescript/preset.d.ts.map +0 -1
  274. package/lib/typescript/store/askBuoySettings.d.ts.map +0 -1
  275. package/lib/typescript/store/askBuoyStore.d.ts.map +0 -1
  276. package/lib/typescript/store/restoredIds.test.d.ts.map +0 -1
  277. package/lib/typescript/store/traceText.d.ts.map +0 -1
  278. package/lib/typescript/store/traceText.test.d.ts.map +0 -1
  279. package/lib/typescript/store/transcriptPersistence.d.ts.map +0 -1
  280. package/lib/typescript/store/transcriptPersistence.test.d.ts.map +0 -1
  281. package/lib/typescript/store/useAskBuoy.d.ts.map +0 -1
  282. package/lib/typescript/store/useAskBuoySettings.d.ts.map +0 -1
  283. package/lib/typescript/sync/askBuoySyncAdapter.d.ts.map +0 -1
  284. package/lib/typescript/sync/askBuoySyncAdapter.test.d.ts.map +0 -1
  285. package/lib/typescript/sync/wire.d.ts.map +0 -1
  286. package/lib/typescript/types.d.ts.map +0 -1
@@ -1,683 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.MessageList = MessageList;
7
- exports.transcriptToText = transcriptToText;
8
- var _react = require("react");
9
- var _reactNative = require("react-native");
10
- var _sharedUi = require("@buoy-gg/shared-ui");
11
- var _agentCore = require("@buoy-gg/agent-core");
12
- var _BlockRenderer = require("../blocks/BlockRenderer");
13
- var _Markdown = require("./Markdown");
14
- var _ThinkingStrip = require("./ThinkingStrip");
15
- var _TypingDots = require("./TypingDots");
16
- var _useCopyAction = require("./useCopyAction");
17
- var _traceText = require("../store/traceText");
18
- var _useAskBuoySettings = require("../store/useAskBuoySettings");
19
- var _jsxRuntime = require("react/jsx-runtime");
20
- /**
21
- * The transcript.
22
- *
23
- * Owns the ONLY scroller in the sheet. JsModal's default wrapper uses
24
- * `contentContainerStyle: { flexGrow: 1 }`, so a `flex: 1` scroller nested
25
- * inside resolves against the CONTENT rather than the viewport: it grows to
26
- * full content height, never scrolls, and the outer wrapper scrolls instead.
27
- * That is invisible to a human and fatal to Detox ("View is not scrollable at
28
- * the given start point"). The sheet passes `disableScrollWrapper` and this
29
- * list is the one scroller.
30
- *
31
- * Layout, and why:
32
- * - The user's messages are bubbles on the right; the assistant's text is
33
- * plain, full-width prose on the left. A grey bubble around every answer
34
- * cost 28pt of width per line and made the two sides look like the same
35
- * speaker.
36
- * - Tool calls render as an ACTIVITY CARD above the answer they produced —
37
- * one row per call, a status mark, a short human title ("Open /bag") and a
38
- * result word ("Done", "12 items", "Not found"). Nothing in a row is
39
- * truncated to the point of being unreadable: the title wraps, and tapping
40
- * the row expands it to the catalog's full sentence plus the tool it ran on.
41
- * The previous version showed the model-facing sentence cut off at two
42
- * lines with the result's JSON key names beside it, which was unreadable
43
- * AND uninformative.
44
- */
45
-
46
- function StatusMark({
47
- status
48
- }) {
49
- switch (status) {
50
- case "running":
51
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
52
- size: "small",
53
- color: _sharedUi.night.color.textSecondary
54
- });
55
- case "ok":
56
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
57
- style: [styles.mark, styles.markOk],
58
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Check, {
59
- size: 10,
60
- color: _sharedUi.night.color.onAccent
61
- })
62
- });
63
- case "failed":
64
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
65
- style: [styles.mark, styles.markFailed],
66
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.X, {
67
- size: 10,
68
- color: _sharedUi.night.color.text
69
- })
70
- });
71
- case "refused":
72
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
73
- style: [styles.mark, styles.markRefused],
74
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.AlertTriangle, {
75
- size: 10,
76
- color: _sharedUi.night.color.onAccent
77
- })
78
- });
79
- }
80
- }
81
-
82
- /** The trailing word: what happened, in one glance. */
83
- function statusText(call) {
84
- if (call.status === "running") return {
85
- text: "",
86
- tone: "muted"
87
- };
88
- if (call.status === "refused") return {
89
- text: "Refused",
90
- tone: "warning"
91
- };
92
- if (call.status === "failed") return {
93
- text: "Failed",
94
- tone: "danger"
95
- };
96
- return {
97
- text: call.summary || "Done",
98
- tone: "muted"
99
- };
100
- }
101
- function ActivityRow({
102
- call,
103
- last
104
- }) {
105
- const [open, setOpen] = (0, _react.useState)(false);
106
- const status = statusText(call);
107
- const Chevron = open ? _sharedUi.ChevronDown : _sharedUi.ChevronRight;
108
- const failureDetail = call.status === "failed" && call.summary && call.summary !== "Failed" ? call.summary : null;
109
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
110
- testID: `buoy-ask-buoy-tool-${call.toolId}`,
111
- accessibilityRole: "button",
112
- accessibilityLabel: `${call.label}, ${status.text || "running"}`,
113
- accessibilityState: {
114
- expanded: open
115
- },
116
- onPress: () => setOpen(v => !v),
117
- style: [styles.row, !last && styles.rowDivider],
118
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
119
- style: styles.rowLine,
120
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
121
- style: styles.markSlot,
122
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(StatusMark, {
123
- status: call.status
124
- })
125
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
126
- style: styles.rowTitle,
127
- children: call.label
128
- }), status.text ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
129
- style: [styles.rowStatus, status.tone === "danger" && styles.rowStatusDanger, status.tone === "warning" && styles.rowStatusWarning],
130
- numberOfLines: 1,
131
- children: status.text
132
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(Chevron, {
133
- size: 12,
134
- color: _sharedUi.night.color.textTertiary
135
- })]
136
- }), open && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
137
- style: styles.rowDetail,
138
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
139
- style: styles.rowTool,
140
- children: (0, _agentCore.toolTitle)(call.toolId).toUpperCase()
141
- }), call.description ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
142
- style: styles.rowDescription,
143
- children: call.description
144
- }) : null, failureDetail ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
145
- style: styles.rowFailure,
146
- children: failureDetail
147
- }) : null]
148
- })]
149
- });
150
- }
151
- const COLLAPSE_AFTER = 4;
152
-
153
- /**
154
- * More than four steps collapse to one line — "Did 15 things · 5 failed" —
155
- * with the failed and refused rows pinned so the bad news is never hidden.
156
- */
157
- function ActivityCard({
158
- calls
159
- }) {
160
- const [expanded, setExpanded] = (0, _react.useState)(false);
161
- const running = calls.some(c => c.status === "running");
162
- const collapse = calls.length > COLLAPSE_AFTER && !expanded && !running;
163
- const failed = calls.filter(c => c.status === "failed").length;
164
- const refused = calls.filter(c => c.status === "refused").length;
165
- const shown = collapse ? calls.filter(c => c.status === "failed" || c.status === "refused") : calls;
166
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
167
- style: styles.card,
168
- testID: "buoy-ask-buoy-activity",
169
- children: [collapse && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
170
- onPress: () => setExpanded(true),
171
- accessibilityRole: "button",
172
- style: [styles.row, shown.length > 0 && styles.rowDivider],
173
- testID: "buoy-ask-buoy-activity-expand",
174
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
175
- style: styles.rowLine,
176
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
177
- style: styles.rowTitle,
178
- children: ["Did ", calls.length, " things", failed ? ` · ${failed} failed` : "", refused ? ` · ${refused} refused` : ""]
179
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronRight, {
180
- size: 12,
181
- color: _sharedUi.night.color.textTertiary
182
- })]
183
- })
184
- }), shown.map((c, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)(ActivityRow, {
185
- call: c,
186
- last: i === shown.length - 1
187
- }, c.id))]
188
- });
189
- }
190
-
191
- /** Receipts and model blocks render between the activity card and the prose; Ask blocks last. */
192
- function Blocks({
193
- blocks
194
- }) {
195
- if (blocks.length === 0) return null;
196
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
197
- style: styles.blocks,
198
- children: blocks.map(({
199
- block
200
- }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_BlockRenderer.BlockRenderer, {
201
- block: block
202
- }, block.id))
203
- });
204
- }
205
- function UserMessage({
206
- message
207
- }) {
208
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
209
- style: styles.userWrap,
210
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
211
- style: styles.userBubble,
212
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
213
- style: styles.userText,
214
- selectable: true,
215
- children: message.text
216
- })
217
- })
218
- });
219
- }
220
- function AssistantMessage({
221
- message,
222
- onRetry
223
- }) {
224
- const {
225
- showThinking
226
- } = (0, _useAskBuoySettings.useAskBuoySettings)();
227
- const running = message.toolCalls.some(c => c.status === "running");
228
- const waiting = !!message.streaming && message.text.length === 0 && !running;
229
- const askBlocks = message.blocks.filter(b => (0, _agentCore.isAskBlock)(b.block));
230
- const showBlocks = message.blocks.filter(b => !(0, _agentCore.isAskBlock)(b.block));
231
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
232
- style: styles.assistantWrap,
233
- children: [message.toolCalls.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(ActivityCard, {
234
- calls: message.toolCalls
235
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Blocks, {
236
- blocks: showBlocks
237
- }), message.text.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Markdown.Markdown, {
238
- text: message.text,
239
- style: styles.assistantText
240
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Blocks, {
241
- blocks: askBlocks
242
- }), showThinking && !message.streaming && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ThinkingStrip.ThinkingStrip, {
243
- message: message
244
- }), waiting && /*#__PURE__*/(0, _jsxRuntime.jsx)(_TypingDots.TypingDots, {}), message.error && /*#__PURE__*/(0, _jsxRuntime.jsx)(ErrorNote, {
245
- error: message.error,
246
- onRetry: onRetry
247
- })]
248
- });
249
- }
250
-
251
- /**
252
- * A failed turn. The headline is for the tester ("couldn't reach the
253
- * endpoint"); the raw message stays underneath for whoever gets the bug
254
- * report, because "fetch failed: UnexpectedException: The network connection
255
- * was lost" is what a developer needs and nothing a tester can act on.
256
- */
257
- function ErrorNote({
258
- error,
259
- onRetry
260
- }) {
261
- const network = /fetch failed|network|ECONN|timed? ?out|socket|abort/i.test(error);
262
- const headline = network ? "Couldn't reach your AI endpoint. Check the connection and try again." : "Something went wrong with that turn.";
263
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
264
- style: styles.errorBox,
265
- testID: "buoy-ask-buoy-error",
266
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.AlertTriangle, {
267
- size: 14,
268
- color: _sharedUi.night.color.danger
269
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
270
- style: styles.errorBody,
271
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
272
- style: styles.errorText,
273
- children: headline
274
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
275
- style: styles.errorDetail,
276
- selectable: true,
277
- children: error
278
- }), onRetry && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
279
- testID: "buoy-ask-buoy-retry",
280
- accessibilityRole: "button",
281
- onPress: onRetry,
282
- style: ({
283
- pressed
284
- }) => [styles.retry, pressed && styles.retryPressed],
285
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
286
- style: styles.retryText,
287
- children: "Retry"
288
- })
289
- })]
290
- })]
291
- });
292
- }
293
-
294
- /**
295
- * The whole conversation as plain text — the only thing Copy ever produces,
296
- * and the only way a session leaves the DEVICE (what it saves to disk for a
297
- * reload goes nowhere — see `transcriptPersistence`).
298
- *
299
- * Plain text on purpose. This lands in a Slack message, a ticket comment or a
300
- * notes file, all of which are read by a person; a JSON document is a worse
301
- * version of that everywhere except a parser, and nothing here parses it.
302
- *
303
- * With `Show agent thinking` on it carries the working too — the reasoning and
304
- * each step with its parameters — because reading the run somewhere that is
305
- * not a phone is the entire point of that setting.
306
- */
307
- function transcriptToText(messages, withTrace = false) {
308
- const lines = [];
309
- for (const m of messages) {
310
- if (m.role === "user") {
311
- lines.push(`You: ${m.text}`);
312
- continue;
313
- }
314
- if (withTrace) {
315
- lines.push(...(0, _traceText.traceToText)(m));
316
- } else {
317
- for (const c of m.toolCalls) {
318
- const status = c.status === "failed" || c.status === "refused" ? ` (${c.status})` : "";
319
- lines.push(` · ${c.label}${c.summary ? ` — ${c.summary}` : ""}${status}`);
320
- }
321
- }
322
- if (m.text) lines.push(`Ask Buoy: ${m.text}`);
323
- if (m.error) lines.push(` ! ${m.error}`);
324
- }
325
- return lines.join("\n");
326
- }
327
-
328
- /** Copy, with the result visible for a moment. Shares the header's behaviour. */
329
- function CopyPill({
330
- testID,
331
- label,
332
- getText
333
- }) {
334
- const {
335
- copied,
336
- copy
337
- } = (0, _useCopyAction.useCopyAction)(getText);
338
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
339
- testID: testID,
340
- accessibilityRole: "button",
341
- accessibilityLabel: label,
342
- onPress: copy,
343
- style: ({
344
- pressed
345
- }) => [styles.copyBtn, styles.iconBtn, pressed && styles.copyPressed],
346
- children: [copied ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Check, {
347
- size: 11,
348
- color: _sharedUi.night.color.accent
349
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Copy, {
350
- size: 11,
351
- color: _sharedUi.night.color.textSecondary
352
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
353
- style: [styles.copyText, copied && styles.copiedText],
354
- children: copied ? "Copied" : label
355
- })]
356
- });
357
- }
358
-
359
- /**
360
- * Under a finished answer: one Copy, and nothing else.
361
- *
362
- * It is on EVERY answer rather than only the newest, because the moment you
363
- * decide to keep a conversation is usually a few replies after the one that
364
- * went wrong, and scrolling to the bottom to find the button is friction at
365
- * exactly the wrong time. Every one of them copies the WHOLE chat — one button
366
- * with one meaning beats four pills the reader has to choose between.
367
- */
368
- function TranscriptActions({
369
- messages
370
- }) {
371
- const {
372
- showThinking
373
- } = (0, _useAskBuoySettings.useAskBuoySettings)();
374
- const getText = (0, _react.useCallback)(() => transcriptToText(messages, showThinking), [messages, showThinking]);
375
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
376
- style: styles.transcriptActions,
377
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(CopyPill, {
378
- testID: "buoy-ask-buoy-copy",
379
- label: "Copy",
380
- getText: getText
381
- })
382
- });
383
- }
384
- function Row({
385
- message,
386
- messages,
387
- onRetry
388
- }) {
389
- if (message.role === "user") return /*#__PURE__*/(0, _jsxRuntime.jsx)(UserMessage, {
390
- message: message
391
- });
392
- const finished = !message.streaming && !message.error;
393
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
394
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(AssistantMessage, {
395
- message: message,
396
- onRetry: onRetry
397
- }), finished && /*#__PURE__*/(0, _jsxRuntime.jsx)(TranscriptActions, {
398
- messages: messages
399
- })]
400
- });
401
- }
402
- function MessageList({
403
- messages,
404
- ListHeaderComponent,
405
- ListEmptyComponent,
406
- ListFooterComponent,
407
- onRetry
408
- }) {
409
- const ref = (0, _react.useRef)(null);
410
- // Only auto-scroll when the user is already at the bottom. Yanking them back
411
- // down while they are reading an earlier answer is the classic chat-UI sin.
412
- //
413
- // "At the bottom" is decided from the USER's gestures, not from every scroll
414
- // event. An animated scrollToEnd fires intermediate events while the content
415
- // is still growing under it, and reading those as "the user scrolled up"
416
- // silently unpinned the list mid-answer — the reply then streamed in below
417
- // the fold and the last thing on screen was the question.
418
- const pinned = (0, _react.useRef)(true);
419
- const dragging = (0, _react.useRef)(false);
420
- const measure = (0, _react.useCallback)(e => {
421
- const {
422
- contentOffset,
423
- contentSize,
424
- layoutMeasurement
425
- } = e.nativeEvent;
426
- const distance = contentSize.height - layoutMeasurement.height - contentOffset.y;
427
- pinned.current = distance < 80;
428
- }, []);
429
- const onScrollBeginDrag = (0, _react.useCallback)(() => {
430
- dragging.current = true;
431
- }, []);
432
- const onScroll = (0, _react.useCallback)(e => {
433
- if (dragging.current) measure(e);
434
- }, [measure]);
435
- const onScrollEndDrag = (0, _react.useCallback)(e => {
436
- dragging.current = false;
437
- measure(e);
438
- }, [measure]);
439
- const scrollToEnd = (0, _react.useCallback)(() => {
440
- if (!pinned.current) return;
441
- // The size change fires before the new row has finished laying out its
442
- // wrapped text; one frame later the end really is the end.
443
- ref.current?.scrollToEnd({
444
- animated: false
445
- });
446
- requestAnimationFrame(() => ref.current?.scrollToEnd({
447
- animated: false
448
- }));
449
- }, []);
450
-
451
- // A row can grow without the list reporting a size change in the same tick
452
- // (an error box appended to the last message). Follow the transcript too.
453
- const last = messages[messages.length - 1];
454
- const tail = last ? `${last.id}:${last.text.length}:${last.toolCalls.length}:${last.error ?? ""}` : "";
455
- (0, _react.useEffect)(() => {
456
- scrollToEnd();
457
- }, [tail, scrollToEnd]);
458
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
459
- ref: ref,
460
- testID: "buoy-ask-buoy-messages-scroll",
461
- style: styles.list,
462
- contentContainerStyle: styles.listContent,
463
- data: messages,
464
- keyExtractor: m => m.id,
465
- renderItem: ({
466
- item
467
- }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
468
- message: item,
469
- messages: messages,
470
- onRetry: item.id === last?.id ? onRetry : undefined
471
- }),
472
- onScroll: onScroll,
473
- onScrollBeginDrag: onScrollBeginDrag,
474
- onScrollEndDrag: onScrollEndDrag,
475
- onMomentumScrollEnd: measure,
476
- scrollEventThrottle: 32,
477
- onContentSizeChange: scrollToEnd
478
- // Mandatory with a focused input below: without it the first tap after
479
- // typing only dismisses the keyboard and the button never fires.
480
- ,
481
- keyboardShouldPersistTaps: "handled",
482
- keyboardDismissMode: "interactive",
483
- ListHeaderComponent: ListHeaderComponent,
484
- ListEmptyComponent: ListEmptyComponent,
485
- ListFooterComponent: ListFooterComponent
486
- });
487
- }
488
- const styles = _reactNative.StyleSheet.create({
489
- list: {
490
- flex: 1,
491
- backgroundColor: "transparent"
492
- },
493
- listContent: {
494
- paddingHorizontal: _sharedUi.night.gutter,
495
- paddingTop: 12,
496
- paddingBottom: 16,
497
- gap: 16,
498
- flexGrow: 1
499
- },
500
- // User
501
- userWrap: {
502
- alignItems: "flex-end"
503
- },
504
- userBubble: {
505
- maxWidth: "84%",
506
- paddingHorizontal: 14,
507
- paddingVertical: 9,
508
- borderRadius: 18,
509
- borderBottomRightRadius: 6,
510
- backgroundColor: _sharedUi.night.color.accentFill,
511
- borderWidth: _reactNative.StyleSheet.hairlineWidth,
512
- borderColor: _sharedUi.night.color.accentBorder
513
- },
514
- userText: {
515
- color: _sharedUi.night.color.text,
516
- fontSize: _sharedUi.night.font.row,
517
- lineHeight: 21
518
- },
519
- // Assistant
520
- assistantWrap: {
521
- alignItems: "stretch",
522
- gap: 10
523
- },
524
- blocks: {
525
- gap: 10
526
- },
527
- assistantText: {
528
- color: _sharedUi.night.color.text,
529
- fontSize: _sharedUi.night.font.row,
530
- lineHeight: 22,
531
- paddingHorizontal: 2
532
- },
533
- // Activity card
534
- card: {
535
- borderRadius: _sharedUi.night.radius.card,
536
- borderWidth: _reactNative.StyleSheet.hairlineWidth,
537
- borderColor: _sharedUi.night.color.border,
538
- backgroundColor: _sharedUi.night.color.surface,
539
- overflow: "hidden"
540
- },
541
- row: {
542
- paddingHorizontal: 12,
543
- paddingVertical: 10
544
- },
545
- rowDivider: {
546
- borderBottomWidth: _reactNative.StyleSheet.hairlineWidth,
547
- borderBottomColor: _sharedUi.night.color.separator
548
- },
549
- rowLine: {
550
- flexDirection: "row",
551
- alignItems: "center",
552
- gap: 10
553
- },
554
- markSlot: {
555
- width: 18,
556
- height: 18,
557
- alignItems: "center",
558
- justifyContent: "center"
559
- },
560
- mark: {
561
- width: 16,
562
- height: 16,
563
- borderRadius: 8,
564
- alignItems: "center",
565
- justifyContent: "center"
566
- },
567
- markOk: {
568
- backgroundColor: _sharedUi.night.color.accent
569
- },
570
- markFailed: {
571
- backgroundColor: _sharedUi.night.color.danger
572
- },
573
- markRefused: {
574
- backgroundColor: _sharedUi.night.color.warning
575
- },
576
- rowTitle: {
577
- flex: 1,
578
- color: _sharedUi.night.color.text,
579
- fontSize: _sharedUi.night.font.body,
580
- lineHeight: 19
581
- },
582
- rowStatus: {
583
- color: _sharedUi.night.color.textTertiary,
584
- fontSize: _sharedUi.night.font.caption,
585
- maxWidth: 120
586
- },
587
- rowStatusDanger: {
588
- color: _sharedUi.night.color.danger
589
- },
590
- rowStatusWarning: {
591
- color: _sharedUi.night.color.warning
592
- },
593
- rowDetail: {
594
- paddingLeft: 28,
595
- paddingTop: 8,
596
- gap: 4
597
- },
598
- rowTool: {
599
- color: _sharedUi.night.color.textTertiary,
600
- fontSize: _sharedUi.night.font.micro,
601
- fontWeight: "600",
602
- letterSpacing: 0.8
603
- },
604
- rowDescription: {
605
- color: _sharedUi.night.color.textSecondary,
606
- fontSize: _sharedUi.night.font.caption,
607
- lineHeight: 18
608
- },
609
- rowFailure: {
610
- color: _sharedUi.night.color.danger,
611
- fontSize: _sharedUi.night.font.caption,
612
- lineHeight: 18
613
- },
614
- // Error
615
- errorBox: {
616
- flexDirection: "row",
617
- alignItems: "flex-start",
618
- gap: 8,
619
- paddingHorizontal: 12,
620
- paddingVertical: 10,
621
- borderRadius: _sharedUi.night.radius.row,
622
- backgroundColor: _sharedUi.night.color.dangerSoft
623
- },
624
- errorBody: {
625
- flex: 1,
626
- gap: 4
627
- },
628
- errorText: {
629
- color: _sharedUi.night.color.danger,
630
- fontSize: _sharedUi.night.font.caption,
631
- fontWeight: "600",
632
- lineHeight: 18
633
- },
634
- errorDetail: {
635
- color: _sharedUi.night.color.textSecondary,
636
- fontSize: _sharedUi.night.font.micro,
637
- lineHeight: 15
638
- },
639
- retry: {
640
- alignSelf: "flex-start",
641
- marginTop: 6,
642
- paddingHorizontal: 14,
643
- paddingVertical: 7,
644
- borderRadius: _sharedUi.night.radius.row,
645
- backgroundColor: _sharedUi.night.color.button
646
- },
647
- retryPressed: {
648
- opacity: 0.7
649
- },
650
- retryText: {
651
- color: _sharedUi.night.color.accent,
652
- fontSize: _sharedUi.night.font.caption,
653
- fontWeight: "600"
654
- },
655
- transcriptActions: {
656
- flexDirection: "row",
657
- marginTop: 8
658
- },
659
- copyBtn: {
660
- paddingHorizontal: 10,
661
- paddingVertical: 5,
662
- borderRadius: _sharedUi.night.radius.badge,
663
- backgroundColor: _sharedUi.night.color.fill
664
- },
665
- iconBtn: {
666
- flexDirection: "row",
667
- alignItems: "center",
668
- gap: 4,
669
- paddingHorizontal: 8
670
- },
671
- copyPressed: {
672
- opacity: 0.7
673
- },
674
- copyText: {
675
- color: _sharedUi.night.color.textSecondary,
676
- fontSize: _sharedUi.night.font.micro,
677
- fontWeight: "600"
678
- },
679
- copiedText: {
680
- color: _sharedUi.night.color.accent
681
- }
682
- });
683
- //# sourceMappingURL=MessageList.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.MessageList=MessageList,exports.transcriptToText=transcriptToText;var _react=require("react"),_reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_agentCore=require("@buoy-gg/agent-core"),_BlockRenderer=require("../blocks/BlockRenderer"),_blockText=require("../blocks/blockText"),_activityGroups=require("../store/activityGroups"),_blockPlacement=require("../store/blockPlacement"),_askBuoyStore=require("../store/askBuoyStore"),_Markdown=require("./Markdown"),_ThinkingStrip=require("./ThinkingStrip"),_TypingDots=require("./TypingDots"),_useCopyAction=require("./useCopyAction"),_traceText=require("../store/traceText"),_useAskBuoySettings=require("../store/useAskBuoySettings"),_jsxRuntime=require("react/jsx-runtime");function StatusMark({status:e}){switch(e){case"running":return(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_sharedUi.night.color.textSecondary});case"ok":return(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.mark,styles.markOk],children:(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:10,color:_sharedUi.night.color.onAccent})});case"failed":return(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.mark,styles.markFailed],children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:10,color:_sharedUi.night.color.text})});case"refused":return(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.mark,styles.markRefused],children:(0,_jsxRuntime.jsx)(_sharedUi.AlertTriangle,{size:10,color:_sharedUi.night.color.onAccent})});case"declined":case"stopped":return(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.mark,styles.markNotRun],children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.markNotRunBar})})}}function statusText(e){return"running"===e.status?{text:"",tone:"muted"}:"refused"===e.status?{text:"Refused",tone:"warning"}:"failed"===e.status?{text:"Failed",tone:"danger"}:"declined"===e.status?{text:"You declined",tone:"muted"}:"stopped"===e.status?{text:"Not run — stopped",tone:"muted"}:"verified"===e.verification?.status?{text:"Verified",tone:"ok"}:"unverified"===e.verification?.status?{text:"Done · not yet visible",tone:"muted"}:"failed"===e.verification?.status?{text:"Done · check failed",tone:"warning"}:{text:e.summary||"Done",tone:"muted"}}const isExceptional=e=>"failed"===e.status||"refused"===e.status||"declined"===e.status||"stopped"===e.status;function ActivityRow({call:e,receipts:t,last:s}){const[r,i]=(0,_react.useState)(!1),o=statusText(e),n=r?_sharedUi.ChevronDown:_sharedUi.ChevronRight,a="failed"===e.status&&e.summary&&"Failed"!==e.summary?e.summary:null;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:[styles.row,!s&&styles.rowDivider],children:[(0,_jsxRuntime.jsxs)(_reactNative.Pressable,{testID:`buoy-ask-buoy-tool-${e.toolId}`,accessibilityRole:"button",accessibilityLabel:`${e.label}, ${o.text||"running"}`,accessibilityState:{expanded:r},onPress:()=>i(e=>!e),children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowLine,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.markSlot,children:(0,_jsxRuntime.jsx)(StatusMark,{status:e.status})}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,children:e.label}),o.text?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.rowStatus,"danger"===o.tone&&styles.rowStatusDanger,"warning"===o.tone&&styles.rowStatusWarning,"ok"===o.tone&&styles.rowStatusOk],numberOfLines:1,children:o.text}):null,(0,_jsxRuntime.jsx)(n,{size:12,color:_sharedUi.night.color.textTertiary})]}),r&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowDetail,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTool,children:(0,_agentCore.toolTitle)(e.toolId).toUpperCase()}),e.description?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowDescription,children:e.description}):null,a?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowFailure,children:a}):null,e.verification?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.rowDescription,"failed"===e.verification.status&&styles.rowFailure,"verified"===e.verification.status&&styles.rowVerified],testID:`buoy-ask-buoy-verification-${e.verification.status}`,children:e.verification.detail}):null]})]}),r&&t.length>0&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.rowReceipts,testID:`buoy-ask-buoy-tool-receipt-${e.toolId}`,children:t.map(e=>(0,_jsxRuntime.jsx)(_BlockRenderer.BlockRenderer,{block:e},e.id))})]})}function ReadsGroup({label:e,count:t,calls:s,receipts:r,last:i}){const[o,n]=(0,_react.useState)(!1),a=o?_sharedUi.ChevronDown:_sharedUi.ChevronRight;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:!i&&!o&&styles.rowDivider,children:[(0,_jsxRuntime.jsx)(_reactNative.Pressable,{testID:"buoy-ask-buoy-reads-group",accessibilityRole:"button",accessibilityLabel:`${e}, ${t} reads`,accessibilityState:{expanded:o},onPress:()=>n(e=>!e),style:[styles.row,o&&styles.rowDivider],children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowLine,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.markSlot,children:(0,_jsxRuntime.jsx)(StatusMark,{status:"ok"})}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,children:e}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.rowStatus,numberOfLines:1,children:[t," reads"]}),(0,_jsxRuntime.jsx)(a,{size:12,color:_sharedUi.night.color.textTertiary})]})}),o&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.groupBody,children:s.map((e,t)=>(0,_jsxRuntime.jsx)(ActivityRow,{call:e,receipts:r.get(e.id)??[],last:i&&t===s.length-1},e.id))})]})}function ActivityCard({calls:e,receipts:t}){const s=(0,_activityGroups.groupCalls)(e);return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.card,testID:"buoy-ask-buoy-activity",children:s.map((e,r)=>"reads"===e.kind?(0,_jsxRuntime.jsx)(ReadsGroup,{label:e.label,count:e.count,calls:e.calls,receipts:t,last:r===s.length-1},e.id):(0,_jsxRuntime.jsx)(ActivityRow,{call:e.call,receipts:t.get(e.call.id)??[],last:r===s.length-1},e.call.id))})}function Blocks({blocks:e}){return 0===e.length?null:(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.blocks,children:e.map(({block:e})=>(0,_jsxRuntime.jsx)(_BlockRenderer.BlockRenderer,{block:e},e.id))})}function SystemLine({message:e}){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.systemLine,testID:"buoy-ask-buoy-system-line",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.systemText,children:e.text})})}function UserMessage({message:e}){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.userWrap,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.userBubble,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.userText,selectable:!0,children:e.text})})})}function AssistantMessage({message:e,onRetry:t,waitingOnUser:s}){const{showThinking:r}=(0,_useAskBuoySettings.useAskBuoySettings)(),i=!!e.streaming&&!s,{nested:o,afterText:n,ask:a}=(0,_blockPlacement.placeBlocks)(e.blocks,e.toolCalls.map(e=>e.id));return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.assistantWrap,children:[e.toolCalls.length>0&&(0,_jsxRuntime.jsx)(ActivityCard,{calls:e.toolCalls,receipts:o}),e.text.length>0&&(0,_jsxRuntime.jsx)(_Markdown.Markdown,{text:e.text,style:styles.assistantText}),(0,_jsxRuntime.jsx)(Blocks,{blocks:n}),(0,_jsxRuntime.jsx)(Blocks,{blocks:a}),r&&!e.streaming&&(0,_jsxRuntime.jsx)(_ThinkingStrip.ThinkingStrip,{message:e}),i&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.waitingRow,children:[(0,_jsxRuntime.jsx)(_TypingDots.TypingDots,{}),e.waiting?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.waitingText,testID:"buoy-ask-buoy-waiting",children:e.waiting}):null]}),e.error&&(0,_jsxRuntime.jsx)(ErrorNote,{error:e.error,onRetry:t}),e.stopped&&!e.error&&(0,_jsxRuntime.jsx)(StoppedNote,{onRetry:t,changed:e.toolCalls.some(e=>"ok"===e.status&&!!e.effect&&"read"!==e.effect)})]})}function StoppedNote({onRetry:e,changed:t}){return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.stoppedBox,testID:"buoy-ask-buoy-stopped",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stoppedText,children:t?"Stopped. Changes already made are listed above.":"Stopped."}),e&&(0,_jsxRuntime.jsx)(_reactNative.Pressable,{testID:"buoy-ask-buoy-retry",accessibilityRole:"button",accessibilityLabel:"Try again",onPress:e,style:({pressed:e})=>[styles.retry,e&&styles.retryPressed],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.retryText,children:"Try again"})})]})}function ErrorNote({error:e,onRetry:t}){const s=/fetch failed|network|ECONN|timed? ?out|socket/i.test(e)?"Couldn't reach your AI endpoint. Check the connection and try again.":"Something went wrong with that turn.";return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.errorBox,testID:"buoy-ask-buoy-error",children:[(0,_jsxRuntime.jsx)(_sharedUi.AlertTriangle,{size:14,color:_sharedUi.night.color.danger}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.errorBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.errorText,children:s}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.errorDetail,selectable:!0,children:e}),t&&(0,_jsxRuntime.jsx)(_reactNative.Pressable,{testID:"buoy-ask-buoy-retry",accessibilityRole:"button",accessibilityLabel:"Try again",onPress:t,style:({pressed:e})=>[styles.retry,e&&styles.retryPressed],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.retryText,children:"Try again"})})]})]})}function transcriptToText(e,t=!1){const s=[];for(const r of e)if("user"!==r.role)if(r.system)s.push(` — ${r.text}`);else{if(t)s.push(...(0,_traceText.traceToText)(r));else for(const e of r.toolCalls){const t=isExceptional(e)?` (${e.status})`:"";s.push(` · ${e.label}${e.summary?` — ${e.summary}`:""}${t}`)}r.text&&s.push(`Ask Buoy: ${r.text}`);for(const e of(0,_blockText.blocksToText)(r.blocks.map(e=>e.block)))s.push(e);r.error&&s.push(` ! ${r.error}`),r.stopped&&!r.error&&s.push(" ! Stopped by the user.")}else s.push(`You: ${r.text}`);return s.join("\n")}function CopyPill({testID:e,label:t,getText:s}){const{copied:r,copy:i}=(0,_useCopyAction.useCopyAction)(s);return(0,_jsxRuntime.jsxs)(_reactNative.Pressable,{testID:e,accessibilityRole:"button",accessibilityLabel:t,onPress:i,style:({pressed:e})=>[styles.copyBtn,styles.iconBtn,e&&styles.copyPressed],children:[r?(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:11,color:_sharedUi.night.color.accent}):(0,_jsxRuntime.jsx)(_sharedUi.Copy,{size:11,color:_sharedUi.night.color.textSecondary}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.copyText,r&&styles.copiedText],children:r?"Copied":t})]})}function TranscriptActions({message:e}){const{showThinking:t}=(0,_useAskBuoySettings.useAskBuoySettings)(),s=(0,_react.useCallback)(()=>transcriptToText(_askBuoyStore.askBuoyStore.getState().messages,t),[t]),r=(0,_activityGroups.turnFooter)(e);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.transcriptActions,children:[r?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.turnFooter,testID:"buoy-ask-buoy-turn-footer",children:r}):null,(0,_jsxRuntime.jsx)(CopyPill,{testID:"buoy-ask-buoy-copy",label:"Copy conversation",getText:s})]})}const Row=(0,_react.memo)(function({message:e,onRetry:t,waitingOnUser:s}){if("user"===e.role)return(0,_jsxRuntime.jsx)(UserMessage,{message:e});if(e.system)return(0,_jsxRuntime.jsx)(SystemLine,{message:e});const r=!e.streaming&&!e.error;return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(AssistantMessage,{message:e,onRetry:t,waitingOnUser:s}),r&&(0,_jsxRuntime.jsx)(TranscriptActions,{message:e})]})});function MessageList({messages:e,ListHeaderComponent:t,ListEmptyComponent:s,ListFooterComponent:r,onRetry:i,waitingOnUser:o}){const n=(0,_react.useRef)(null),a=(0,_react.useRef)(!0),l=(0,_react.useRef)(!1),c=(0,_react.useCallback)(e=>{const{contentOffset:t,contentSize:s,layoutMeasurement:r}=e.nativeEvent,i=s.height-r.height-t.y;a.current=i<80},[]),d=(0,_react.useCallback)(()=>{l.current=!0},[]),u=(0,_react.useCallback)(e=>{l.current&&c(e)},[c]),h=(0,_react.useCallback)(e=>{l.current=!1,c(e)},[c]),x=(0,_react.useCallback)(()=>{a.current&&(n.current?.scrollToEnd({animated:!1}),requestAnimationFrame(()=>n.current?.scrollToEnd({animated:!1})))},[]),y=e[e.length-1],g=y?`${y.id}:${y.text.length}:${y.toolCalls.length}:${y.error??""}`:"";return(0,_react.useEffect)(()=>{x()},[g,x]),(0,_jsxRuntime.jsx)(_reactNative.FlatList,{ref:n,testID:"buoy-ask-buoy-messages-scroll",style:styles.list,contentContainerStyle:styles.listContent,data:e,keyExtractor:e=>e.id,renderItem:({item:e})=>(0,_jsxRuntime.jsx)(Row,{message:e,onRetry:e.id===y?.id?i:void 0,waitingOnUser:e.id===y?.id&&o}),onScroll:u,onScrollBeginDrag:d,onScrollEndDrag:h,onMomentumScrollEnd:c,scrollEventThrottle:32,onContentSizeChange:x,keyboardShouldPersistTaps:"handled",keyboardDismissMode:"interactive",ListHeaderComponent:t,ListEmptyComponent:s,ListFooterComponent:r})}const styles=_reactNative.StyleSheet.create({list:{flex:1,backgroundColor:"transparent"},listContent:{paddingHorizontal:_sharedUi.night.gutter,paddingTop:12,paddingBottom:16,gap:16,flexGrow:1},userWrap:{alignItems:"flex-end"},userBubble:{maxWidth:"84%",paddingHorizontal:14,paddingVertical:9,borderRadius:18,borderBottomRightRadius:6,backgroundColor:_sharedUi.night.color.accentFill,borderWidth:_reactNative.StyleSheet.hairlineWidth,borderColor:_sharedUi.night.color.accentBorder},userText:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row,lineHeight:21},systemLine:{alignSelf:"stretch",paddingHorizontal:12,paddingVertical:7,borderRadius:_sharedUi.night.radius.row,backgroundColor:_sharedUi.night.color.fill},systemText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.micro,lineHeight:16,textAlign:"center"},assistantWrap:{alignItems:"stretch",gap:10},blocks:{gap:10},waitingRow:{flexDirection:"row",alignItems:"center",gap:8},waitingText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption},assistantText:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row,lineHeight:22,paddingHorizontal:2},card:{borderRadius:_sharedUi.night.radius.card,borderWidth:_reactNative.StyleSheet.hairlineWidth,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.surface,overflow:"hidden"},row:{paddingHorizontal:12,paddingVertical:10},rowDivider:{borderBottomWidth:_reactNative.StyleSheet.hairlineWidth,borderBottomColor:_sharedUi.night.color.separator},rowLine:{flexDirection:"row",alignItems:"center",gap:10},markSlot:{width:18,height:18,alignItems:"center",justifyContent:"center"},mark:{width:16,height:16,borderRadius:8,alignItems:"center",justifyContent:"center"},markOk:{backgroundColor:_sharedUi.night.color.accent},markFailed:{backgroundColor:_sharedUi.night.color.danger},markRefused:{backgroundColor:_sharedUi.night.color.warning},markNotRun:{borderWidth:1.5,borderColor:_sharedUi.night.color.textTertiary},markNotRunBar:{width:7,height:1.5,borderRadius:1,backgroundColor:_sharedUi.night.color.textSecondary},rowTitle:{flex:1,color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.body,lineHeight:19},rowStatus:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,maxWidth:120},rowStatusDanger:{color:_sharedUi.night.color.danger},rowStatusWarning:{color:_sharedUi.night.color.warning},rowStatusOk:{color:_sharedUi.night.color.accent},rowVerified:{color:_sharedUi.night.color.accent},rowDetail:{paddingLeft:28,paddingTop:8,gap:4},rowTool:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.micro,fontWeight:"600",letterSpacing:.8},rowDescription:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,lineHeight:18},rowFailure:{color:_sharedUi.night.color.danger,fontSize:_sharedUi.night.font.caption,lineHeight:18},rowReceipts:{paddingTop:10,gap:10},groupBody:{paddingLeft:14,backgroundColor:_sharedUi.night.color.fill},stoppedBox:{alignItems:"flex-start",gap:2,paddingHorizontal:12,paddingVertical:8},stoppedText:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,lineHeight:18},errorBox:{flexDirection:"row",alignItems:"flex-start",gap:8,paddingHorizontal:12,paddingVertical:10,borderRadius:_sharedUi.night.radius.row,backgroundColor:_sharedUi.night.color.dangerSoft},errorBody:{flex:1,gap:4},errorText:{color:_sharedUi.night.color.danger,fontSize:_sharedUi.night.font.caption,fontWeight:"600",lineHeight:18},errorDetail:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.micro,lineHeight:15},retry:{alignSelf:"flex-start",marginTop:6,paddingHorizontal:14,paddingVertical:7,borderRadius:_sharedUi.night.radius.row,backgroundColor:_sharedUi.night.color.button},retryPressed:{opacity:.7},retryText:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.caption,fontWeight:"600"},transcriptActions:{flexDirection:"row",alignItems:"center",gap:10,marginTop:8},turnFooter:{flex:1,color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.micro,fontVariant:["tabular-nums"]},copyBtn:{paddingHorizontal:10,paddingVertical:5,borderRadius:_sharedUi.night.radius.badge,backgroundColor:_sharedUi.night.color.fill},iconBtn:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:8},copyPressed:{opacity:.7},copyText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.micro,fontWeight:"600"},copiedText:{color:_sharedUi.night.color.accent}});