@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,164 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AskBuoyHeader = AskBuoyHeader;
7
- var _react = require("react");
8
- var _reactNative = require("react-native");
9
- var _sharedUi = require("@buoy-gg/shared-ui");
10
- var _useCopyAction = require("./useCopyAction");
11
- var _jsxRuntime = require("react/jsx-runtime");
12
- /**
13
- * The sheet header.
14
- *
15
- * Built on the shared `ModalHeader` so it matches Console, Network and Events
16
- * 1:1 — the stock JsModal header was designed for a single centred title and
17
- * paints its "Double tap: Toggle • Triple tap: Close" hint through the middle
18
- * of it, which is how "Ask Buoy" ended up overprinted by grey italics.
19
- *
20
- * The subtitle is the one piece of live status the sheet has: what the agent
21
- * is doing right now, in words a tester can act on. "Thinking…" while a
22
- * response is streaming with no tool in flight, the current tool's title
23
- * while one runs, and the reachable tool count at rest so a "why can't it
24
- * see my network calls" question has an answer in the header.
25
- *
26
- * "New conversation" moved up here from a 11pt text link under the composer.
27
- * A reset that lives under the keyboard is a reset nobody finds. Copy sits
28
- * beside it for the same reason: the transcript actions under the newest
29
- * answer are only reachable once you have scrolled back down to it.
30
- */
31
-
32
- /**
33
- * Slower than the sprite's default 140ms.
34
- *
35
- * This mascot is ambient status a user stares at for the length of a turn,
36
- * not a moment of delight they glance at once — at the stock tick it read as
37
- * fidgeting in the corner of the eye while you were trying to read the
38
- * answer next to it. Every other placement keeps the default.
39
- */const HEADER_TICK_MS = 200;
40
-
41
- /** No conversation to copy — the button is left out rather than left dead. */
42
- const NO_TRANSCRIPT = () => "";
43
- function AskBuoyHeader({
44
- configured,
45
- busy,
46
- failed = false,
47
- activeLabel,
48
- toolCount,
49
- hasMessages,
50
- onBack,
51
- onReset,
52
- getTranscript,
53
- onOpenSettings
54
- }) {
55
- const {
56
- copied,
57
- copy
58
- } = (0, _useCopyAction.useCopyAction)(getTranscript ?? NO_TRANSCRIPT);
59
-
60
- /**
61
- * ONE mascot state per turn, held to the end of it.
62
- *
63
- * `activeLabel` drops to null in the gap between two tool calls, so deriving
64
- * the state from it directly flipped robot → thinking → robot on every
65
- * boundary. A turn that runs four tools swapped the sprite eight times in
66
- * about three seconds — a strobe that reads as a glitch, not as progress.
67
- * So the robot latches: once this turn has driven a tool it stays `robot`
68
- * until the turn ends, which is also the honest summary of that turn.
69
- *
70
- * The SUBTITLE still tracks each call, because updating a line of text is
71
- * informative where restarting an animation is just noise.
72
- */
73
- const [droveTool, setDroveTool] = (0, _react.useState)(false);
74
- (0, _react.useEffect)(() => {
75
- if (!busy) setDroveTool(false);else if (activeLabel) setDroveTool(true);
76
- }, [busy, activeLabel]);
77
-
78
- /**
79
- * Otto mirrors the subtitle, never contradicts it. This is the one place in
80
- * the product where a mascot earns continuous presence: the user is waiting
81
- * on a machine and the header is the only thing reporting on it.
82
- *
83
- * `robot` while a tool runs is literal — the agent IS driving the tools.
84
- */
85
- const otto = !configured ? "confused" : failed ? "error" : busy ? activeLabel || droveTool ? "robot" : "thinking" : "idle";
86
- const subtitle = !configured ? "Not set up in this app" : busy ? activeLabel ? `${activeLabel}…` : "Thinking…" : toolCount > 0 ? `Ready · ${toolCount} tool${toolCount === 1 ? "" : "s"} available` : "Ready";
87
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
88
- children: [onBack ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
89
- onBack: onBack
90
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
91
- style: styles.otto,
92
- testID: "buoy-ask-buoy-otto",
93
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Otto, {
94
- state: otto,
95
- pixelSize: 2,
96
- tickMs: HEADER_TICK_MS,
97
- water: false
98
- })
99
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
100
- title: "Ask Buoy",
101
- subtitle: subtitle,
102
- testID: "buoy-ask-buoy-title"
103
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions, {
104
- children: [getTranscript ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
105
- testID: "buoy-ask-buoy-copy-chat",
106
- accessibilityRole: "button",
107
- accessibilityLabel: copied ? "Conversation copied" : "Copy conversation",
108
- disabled: !hasMessages,
109
- onPress: copy,
110
- style: [styles.actionBtn, !hasMessages && styles.actionBtnDisabled],
111
- children: copied ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Check, {
112
- size: 14,
113
- color: _sharedUi.night.color.accent
114
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Copy, {
115
- size: 14,
116
- color: hasMessages ? _sharedUi.night.color.textSecondary : _sharedUi.night.color.textTertiary
117
- })
118
- }) : null, onOpenSettings ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
119
- testID: "buoy-ask-buoy-settings",
120
- accessibilityRole: "button",
121
- accessibilityLabel: "Settings",
122
- onPress: onOpenSettings,
123
- style: styles.actionBtn,
124
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Settings, {
125
- size: 14,
126
- color: _sharedUi.night.color.textSecondary
127
- })
128
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
129
- testID: "buoy-ask-buoy-reset",
130
- accessibilityRole: "button",
131
- accessibilityLabel: "New conversation",
132
- disabled: !hasMessages,
133
- onPress: onReset,
134
- style: [styles.actionBtn, !hasMessages && styles.actionBtnDisabled],
135
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Plus, {
136
- size: 14,
137
- color: hasMessages ? _sharedUi.night.color.textSecondary : _sharedUi.night.color.textTertiary
138
- })
139
- })]
140
- })]
141
- });
142
- }
143
- const styles = _reactNative.StyleSheet.create({
144
- // 32pt of Otto (16 grid × 2pt) reading as the header's status glyph.
145
- otto: {
146
- marginRight: 8,
147
- justifyContent: "center"
148
- },
149
- // Same plate as the Console header's action buttons.
150
- actionBtn: {
151
- width: 32,
152
- height: 32,
153
- borderRadius: 8,
154
- backgroundColor: _sharedUi.night.color.buttonSurface,
155
- borderWidth: 1,
156
- borderColor: _sharedUi.night.color.border,
157
- alignItems: "center",
158
- justifyContent: "center"
159
- },
160
- actionBtnDisabled: {
161
- opacity: 0.55
162
- }
163
- });
164
- //# sourceMappingURL=AskBuoyHeader.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AskBuoyHeader=AskBuoyHeader;var _react=require("react"),_reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_useCopyAction=require("./useCopyAction"),_activityGroups=require("../store/activityGroups"),_jsxRuntime=require("react/jsx-runtime");const HEADER_TICK_MS=200,NO_TRANSCRIPT=()=>"";function AskBuoyHeader({configured:e,busy:t,failed:i=!1,activeLabel:s,awaitingApproval:o=!1,startedAt:a=null,stopping:r=!1,readOnly:n=!1,toolCount:c,hasMessages:l,onBack:u,onReset:d,getTranscript:y,onOpenSettings:_,onTicket:h}){const{copied:b,copy:x}=(0,_useCopyAction.useCopyAction)(y??NO_TRANSCRIPT),[j,p]=(0,_react.useState)(!1);(0,_react.useEffect)(()=>{t?s&&p(!0):p(!1)},[t,s]);const R=t&&!o&&null!==a,[g,m]=(0,_react.useState)(()=>Date.now());(0,_react.useEffect)(()=>{if(!R)return;m(Date.now());const e=setInterval(()=>m(Date.now()),1e3);return()=>clearInterval(e)},[R]);const v=R&&null!==a?(0,_activityGroups.formatElapsed)(g-a):null,U=e?i?"error":t?s||j?"robot":"thinking":"idle":"confused",k=r?"Stopping":s??"Thinking",S=e?o?"Waiting for you":t?v?`${k} · ${v}`:`${k}…`:n?"Read only"+(c>0?` · ${c} tool${1===c?"":"s"}`:""):c>0?`Ready · ${c} tool${1===c?"":"s"} available`:"Ready":"Not set up in this app";return(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[u?(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation,{onBack:u}):null,(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.otto,testID:"buoy-ask-buoy-otto",children:(0,_jsxRuntime.jsx)(_sharedUi.Otto,{state:U,pixelSize:2,tickMs:HEADER_TICK_MS,water:!1})}),(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:"Ask Buoy",subtitle:S,testID:"buoy-ask-buoy-title"}),(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions,{children:[h?(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"buoy-ask-buoy-ticket",accessibilityRole:"button",accessibilityLabel:"Summarize for a ticket",disabled:!l||t,onPress:h,style:[styles.actionBtn,(!l||t)&&styles.actionBtnDisabled],children:(0,_jsxRuntime.jsx)(_sharedUi.FileText,{size:14,color:l&&!t?_sharedUi.night.color.textSecondary:_sharedUi.night.color.textTertiary})}):null,y?(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"buoy-ask-buoy-copy-chat",accessibilityRole:"button",accessibilityLabel:b?"Conversation copied":"Copy conversation",disabled:!l,onPress:x,style:[styles.actionBtn,!l&&styles.actionBtnDisabled],children:b?(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:14,color:_sharedUi.night.color.accent}):(0,_jsxRuntime.jsx)(_sharedUi.Copy,{size:14,color:l?_sharedUi.night.color.textSecondary:_sharedUi.night.color.textTertiary})}):null,_?(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"buoy-ask-buoy-settings",accessibilityRole:"button",accessibilityLabel:"Settings",onPress:_,style:styles.actionBtn,children:(0,_jsxRuntime.jsx)(_sharedUi.SettingsSolid,{size:14,color:_sharedUi.night.color.textSecondary})}):null,(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"buoy-ask-buoy-reset",accessibilityRole:"button",accessibilityLabel:"New conversation",disabled:!l,onPress:d,style:[styles.actionBtn,!l&&styles.actionBtnDisabled],children:(0,_jsxRuntime.jsx)(_sharedUi.Plus,{size:14,color:l?_sharedUi.night.color.textSecondary:_sharedUi.night.color.textTertiary})})]})]})}const styles=_reactNative.StyleSheet.create({otto:{marginRight:8,justifyContent:"center"},actionBtn:{width:32,height:32,borderRadius:8,backgroundColor:_sharedUi.night.color.buttonSurface,borderWidth:1,borderColor:_sharedUi.night.color.border,alignItems:"center",justifyContent:"center"},actionBtnDisabled:{opacity:.55}});
@@ -1,19 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "ASK_BUOY_ICON_COLOR", {
7
- enumerable: true,
8
- get: function () {
9
- return _floatingToolsCore.ASK_BUOY_ICON_COLOR;
10
- }
11
- });
12
- Object.defineProperty(exports, "AskBuoyIcon", {
13
- enumerable: true,
14
- get: function () {
15
- return _floatingToolsCore.AskBuoyIcon;
16
- }
17
- });
18
- var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
19
- //# sourceMappingURL=AskBuoyIcon.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ASK_BUOY_ICON_COLOR",{enumerable:!0,get:function(){return _floatingToolsCore.ASK_BUOY_ICON_COLOR}}),Object.defineProperty(exports,"AskBuoyIcon",{enumerable:!0,get:function(){return _floatingToolsCore.AskBuoyIcon}});var _floatingToolsCore=require("@buoy-gg/floating-tools-core");
@@ -1,353 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AskBuoyModal = AskBuoyModal;
7
- var _react = require("react");
8
- var _reactNative = require("react-native");
9
- var _agentCore = require("@buoy-gg/agent-core");
10
- var _sharedUi = require("@buoy-gg/shared-ui");
11
- var _blocks = require("../blocks");
12
- var _ApprovalCard = require("./ApprovalCard");
13
- var _ChangesBar = require("./ChangesBar");
14
- var _Composer = require("./Composer");
15
- var _AskBuoyHeader = require("./AskBuoyHeader");
16
- var _AskBuoySettings = require("./AskBuoySettings");
17
- var _EmptyState = require("./EmptyState");
18
- var _MessageList = require("./MessageList");
19
- var _askBuoyStore = require("../store/askBuoyStore");
20
- var _useAskBuoy = require("../store/useAskBuoy");
21
- var _useAskBuoySettings = require("../store/useAskBuoySettings");
22
- var _jsxRuntime = require("react/jsx-runtime");
23
- /**
24
- * Ask Buoy — the sheet.
25
- *
26
- * Manual JsModal chrome rather than the declarative `InstalledApp.modal` path,
27
- * because `ToolModalShell` forwards neither `footer`/`footerHeight` nor
28
- * `initialHeight`, and a conversation in a 400pt sheet with no sticky composer
29
- * is not usable.
30
- *
31
- * The layout rules here are all learned ones, each noted at its line: one
32
- * scroller owned by the message list, no animated background competing with
33
- * streaming text, transparent containers so the sheet's own chrome shows, and
34
- * an iOS-only keyboard offset.
35
- *
36
- * Top to bottom: header (title, live status, new-conversation) · changes bar
37
- * (only once something has been changed) · transcript · approval card (only
38
- * with `requireApproval`) · composer. Nothing else. The old "New conversation"
39
- * text link under the composer is gone — it is the header's + button now.
40
- */
41
-
42
- function AskBuoyModal({
43
- visible,
44
- onClose,
45
- onBack,
46
- onMinimize,
47
- persistenceKey,
48
- config
49
- }) {
50
- const {
51
- state,
52
- send,
53
- stop,
54
- reset,
55
- approve,
56
- retry,
57
- answer,
58
- runAction,
59
- configured,
60
- toolCount
61
- } = (0, _useAskBuoy.useAskBuoy)(config);
62
- const [changesOpen, setChangesOpen] = (0, _react.useState)(false);
63
- // A hardcoded device map, not the native library — an unmapped phone
64
- // silently returns bottom: 0, which is how footers ended up sitting on the
65
- // home indicator.
66
- const insets = (0, _sharedUi.useSafeAreaInsets)({
67
- minBottom: 16
68
- });
69
-
70
- /**
71
- * `dispatchToolAction` is imported STATICALLY at the top of this file, not
72
- * with `import()`. A dynamic import here resolves through Metro's
73
- * async-require path, which in a lazy dev bundle rejects with "Expected
74
- * HMRClient.setup() call at startup" — and because the promise was voided,
75
- * Undo did nothing at all while the bar went on claiming the changes were
76
- * undoable. shared-ui is already a static dependency of this component.
77
- *
78
- * A failed revert is SHOWN. `revertAll` reports what it could not put back,
79
- * and swallowing that is the same failure in a quieter form: the whole
80
- * reason mutations may auto-run is that undo is real.
81
- */
82
- const undoAll = (0, _react.useCallback)(() => {
83
- const ledger = _askBuoyStore.askBuoyStore.getLedger();
84
- if (!ledger) return;
85
- void (async () => {
86
- const outcome = await ledger.revertAll(_sharedUi.dispatchToolAction);
87
- if (outcome.failed.length === 0) {
88
- _askBuoyStore.askBuoyStore.setNotice(null);
89
- return;
90
- }
91
- const detail = outcome.failed.map(f => `${f.label} (${f.error})`).join("; ");
92
- _askBuoyStore.askBuoyStore.setNotice(`Couldn't undo ${outcome.failed.length} change${outcome.failed.length === 1 ? "" : "s"} — ${detail}`);
93
- })();
94
- }, []);
95
- const toggleChanges = (0, _react.useCallback)(() => setChangesOpen(v => !v), []);
96
-
97
- /**
98
- * PEEK. When the agent navigates or taps, the sheet drops to a 120pt strip
99
- * for ~2.5s so the user watches the app do it, then springs back to the
100
- * height it had (including a user's drag-resize — the value is read live,
101
- * never assumed). Rides JsModal's external `animatedHeight` seam, so the
102
- * modal's own drag-resize keeps working on the same value.
103
- */
104
- const sheetHeight = (0, _react.useRef)(new _reactNative.Animated.Value(560)).current;
105
- const peeking = (0, _react.useRef)(false);
106
- const runPeek = (0, _react.useCallback)(() => {
107
- if (peeking.current) return;
108
- peeking.current = true;
109
- sheetHeight.stopAnimation(from => {
110
- const restoreTo = typeof from === "number" && from > 200 ? from : 560;
111
- _reactNative.Animated.timing(sheetHeight, {
112
- toValue: 120,
113
- duration: 220,
114
- useNativeDriver: false
115
- }).start(() => {
116
- setTimeout(() => {
117
- _reactNative.Animated.spring(sheetHeight, {
118
- toValue: restoreTo,
119
- friction: 9,
120
- useNativeDriver: false
121
- }).start(() => {
122
- peeking.current = false;
123
- });
124
- }, 2500);
125
- });
126
- });
127
- }, [sheetHeight]);
128
-
129
- // A new `peek` receipt (navigate, tap) triggers the shrink. Keyed by
130
- // message id + count so a fresh assistant message restarts the count.
131
- const peekKey = (0, _react.useMemo)(() => {
132
- const last = state.messages[state.messages.length - 1];
133
- if (!last || last.role !== "assistant") return "";
134
- const peeks = last.blocks.filter(p => p.block.kind === "peek").length;
135
- return peeks > 0 ? `${last.id}:${peeks}` : "";
136
- }, [state.messages]);
137
- const prevPeekKey = (0, _react.useRef)("");
138
- (0, _react.useEffect)(() => {
139
- if (peekKey && peekKey !== prevPeekKey.current && config?.peek !== false) runPeek();
140
- prevPeekKey.current = peekKey;
141
- }, [peekKey, runPeek, config]);
142
-
143
- /**
144
- * New conversation, guarded. Clearing the session clears the ledger — the
145
- * ONLY undo surface — while the agent's changes stay live in the app, so
146
- * with reversible changes outstanding the user chooses their fate first.
147
- */
148
- const confirmReset = (0, _react.useCallback)(() => {
149
- const ledger = _askBuoyStore.askBuoyStore.getLedger();
150
- const reversible = ledger?.list().filter(e => !e.undoneAt && (0, _agentCore.isReversible)(e.effect)).length ?? 0;
151
- if (reversible === 0) {
152
- reset();
153
- return;
154
- }
155
- _reactNative.Alert.alert("Undo changes first?", `Ask Buoy made ${reversible} change${reversible === 1 ? "" : "s"} that can still be undone. Clearing the conversation loses the only automatic undo for ${reversible === 1 ? "it" : "them"}.`, [{
156
- text: "Undo, then clear",
157
- onPress: () => {
158
- void (async () => {
159
- const l = _askBuoyStore.askBuoyStore.getLedger();
160
- if (l) await l.revertAll(_sharedUi.dispatchToolAction);
161
- reset();
162
- })();
163
- }
164
- }, {
165
- text: "Clear anyway",
166
- style: "destructive",
167
- onPress: reset
168
- }, {
169
- text: "Cancel",
170
- style: "cancel"
171
- }]);
172
- }, [reset]);
173
-
174
- // The header's live status: the title of whichever tool call is in flight.
175
- const activeLabel = (0, _react.useMemo)(() => {
176
- const last = state.messages[state.messages.length - 1];
177
- if (!last || last.role !== "assistant" || !last.streaming) return null;
178
- return last.toolCalls.find(c => c.status === "running")?.label ?? null;
179
- }, [state.messages]);
180
-
181
- /**
182
- * What a block can do in THIS host. `minimize` collapses the sheet to the
183
- * rail so the user can look at the app (the peek chip). `openTool` has no
184
- * seam yet, so those buttons don't render here rather than render dead.
185
- */
186
- const blockHandlers = (0, _react.useMemo)(() => ({
187
- answer,
188
- runAction: (action, blockId) => {
189
- if (action.minimize) {
190
- onMinimize?.({
191
- mode: "bottomSheet"
192
- });
193
- return;
194
- }
195
- return runAction(action, blockId);
196
- },
197
- answered: state.answers,
198
- actionState: state.actionState,
199
- busy: state.busy,
200
- supports: {
201
- openTool: false,
202
- minimize: !!onMinimize,
203
- dispatch: true
204
- }
205
- }), [answer, runAction, onMinimize, state.answers, state.actionState, state.busy]);
206
-
207
- // The last assistant turn carrying an error is the only "it went wrong"
208
- // signal the header can read; it clears as soon as the next send starts.
209
- const lastMessage = state.messages[state.messages.length - 1];
210
- const failed = !state.busy && lastMessage?.role === "assistant" && !!lastMessage.error;
211
-
212
- // Built on press, not on render — a streaming answer would otherwise rebuild
213
- // the whole transcript on every frame for a button nobody tapped.
214
- const {
215
- showThinking
216
- } = (0, _useAskBuoySettings.useAskBuoySettings)();
217
- const getTranscript = (0, _react.useCallback)(() => (0, _MessageList.transcriptToText)(state.messages, showThinking), [state.messages, showThinking]);
218
-
219
- /**
220
- * Settings replaces the transcript in place rather than opening over it. The
221
- * sheet's own back arrow is the way out, and the conversation is untouched
222
- * underneath — a toggle you flip here should be visible the moment you go
223
- * back, not after dismissing something.
224
- */
225
- const [showSettings, setShowSettings] = (0, _react.useState)(false);
226
- const closeSettings = (0, _react.useCallback)(() => setShowSettings(false), []);
227
- const openSettings = (0, _react.useCallback)(() => setShowSettings(true), []);
228
- const header = showSettings ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
229
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
230
- onBack: closeSettings
231
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
232
- title: "Settings",
233
- subtitle: "Ask Buoy",
234
- testID: "buoy-ask-buoy-settings-title"
235
- })]
236
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_AskBuoyHeader.AskBuoyHeader, {
237
- configured: configured,
238
- busy: state.busy,
239
- failed: failed,
240
- activeLabel: activeLabel,
241
- toolCount: toolCount,
242
- hasMessages: state.messages.length > 0,
243
- onBack: onBack,
244
- onReset: confirmReset,
245
- getTranscript: getTranscript,
246
- onOpenSettings: openSettings
247
- });
248
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.JsModal, {
249
- visible: visible,
250
- onClose: onClose
251
- // The message list is the only scroller. JsModal's default wrapper is
252
- // flexGrow:1, which makes a nested flex:1 scroller resolve against the
253
- // content and never scroll at all.
254
- ,
255
- disableScrollWrapper: true
256
- // ToolBackground is an animated star field. A chat re-renders on every
257
- // streamed token; two continuous animations competing is a dropped
258
- // frame budget for no benefit.
259
- ,
260
- background: false,
261
- initialHeight: 560,
262
- animatedHeight: sheetHeight,
263
- header: {
264
- customContent: header,
265
- showToggleButton: false
266
- },
267
- onBack: onBack,
268
- onMinimize: onMinimize,
269
- persistenceKey: persistenceKey ?? "buoy-ask-buoy",
270
- enablePersistence: true,
271
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blocks.BlockHandlersProvider, {
272
- value: blockHandlers,
273
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
274
- style: [styles.root, {
275
- paddingBottom: insets.bottom
276
- }],
277
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_ChangesBar.ChangesBar, {
278
- ledger: _askBuoyStore.askBuoyStore.getLedger(),
279
- onUndoAll: undoAll,
280
- expanded: changesOpen,
281
- onToggle: toggleChanges
282
- }), state.notice && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
283
- style: styles.notice,
284
- testID: "buoy-ask-buoy-notice",
285
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Info, {
286
- size: 14,
287
- color: _sharedUi.night.color.info
288
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
289
- style: styles.noticeText,
290
- children: state.notice
291
- })]
292
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.KeyboardAvoidingView, {
293
- style: styles.flex
294
- // iOS only: Android's default softwareKeyboardLayoutMode is "resize",
295
- // so the window shrinks and a bottom-anchored view rides up already.
296
- // Padding on both would lift the composer twice.
297
- ,
298
- behavior: _reactNative.Platform.OS === "ios" ? "padding" : undefined,
299
- enabled: _reactNative.Platform.OS === "ios",
300
- keyboardVerticalOffset: insets.bottom,
301
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.FeatureGate, {
302
- featureName: "Ask Buoy",
303
- children: showSettings ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_AskBuoySettings.AskBuoySettings, {}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
304
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_MessageList.MessageList, {
305
- messages: state.messages,
306
- onRetry: retry,
307
- ListEmptyComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_EmptyState.EmptyState, {
308
- configured: configured,
309
- onPick: send
310
- })
311
- }), state.pending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ApprovalCard.ApprovalCard, {
312
- pending: state.pending,
313
- onAnswer: approve
314
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Composer.Composer, {
315
- onSend: send,
316
- onStop: stop,
317
- busy: state.busy,
318
- disabled: !configured,
319
- placeholder: state.queued ? "Queued — sends when this turn finishes" : state.awaitingBlockId ? "Pick an option above, or type…" : undefined
320
- })]
321
- })
322
- })
323
- })]
324
- })
325
- })
326
- });
327
- }
328
- const styles = _reactNative.StyleSheet.create({
329
- // Transparent or it paints over the sheet's own chrome — the convention is
330
- // repeated verbatim across every Buoy tool body.
331
- root: {
332
- flex: 1,
333
- backgroundColor: "transparent"
334
- },
335
- flex: {
336
- flex: 1
337
- },
338
- notice: {
339
- flexDirection: "row",
340
- alignItems: "flex-start",
341
- gap: 8,
342
- paddingHorizontal: _sharedUi.night.gutter,
343
- paddingVertical: 10,
344
- backgroundColor: _sharedUi.night.color.infoSoft
345
- },
346
- noticeText: {
347
- flex: 1,
348
- color: _sharedUi.night.color.text,
349
- fontSize: _sharedUi.night.font.caption,
350
- lineHeight: 18
351
- }
352
- });
353
- //# sourceMappingURL=AskBuoyModal.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AskBuoyModal=AskBuoyModal;var _react=require("react"),_reactNative=require("react-native"),_agentCore=require("@buoy-gg/agent-core"),_sharedUi=require("@buoy-gg/shared-ui"),_blocks=require("../blocks"),_ApprovalCard=require("./ApprovalCard"),_ChangesBar=require("./ChangesBar"),_Composer=require("./Composer"),_KeyboardPad=require("./KeyboardPad"),_AskBuoyHeader=require("./AskBuoyHeader"),_AskBuoySettings=require("./AskBuoySettings"),_EmptyState=require("./EmptyState"),_MessageList=require("./MessageList"),_QueuedMessages=require("./QueuedMessages"),_askBuoyStore=require("../store/askBuoyStore"),_ticketPrompt=require("../store/ticketPrompt"),_useAskBuoy=require("../store/useAskBuoy"),_useAskBuoySettings=require("../store/useAskBuoySettings"),_jsxRuntime=require("react/jsx-runtime");function AskBuoyModal({visible:e,onClose:t,onBack:s,onMinimize:a,persistenceKey:r,config:o}){const{state:n,send:i,stop:u,reset:l,undoThenReset:c,approve:d,retry:g,answer:_,runAction:y,editQueued:m,removeQueued:k,configured:p,toolCount:h,availableToolIds:b}=(0,_useAskBuoy.useAskBuoy)(o),[f,x]=(0,_react.useState)(!1),B=(0,_react.useCallback)(()=>{u(),t()},[u,t]),A=(0,_react.useCallback)(()=>_askBuoyStore.askBuoyStore.clearDraft(),[]),[j,S]=(0,_react.useState)(!1),v=(0,_react.useCallback)(()=>S(!1),[]),C=(0,_react.useCallback)(()=>S(!0),[]),R=!e,T=!!n.pending||!!n.awaitingBlockId,M=n.messages[n.messages.length-1],U=(0,_react.useRef)(!1),w=(0,_react.useRef)(n.busy);(0,_react.useEffect)(()=>{R&&w.current&&!n.busy&&(U.current=!0),R||(U.current=!1),w.current=n.busy},[R,n.busy]),(0,_react.useEffect)(()=>{R?T?(0,_sharedUi.setToolAttention)("ask-buoy",{kind:"needsInput",label:n.pending?"Needs your approval":"Has a question for you"}):U.current&&"assistant"===M?.role&&M.error?(0,_sharedUi.setToolAttention)("ask-buoy",{kind:"failed",label:"The last turn failed"}):U.current&&!n.busy?(0,_sharedUi.setToolAttention)("ask-buoy",{kind:"done",label:"Finished"}):(0,_sharedUi.setToolAttention)("ask-buoy",null):(0,_sharedUi.setToolAttention)("ask-buoy",null)},[R,T,n.busy,n.pending,M]),(0,_react.useEffect)(()=>()=>(0,_sharedUi.setToolAttention)("ask-buoy",null),[]),(0,_react.useEffect)(()=>{n.pending&&j&&S(!1)},[n.pending,j]);const q=(0,_sharedUi.useSafeAreaInsets)({minBottom:16}),[P,N]=(0,_react.useState)("bottomSheet"),$="floating"===P?0:q.bottom,H=(0,_react.useCallback)(()=>{const e=_askBuoyStore.askBuoyStore.getLedger();e&&(async()=>{const t=await e.revertAll(_sharedUi.dispatchToolAction);if(0===t.failed.length)return void _askBuoyStore.askBuoyStore.setNotice(null);const s=t.failed.map(e=>`${e.label} (${e.error})`).join("; ");_askBuoyStore.askBuoyStore.setNotice(`Couldn't undo ${t.failed.length} change${1===t.failed.length?"":"s"} — ${s}`)})()},[]),E=(0,_react.useCallback)(()=>x(e=>!e),[]),I=(0,_react.useRef)(new _reactNative.Animated.Value(560)).current,L=(0,_react.useRef)(!1),K=(0,_react.useCallback)(()=>{L.current||(L.current=!0,I.stopAnimation(e=>{const t="number"==typeof e&&e>200?e:560;_reactNative.Animated.timing(I,{toValue:120,duration:220,useNativeDriver:!1}).start(()=>{setTimeout(()=>{_reactNative.Animated.spring(I,{toValue:t,friction:9,useNativeDriver:!1}).start(()=>{L.current=!1})},2500)})}))},[I]),O=(0,_react.useMemo)(()=>{const e=n.messages[n.messages.length-1];if(!e||"assistant"!==e.role)return"";const t=e.blocks.filter(e=>"peek"===e.block.kind).length;return t>0?`${e.id}:${t}`:""},[n.messages]),z=(0,_react.useRef)("");(0,_react.useEffect)(()=>{O&&O!==z.current&&!1!==o?.peek&&K(),z.current=O},[O,K,o]);const D=(0,_react.useCallback)(()=>{const e=_askBuoyStore.askBuoyStore.getLedger(),t=e?.list().filter(e=>!e.undoneAt&&(0,_agentCore.isReversible)(e.effect)).length??0;0!==t?_reactNative.Alert.alert("Undo changes first?",`Ask Buoy made ${t} change${1===t?"":"s"} that can still be undone. Clearing the conversation loses the only automatic undo for ${1===t?"it":"them"}.`,[{text:"Undo, then clear",onPress:()=>{(async()=>{const e=await c();if(e.cleared)return;const t=e.reverted+e.failed.length,s=e.failed.map(e=>`${e.label} (${e.error})`).join("\n");_reactNative.Alert.alert(`Couldn't undo ${e.failed.length} of ${t} change${1===t?"":"s"}`,`${s}\n\nStill applied in the app. Clear the conversation anyway?`,[{text:"Keep conversation",style:"cancel"},{text:"Clear anyway",style:"destructive",onPress:l}])})()}},{text:"Clear anyway",style:"destructive",onPress:l},{text:"Cancel",style:"cancel"}]):l()},[l,c]),Q=(0,_react.useMemo)(()=>{const e=n.messages[n.messages.length-1];return e&&"assistant"===e.role&&e.streaming?e.toolCalls.find(e=>"running"===e.status)?.label??null:null},[n.messages]),V=(0,_react.useMemo)(()=>({answer:_,runAction:(e,t)=>{if(!e.minimize)return y(e,t);a?.({mode:"bottomSheet"})},answered:n.answers,actionState:n.actionState,busy:n.busy,supports:{openTool:!1,minimize:!!a,dispatch:!0}}),[_,y,a,n.answers,n.actionState,n.busy]),F=!n.busy&&"assistant"===M?.role&&!!M.error,G=n.busy||"assistant"!==M?.role||!M.stopped||M.error?null:M.id,J=(0,_askBuoyStore.queuePauseReason)(n),{showThinking:W,readOnly:X}=(0,_useAskBuoySettings.useAskBuoySettings)(),Y=(0,_react.useCallback)(()=>(0,_MessageList.transcriptToText)(n.messages,W),[n.messages,W]),Z=(0,_react.useCallback)(()=>i(_ticketPrompt.TICKET_PROMPT),[i]),ee=j?(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation,{onBack:v}),(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:"Settings",subtitle:"Ask Buoy",testID:"buoy-ask-buoy-settings-title"})]}):(0,_jsxRuntime.jsx)(_AskBuoyHeader.AskBuoyHeader,{configured:p,busy:n.busy,failed:F,activeLabel:Q,awaitingApproval:!!n.pending,startedAt:"assistant"===M?.role&&M.streaming?M.startedAt??null:null,stopping:n.stopping,readOnly:X,toolCount:h,hasMessages:n.messages.length>0,onBack:s,onReset:D,getTranscript:Y,onOpenSettings:C,onTicket:Z});return(0,_jsxRuntime.jsx)(_sharedUi.JsModal,{visible:e,onClose:B,disableScrollWrapper:!0,background:!1,initialHeight:560,animatedHeight:I,header:{customContent:ee,showToggleButton:!1},onBack:s,onMinimize:a,onModeChange:N,persistenceKey:r??"buoy-ask-buoy",enablePersistence:!0,children:(0,_jsxRuntime.jsx)(_blocks.BlockHandlersProvider,{value:V,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:[styles.root,{paddingBottom:$}],children:[(0,_jsxRuntime.jsx)(_ChangesBar.ChangesBar,{ledger:_askBuoyStore.askBuoyStore.getLedger(),onUndoAll:H,expanded:f,onToggle:E}),n.notice&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.notice,testID:"buoy-ask-buoy-notice",children:[(0,_jsxRuntime.jsx)(_sharedUi.Info,{size:14,color:_sharedUi.night.color.info}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.noticeText,children:n.notice})]}),(0,_jsxRuntime.jsx)(_KeyboardPad.KeyboardPad,{children:(0,_jsxRuntime.jsx)(_sharedUi.FeatureGate,{featureName:"Ask Buoy",children:j?(0,_jsxRuntime.jsx)(_AskBuoySettings.AskBuoySettings,{}):(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_MessageList.MessageList,{messages:n.messages,onRetry:g,waitingOnUser:!!n.pending||!!n.awaitingBlockId,ListEmptyComponent:(0,_jsxRuntime.jsx)(_EmptyState.EmptyState,{configured:p,onPick:i,availableToolIds:b,readOnly:X||!!o?.policy?.readOnly})}),(0,_jsxRuntime.jsx)(_QueuedMessages.QueuedMessages,{items:n.queued,paused:J,onEdit:m,onRemove:k}),n.pending&&(0,_jsxRuntime.jsx)(_ApprovalCard.ApprovalCard,{pending:n.pending,onAnswer:d}),(0,_jsxRuntime.jsx)(_Composer.Composer,{onSend:i,onStop:u,busy:n.busy,draft:n.draft,onDraftTaken:A,disabled:!p,focusKey:G,canFocus:e,placeholder:G?"Tell it what to do differently…":n.awaitingBlockId?"Pick an option above, or type…":void 0})]})})})]})})})}const styles=_reactNative.StyleSheet.create({root:{flex:1,backgroundColor:"transparent"},notice:{flexDirection:"row",alignItems:"flex-start",gap:8,paddingHorizontal:_sharedUi.night.gutter,paddingVertical:10,backgroundColor:_sharedUi.night.color.infoSoft},noticeText:{flex:1,color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.caption,lineHeight:18}});
@@ -1,69 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AskBuoySettings = AskBuoySettings;
7
- var _reactNative = require("react-native");
8
- var _sharedUi = require("@buoy-gg/shared-ui");
9
- var _useAskBuoySettings = require("../store/useAskBuoySettings");
10
- var _askBuoySettings = require("../store/askBuoySettings");
11
- var _jsxRuntime = require("react/jsx-runtime");
12
- /**
13
- * The sheet's settings, reached from the header.
14
- *
15
- * A view inside the sheet rather than a second modal: a settings panel that
16
- * covers the conversation you are configuring makes the effect of a toggle
17
- * invisible until you dismiss it. Back returns to the chat with the
18
- * transcript exactly where it was.
19
- *
20
- * Sections are by subject, not by implementation. "Chat" is what a tester
21
- * calls the thing they are looking at.
22
- */
23
-
24
- function AskBuoySettings() {
25
- const settings = (0, _useAskBuoySettings.useAskBuoySettings)();
26
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
27
- style: styles.scroll,
28
- contentContainerStyle: styles.content,
29
- testID: "buoy-ask-buoy-settings",
30
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
31
- style: styles.section,
32
- children: "CHAT"
33
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToggleRow, {
34
- testID: "buoy-ask-buoy-setting-thinking",
35
- label: "Show agent thinking",
36
- description: "Adds a collapsed strip under each answer: the model's reasoning, and every step it ran with its parameters, result, duration and token cost. Copy includes the steps and reasoning while this is on, so you can read the run outside the app.",
37
- value: settings.showThinking,
38
- onValueChange: next => _askBuoySettings.askBuoySettings.set("showThinking", next)
39
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
40
- style: styles.note,
41
- children: "Not every model reports reasoning. Claude thinks by default; most OpenAI models return none, and the strip then shows the steps alone."
42
- })]
43
- });
44
- }
45
- const styles = _reactNative.StyleSheet.create({
46
- scroll: {
47
- flex: 1
48
- },
49
- content: {
50
- padding: _sharedUi.night.gutter,
51
- gap: 10,
52
- paddingBottom: 32
53
- },
54
- section: {
55
- color: _sharedUi.night.color.textTertiary,
56
- fontSize: 10,
57
- fontWeight: "700",
58
- letterSpacing: 0.6,
59
- paddingHorizontal: 4,
60
- paddingTop: 4
61
- },
62
- note: {
63
- color: _sharedUi.night.color.textTertiary,
64
- fontSize: _sharedUi.night.font.micro,
65
- lineHeight: 16,
66
- paddingHorizontal: 4
67
- }
68
- });
69
- //# sourceMappingURL=AskBuoySettings.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AskBuoySettings=AskBuoySettings;var _reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_useAskBuoySettings=require("../store/useAskBuoySettings"),_askBuoySettings=require("../store/askBuoySettings"),_askBuoyStore=require("../store/askBuoyStore"),_useAskBuoy=require("../store/useAskBuoy"),_jsxRuntime=require("react/jsx-runtime");function AskBuoySettings(){const e=(0,_useAskBuoySettings.useAskBuoySettings)(),t=(0,_useAskBuoy.useAskBuoyState)().trusted;return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.scroll,contentContainerStyle:styles.content,testID:"buoy-ask-buoy-settings",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.section,children:"CHAT"}),(0,_jsxRuntime.jsx)(_sharedUi.ToggleRow,{testID:"buoy-ask-buoy-setting-thinking",label:"Show agent thinking",description:"Adds a collapsed strip under each answer: the model's reasoning, and every step it ran with its parameters, result, duration and token cost. Copy includes the steps and reasoning while this is on, so you can read the run outside the app.",value:e.showThinking,onValueChange:e=>_askBuoySettings.askBuoySettings.set("showThinking",e)}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.note,children:"Not every model reports reasoning. Claude thinks by default; most OpenAI models return none, and the strip then shows the steps alone."}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.section,children:"PERMISSIONS"}),(0,_jsxRuntime.jsx)(_sharedUi.ToggleRow,{testID:"buoy-ask-buoy-setting-readonly",label:"Read only",description:"Inspect the app, change nothing. Every write and simulation is refused until this is off. Undo still works — putting things back is the safe direction.",value:e.readOnly,onValueChange:e=>_askBuoySettings.askBuoySettings.set("readOnly",e)}),e.readOnly?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.note,testID:"buoy-ask-buoy-readonly-note",children:"On across reloads until you turn it off here. The header says “Read only” while it is on. It adds to whatever this app already restricts — it never loosens anything."}):null,(0,_jsxRuntime.jsx)(_sharedUi.ToggleRow,{testID:"buoy-ask-buoy-setting-bypass",tone:"warning",emphasizeLabel:e.bypassApprovals,disabled:e.readOnly,label:"Skip approval prompts",description:e.readOnly?"Unavailable while Read only is on — nothing can be approved.":"Runs every action the moment the agent calls it, with no Allow card — including the destructive ones that wipe or reset data.",value:e.bypassApprovals,onValueChange:e=>_askBuoySettings.askBuoySettings.set("bypassApprovals",e)}),e.bypassApprovals&&!e.readOnly?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.warning,testID:"buoy-ask-buoy-bypass-warning",children:[(0,_jsxRuntime.jsx)(_sharedUi.AlertTriangle,{size:14,color:_sharedUi.night.color.warning}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.warningText,children:"Nothing will ask before a change lands. A wipe or a reset runs on the model's word alone, and Undo only reverses the changes that can be reversed — the bar tells you which. This stays on across reloads and app restarts until you turn it off here, so leave it off on any device holding data you care about. It does not widen what the agent may reach: read-only mode, this app's deny list and the release-build refusals still apply."})]}):(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.note,children:"On by default for destructive actions only — reads and ordinary writes already run without asking, and the changes bar records them."}),t.length>0?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.trustedBox,testID:"buoy-ask-buoy-trusted",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.section,children:"ALLOWED WITHOUT ASKING — THIS CHAT"}),t.map(e=>(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.trustedRow,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.trustedLabel,numberOfLines:2,children:e.label}),(0,_jsxRuntime.jsx)(_reactNative.Pressable,{testID:`buoy-ask-buoy-untrust-${e.key}`,accessibilityRole:"button",onPress:()=>_askBuoyStore.askBuoyStore.untrust(e.key),style:({pressed:e})=>[styles.forget,e&&{opacity:.7}],hitSlop:6,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.forgetText,children:"Ask again"})})]},e.key))]}):null]})}const styles=_reactNative.StyleSheet.create({scroll:{flex:1},content:{padding:_sharedUi.night.gutter,gap:10,paddingBottom:32},section:{color:_sharedUi.night.color.textTertiary,fontSize:10,fontWeight:"700",letterSpacing:.6,paddingHorizontal:4,paddingTop:4},warning:{flexDirection:"row",gap:8,padding:_sharedUi.night.cardPad,borderRadius:_sharedUi.night.radius.card,borderWidth:_reactNative.StyleSheet.hairlineWidth,borderColor:_sharedUi.night.color.warning,backgroundColor:_sharedUi.night.color.surface},warningText:{flex:1,color:_sharedUi.night.color.warning,fontSize:_sharedUi.night.font.micro,lineHeight:16},trustedBox:{gap:6,paddingTop:6},trustedRow:{flexDirection:"row",alignItems:"center",gap:10,padding:_sharedUi.night.cardPad,borderRadius:_sharedUi.night.radius.card,borderWidth:_reactNative.StyleSheet.hairlineWidth,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.surface},trustedLabel:{flex:1,color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.caption,lineHeight:18},forget:{paddingHorizontal:10,paddingVertical:6,borderRadius:_sharedUi.night.radius.row,backgroundColor:_sharedUi.night.color.button},forgetText:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.micro,fontWeight:"600"},note:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.micro,lineHeight:16,paddingHorizontal:4}});