@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,400 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useAskBuoy = useAskBuoy;
7
- exports.useAskBuoyState = useAskBuoyState;
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 _askBuoyStore = require("./askBuoyStore");
13
- var _transcriptPersistence = require("./transcriptPersistence");
14
- /**
15
- * Wire the sheet to the agent.
16
- *
17
- * Two things here are load-bearing:
18
- *
19
- * 1. DISPATCH GOES THROUGH `dispatchToolAction`, the same on-device seam a
20
- * Scenario step and a desktop click use. No second adapter map, nothing
21
- * that can drift from what the broker sees.
22
- * 2. THE SESSION IS REBUILT WHEN THE TOOL LIST CHANGES. The adapter map is a
23
- * memo whose contents depend on which packages resolved and whether a
24
- * QueryClientProvider is above FloatingDevTools — it is per-app and per
25
- * render, never a constant. A session that cached the tool list at open
26
- * would offer the model tools that are no longer there.
27
- */
28
-
29
- const isRelease = typeof __DEV__ !== "undefined" && !__DEV__;
30
-
31
- /** Long enough to coalesce a streaming answer's deltas, short enough to beat a crash. */
32
- const SAVE_DEBOUNCE_MS = 600;
33
- function useAskBuoyState() {
34
- return (0, _react.useSyncExternalStore)(_askBuoyStore.askBuoyStore.subscribe, _askBuoyStore.askBuoyStore.getState, _askBuoyStore.askBuoyStore.getState);
35
- }
36
- function useAskBuoy(config) {
37
- const state = useAskBuoyState();
38
- const sessionRef = (0, _react.useRef)(null);
39
- /** One restore attempt per mount — see the note at the read. */
40
- const restoredRef = (0, _react.useRef)(false);
41
- const abortRef = (0, _react.useRef)(null);
42
- // Read through a ref where a stable callback needs the LATEST config (the
43
- // onEvent tap) without re-creating the callback per render.
44
- const configRef = (0, _react.useRef)(config);
45
- configRef.current = config;
46
- const configured = !!config?.endpoint && !!config?.model;
47
- /**
48
- * On by default. The conversation surviving a reload is what makes the tool
49
- * usable while iterating, and it is the only thing that survives a crash —
50
- * but it puts the chat on disk, so a host handling regulated data can say no.
51
- */
52
- const persist = config?.persistTranscript !== false;
53
-
54
- // Recomputed each render: the set of dispatchable tools is not a constant.
55
- //
56
- // `getSnapshot` is folded in here because half of Buoy's read surface is not
57
- // an action at all — console entries, network events, routes and env live
58
- // only in the adapter's snapshot. Without this the model is offered a
59
- // console tool whose sole action wipes the logs, and no way to read them.
60
- const availableActions = (0, _react.useMemo)(() => {
61
- try {
62
- const actions = (0, _sharedUi.listToolActions)();
63
- for (const toolId of (0, _sharedUi.listSnapshotToolIds)()) {
64
- if (!actions[toolId]) actions[toolId] = [];
65
- if (!actions[toolId].includes(_agentCore.SNAPSHOT_ACTION)) {
66
- actions[toolId] = [_agentCore.SNAPSHOT_ACTION, ...actions[toolId]];
67
- }
68
- }
69
- return actions;
70
- } catch {
71
- return {};
72
- }
73
- }, []);
74
- const toolKey = Object.keys(availableActions).sort().join(",");
75
- (0, _react.useEffect)(() => {
76
- _askBuoyStore.askBuoyStore.setConfigured(configured);
77
- // Stamped on the store so an exported run says what it ran against.
78
- _askBuoyStore.askBuoyStore.setMeta({
79
- model: config?.model,
80
- protocol: config?.protocol ?? (config ? "anthropic" : undefined),
81
- appName: config?.appName,
82
- platform: _reactNative.Platform.OS,
83
- build: isRelease ? "release" : "development"
84
- });
85
- if (!configured || !config) {
86
- sessionRef.current = null;
87
- _askBuoyStore.askBuoyStore.setNotice("Ask Buoy isn't set up in this app yet. A developer needs to point it at your team's AI endpoint.");
88
- return;
89
- }
90
- // The classic first-run mistake, caught statically: a provider's own URL
91
- // with the wrong protocol fails with a raw error that says nothing about
92
- // the one-line fix. ONLY the canonical provider hosts are checked — a
93
- // gateway may legitimately speak either protocol on any path (our own dev
94
- // gateway serves OpenAI framing on /v1/messages, and a path-based version
95
- // of this check flagged it on the first device run).
96
- const protocol = config.protocol ?? "anthropic";
97
- if (isRelease && config.apiKey) {
98
- _askBuoyStore.askBuoyStore.setNotice("This build carries a plaintext apiKey — that's dev-only and it ships to every install. Use the headers callback with your own gateway for distributed builds.");
99
- } else if (protocol === "anthropic" && /^https?:\/\/api\.openai\.com\//i.test(config.endpoint)) {
100
- _askBuoyStore.askBuoyStore.setNotice('This endpoint is api.openai.com but the protocol is "anthropic". Set protocol: "openai" in the askBuoy config.');
101
- } else if (protocol === "openai" && /^https?:\/\/api\.anthropic\.com\//i.test(config.endpoint)) {
102
- _askBuoyStore.askBuoyStore.setNotice('This endpoint is api.anthropic.com but the protocol is "openai". Remove protocol or set it to "anthropic".');
103
- } else {
104
- _askBuoyStore.askBuoyStore.setNotice(null);
105
- }
106
-
107
- // Reuse the held session while nothing material changed. The transcript
108
- // already survives close/reopen in the module store; without this the
109
- // session and ledger did not — reopening the sheet swapped in an empty
110
- // ledger (undo bar gone, agent changes still live in the app) and a blank
111
- // model memory behind a transcript that still showed the conversation.
112
- // The tool list is deliberately NOT part of this signature. Packages
113
- // register a frame or two apart, so `toolKey` legitimately changes right
114
- // after open — and keying on it silently rebuilt the session mid-chat,
115
- // throwing away the conversation, the model's memory and the undo ledger
116
- // while the transcript (a separate store) kept rendering as if nothing
117
- // happened. Verified on device: a destructive change went unrecorded
118
- // because it landed in a ledger that had just been replaced.
119
- const signature = [config.endpoint, config.protocol ?? "anthropic", config.model].join("|");
120
- const held = _askBuoyStore.askBuoyStore.getHeldSession();
121
- if (held && held.signature === signature) {
122
- sessionRef.current = held.session;
123
- held.session.setAvailableActions(availableActions);
124
- _askBuoyStore.askBuoyStore.setLedger(held.session.ledger);
125
- return;
126
- }
127
- const session = (0, _agentCore.createAskBuoySession)({
128
- endpoint: config.endpoint,
129
- protocol: config.protocol ?? "anthropic",
130
- model: config.model,
131
- headers: config.headers,
132
- apiKey: config.apiKey,
133
- maxTokens: config.maxTokens,
134
- anthropicVersion: config.anthropicVersion,
135
- requestOverrides: config.requestOverrides,
136
- // Host-declared custom tools join the built-in catalog. toProviderTools
137
- // still filters against the live registry, so a descriptor whose
138
- // `custom:<id>` adapter never registered is simply not offered.
139
- catalog: config.tools?.length ? [..._agentCore.CATALOG, ...config.tools] : undefined,
140
- dispatch: _sharedUi.dispatchToolAction,
141
- readSnapshot: _sharedUi.readToolSnapshot,
142
- availableActions,
143
- policy: config.policy,
144
- context: config.context,
145
- isRelease,
146
- appName: config.appName,
147
- platform: _reactNative.Platform.OS,
148
- requestApproval: input => _askBuoyStore.askBuoyStore.askApproval(input)
149
- });
150
- sessionRef.current = session;
151
- _askBuoyStore.askBuoyStore.holdSession(session, signature);
152
- _askBuoyStore.askBuoyStore.setLedger(session.ledger);
153
-
154
- /**
155
- * Bring the last conversation back — both halves of it.
156
- *
157
- * The transcript and the model's memory are separate things (the store and
158
- * the session), and restoring only the first is worse than restoring
159
- * neither: the user reads a conversation the agent has no recollection of,
160
- * and "undo that" or "now do the same for Pikachu" lands on an empty
161
- * history. So the session is restored in the same pass, and only into a
162
- * session this effect just built.
163
- */
164
- // The registry publishes on mount, a frame or two after first paint. Warm
165
- // the grounding once it is there so the first question does not pay for it.
166
- let cancelled = false;
167
- void (0, _sharedUi.waitForToolRegistry)().then(ready => {
168
- if (ready && !cancelled) void session.prime();
169
- });
170
-
171
- /**
172
- * NOT gated on `cancelled`, and once per mount.
173
- *
174
- * The disk read races the tool registry, and it was losing about half the
175
- * time. `availableActions` legitimately changes a frame or two after open
176
- * (see the note above) — that re-runs this effect, whose cleanup sets
177
- * `cancelled`, and the in-flight restore then threw its result away. The
178
- * second pass takes the held-session branch and returns early, so nothing
179
- * ever retried: the conversation was on disk, read correctly, and dropped
180
- * on the floor. Caught by the e2e, where one test restored and the next
181
- * did not, with no difference between them.
182
- *
183
- * Safe to leave running: `hydrate` refuses if anything has been said since,
184
- * and `restore` refuses a session that already has history. Resolved
185
- * against `sessionRef.current` rather than the captured `session` so a
186
- * genuine reconfiguration mid-read restores into the session in use.
187
- */
188
- if (persist && !restoredRef.current) {
189
- restoredRef.current = true;
190
- void (0, _transcriptPersistence.readTranscript)().then(saved => {
191
- if (!saved) return;
192
- const hydrated = _askBuoyStore.askBuoyStore.hydrate({
193
- messages: saved.messages,
194
- answers: saved.answers,
195
- usage: saved.usage
196
- });
197
- if (hydrated) sessionRef.current?.restore(saved.history);
198
- });
199
- }
200
- return () => {
201
- cancelled = true;
202
- };
203
- }, [configured, config, availableActions, toolKey, persist]);
204
-
205
- /**
206
- * Save on change: coalesced while a turn streams, immediate the moment it ends.
207
- *
208
- * The debounce exists because a streaming answer changes the store on every
209
- * delta, and writing a whole transcript per token would cost more than the
210
- * turn does. But applying it to the END of a turn as well left a window
211
- * where the finished answer was on screen and not yet on disk — a crash or a
212
- * fast reload inside it lost the whole turn, which is precisely the case
213
- * this feature exists for. An e2e that relaunched as soon as the answer
214
- * rendered lost it every time, and that is a real user doing a fast reload,
215
- * not a harness artefact.
216
- *
217
- * Saving still happens DURING a turn as well, which is what lets a bubble
218
- * the app died in come back marked interrupted rather than blank.
219
- */
220
- const messages = state.messages;
221
- const answers = state.answers;
222
- const usage = state.usage;
223
- const busy = state.busy;
224
- (0, _react.useEffect)(() => {
225
- if (!persist) return;
226
- if (messages.length === 0) return;
227
- const write = () => {
228
- void (0, _transcriptPersistence.writeTranscript)((0, _transcriptPersistence.buildPayload)({
229
- messages,
230
- history: sessionRef.current?.messages ?? [],
231
- answers,
232
- usage
233
- }));
234
- };
235
- if (!busy) {
236
- write();
237
- return;
238
- }
239
- const timer = setTimeout(write, SAVE_DEBOUNCE_MS);
240
- return () => clearTimeout(timer);
241
- }, [persist, busy, messages, answers, usage]);
242
-
243
- /** Stream one turn into a fresh assistant bubble. Callers set up the user side. */
244
- const runTurn = (0, _react.useCallback)(text => {
245
- const session = sessionRef.current;
246
- if (!session) return;
247
- _askBuoyStore.askBuoyStore.beginTurn();
248
- const messageId = _askBuoyStore.askBuoyStore.startAssistant();
249
- const controller = new AbortController();
250
- abortRef.current = controller;
251
- const onEvent = configRef.current?.onEvent;
252
- void (async () => {
253
- try {
254
- for await (const ev of session.send(text, controller.signal)) {
255
- _askBuoyStore.askBuoyStore.applyEvent(messageId, ev);
256
- if (onEvent) {
257
- try {
258
- onEvent(ev);
259
- } catch {
260
- // The audit tap must never take the chat down.
261
- }
262
- }
263
- }
264
- } catch (err) {
265
- _askBuoyStore.askBuoyStore.applyEvent(messageId, {
266
- type: "error",
267
- message: err instanceof Error ? err.message : "Something went wrong talking to your AI endpoint."
268
- });
269
- } finally {
270
- _askBuoyStore.askBuoyStore.finishAssistant(messageId);
271
- abortRef.current = null;
272
- }
273
- })();
274
- }, []);
275
- const send = (0, _react.useCallback)(text => {
276
- const trimmed = text.trim();
277
- if (!sessionRef.current || !trimmed) return;
278
-
279
- // Typed mid-turn: park it. The composer already cleared the field, and
280
- // silently dropping the words was the worst of all outcomes.
281
- if (_askBuoyStore.askBuoyStore.getState().busy) {
282
- _askBuoyStore.askBuoyStore.setQueued(trimmed);
283
- return;
284
- }
285
-
286
- // Typing past an Ask block IS an answer: the block is skipped and locks.
287
- // Without this the composer stayed on "Pick an option above…" forever and
288
- // a stale choice sat tappable in the history.
289
- const awaiting = _askBuoyStore.askBuoyStore.getState().awaitingBlockId;
290
- if (awaiting) _askBuoyStore.askBuoyStore.recordAnswer({
291
- blockId: awaiting,
292
- kind: "skipped"
293
- });
294
- _askBuoyStore.askBuoyStore.addUser(trimmed);
295
- runTurn(trimmed);
296
- }, [runTurn]);
297
- const retry = (0, _react.useCallback)(() => {
298
- const {
299
- messages,
300
- busy
301
- } = _askBuoyStore.askBuoyStore.getState();
302
- if (busy || !sessionRef.current) return;
303
- const lastUser = [...messages].reverse().find(m => m.role === "user");
304
- if (!lastUser) return;
305
- // Replace the failed bubble rather than stacking a second one under it.
306
- const last = messages[messages.length - 1];
307
- if (last && last.role === "assistant" && last.error) _askBuoyStore.askBuoyStore.removeMessage(last.id);
308
- runTurn(lastUser.text);
309
- }, [runTurn]);
310
- const stop = (0, _react.useCallback)(() => {
311
- // A pending approval parks an unresolved promise inside the engine; the
312
- // abort signal is only read between steps, so Stop must also answer the
313
- // approval (as declined) or the generator hangs forever.
314
- if (_askBuoyStore.askBuoyStore.getState().pending) _askBuoyStore.askBuoyStore.answerApproval(false);
315
- abortRef.current?.abort();
316
- abortRef.current = null;
317
- }, []);
318
-
319
- // Flush the parked message the moment the turn ends.
320
- const queued = state.queued;
321
- (0, _react.useEffect)(() => {
322
- if (!state.busy && queued) {
323
- _askBuoyStore.askBuoyStore.setQueued(null);
324
- send(queued);
325
- }
326
- }, [state.busy, queued, send]);
327
- const reset = (0, _react.useCallback)(() => {
328
- abortRef.current?.abort();
329
- sessionRef.current?.reset();
330
- _askBuoyStore.askBuoyStore.reset();
331
- // "New conversation" means gone, not hidden. Leaving the last chat on disk
332
- // after the user asked for a clean one is the opposite of what they said.
333
- void (0, _transcriptPersistence.clearTranscript)();
334
- }, []);
335
- const approve = (0, _react.useCallback)(approved => {
336
- _askBuoyStore.askBuoyStore.answerApproval(approved);
337
- }, []);
338
- const answer = (0, _react.useCallback)(a => {
339
- _askBuoyStore.askBuoyStore.recordAnswer(a);
340
- // Plain words to the model, never JSON: "Business checkout", "Yes, go ahead."
341
- send((0, _agentCore.answerToText)(a));
342
- }, [send]);
343
-
344
- /**
345
- * Block buttons. `send` is a chat reply; `dispatch` runs the action through
346
- * `runGatedAction` — the SAME validation, policy and ledger path a model
347
- * call takes, minus the model. The first version called `dispatchToolAction`
348
- * raw, which made a model-authored button an invisible, ungoverned,
349
- * unundoable mutation while the `buoy_ui` schema promised the opposite.
350
- * The human's tap satisfies `requireApproval`; deny lists, read-only mode
351
- * and release refusals still stand. Button state is tracked so a tap shows
352
- * running → done and can't double-fire.
353
- * (`minimize` / `openTool` are the sheet's to handle; see AskBuoyModal.)
354
- */
355
- const runAction = (0, _react.useCallback)(async (action, blockId) => {
356
- if (action.send) {
357
- send(action.send);
358
- return;
359
- }
360
- if (!action.dispatch) return;
361
- const key = `${blockId}:${action.label}`;
362
- const ledger = _askBuoyStore.askBuoyStore.getLedger();
363
- if (!ledger) {
364
- _askBuoyStore.askBuoyStore.setNotice(`${action.label} failed — no active Ask Buoy session.`);
365
- return;
366
- }
367
- _askBuoyStore.askBuoyStore.setActionState(key, "running");
368
- const outcome = await (0, _agentCore.runGatedAction)({
369
- toolId: action.dispatch.toolId,
370
- action: action.dispatch.action,
371
- params: action.dispatch.params ?? {},
372
- dispatch: _sharedUi.dispatchToolAction,
373
- ledger,
374
- policy: config?.policy ?? {},
375
- isRelease,
376
- // Same merged catalog the session offers, so a button on a custom
377
- // tool's block is not refused as unknown.
378
- catalog: config?.tools?.length ? [..._agentCore.CATALOG, ...config.tools] : undefined
379
- });
380
- if (outcome.ok) {
381
- _askBuoyStore.askBuoyStore.setActionState(key, "done");
382
- } else {
383
- _askBuoyStore.askBuoyStore.setActionState(key, "failed");
384
- _askBuoyStore.askBuoyStore.setNotice(`${action.label} failed — ${outcome.error}`);
385
- }
386
- }, [send, config]);
387
- return {
388
- state,
389
- send,
390
- stop,
391
- reset,
392
- approve,
393
- retry,
394
- answer,
395
- runAction,
396
- configured,
397
- toolCount: Object.keys(availableActions).length
398
- };
399
- }
400
- //# sourceMappingURL=useAskBuoy.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useAskBuoy=useAskBuoy,exports.useAskBuoyState=useAskBuoyState;var _sharedUi=require("@buoy-gg/shared-ui"),_react=require("react"),_reactNative=require("react-native"),_agentCore=require("@buoy-gg/agent-core"),_askBuoyStore=require("./askBuoyStore"),_resetConversation=require("./resetConversation"),_transcriptPersistence=require("./transcriptPersistence"),_useAskBuoySettings=require("./useAskBuoySettings");const isRelease="undefined"!=typeof __DEV__&&!__DEV__;function questionBehind(e){for(const t of _askBuoyStore.askBuoyStore.getState().messages)if(t.restored)for(const o of t.blocks){const t=o.block;if(t?.id!==e)continue;const s=t.question??t.label??t.title;return"string"==typeof s&&s.trim()?s.trim():void 0}}function readAvailableActions(){try{const e=(0,_sharedUi.listToolActions)();for(const t of(0,_sharedUi.listSnapshotToolIds)())e[t]||(e[t]=[]),e[t].includes(_agentCore.SNAPSHOT_ACTION)||(e[t]=[_agentCore.SNAPSHOT_ACTION,...e[t]]);return e}catch{return{}}}const SAVE_DEBOUNCE_MS=600;function useAskBuoyState(){return(0,_react.useSyncExternalStore)(_askBuoyStore.askBuoyStore.subscribe,_askBuoyStore.askBuoyStore.getState,_askBuoyStore.askBuoyStore.getState)}function useAskBuoy(e){const t=useAskBuoyState(),o=(0,_sharedUi.getUseIsPro)()(),s=(0,_react.useRef)(o);s.current=o;const r=(0,_react.useCallback)((...e)=>(0,_sharedUi.hasAccountAccess)()&&s.current?(0,_sharedUi.dispatchToolAction)(...e):Promise.reject(new Error("Ask Buoy requires Pro access.")),[]),a=(0,_react.useRef)(null),n=(0,_react.useRef)(!1),u=(0,_react.useRef)(null),i=(0,_react.useRef)(e);i.current=e;const c=!!e?.endpoint&&!!e?.model,l=!1!==e?.persistTranscript,{bypassApprovals:d,readOnly:y}=(0,_useAskBuoySettings.useAskBuoySettings)(),k=(0,_react.useRef)(d);k.current=d;const p=(0,_react.useRef)(y);p.current=y;const S=(0,_react.useCallback)(()=>p.current?{...e?.policy??{},readOnly:!0}:e?.policy??{},[e]),[_,B]=(0,_react.useState)(0);(0,_react.useEffect)(()=>{let e=!1;return(0,_sharedUi.waitForToolRegistry)().then(()=>{e||B(e=>e+1)}),()=>{e=!0}},[]);const g=(0,_react.useMemo)(()=>readAvailableActions(),[_]),h=Object.keys(g).sort().join(",");(0,_react.useEffect)(()=>{if(_askBuoyStore.askBuoyStore.setConfigured(c),_askBuoyStore.askBuoyStore.setMeta({model:e?.model,protocol:e?.protocol??(e?"anthropic":void 0),appName:e?.appName,platform:_reactNative.Platform.OS,build:isRelease?"release":"development"}),!c||!e)return a.current=null,void _askBuoyStore.askBuoyStore.setNotice("Ask Buoy isn't set up in this app yet. A developer needs to point it at your team's AI endpoint.");const t=e.protocol??"anthropic";isRelease&&e.apiKey?_askBuoyStore.askBuoyStore.setNotice("This build carries a plaintext apiKey — that's dev-only and it ships to every install. Use the headers callback with your own gateway for distributed builds."):"anthropic"===t&&/^https?:\/\/api\.openai\.com\//i.test(e.endpoint)?_askBuoyStore.askBuoyStore.setNotice('This endpoint is api.openai.com but the protocol is "anthropic". Set protocol: "openai" in the askBuoy config.'):"openai"===t&&/^https?:\/\/api\.anthropic\.com\//i.test(e.endpoint)?_askBuoyStore.askBuoyStore.setNotice('This endpoint is api.anthropic.com but the protocol is "openai". Remove protocol or set it to "anthropic".'):_askBuoyStore.askBuoyStore.setNotice(null);const o=[e.endpoint,e.protocol??"anthropic",e.model].join("|"),s=_askBuoyStore.askBuoyStore.getHeldSession();if(s&&s.signature===o)return a.current=s.session,s.session.setAvailableActions(g),s.session.setApprovalBypass(k.current),s.session.setReadOnly(p.current),void _askBuoyStore.askBuoyStore.setLedger(s.session.ledger);const u=(0,_agentCore.createAskBuoySession)({endpoint:e.endpoint,protocol:e.protocol??"anthropic",model:e.model,headers:e.headers,apiKey:e.apiKey,maxTokens:e.maxTokens,anthropicVersion:e.anthropicVersion,requestOverrides:e.requestOverrides,catalog:e.tools?.length?[..._agentCore.CATALOG,...e.tools]:void 0,dispatch:r,readSnapshot:_sharedUi.readToolSnapshot,availableActions:g,policy:e.policy,context:e.context,isRelease:isRelease,appName:e.appName,platform:_reactNative.Platform.OS,requestApproval:e=>_askBuoyStore.askBuoyStore.askApproval(e)});a.current=u,u.setApprovalBypass(k.current),u.setReadOnly(p.current),_askBuoyStore.askBuoyStore.holdSession(u,o),_askBuoyStore.askBuoyStore.setLedger(u.ledger);let i=!1;return(0,_sharedUi.waitForToolRegistry)().then(e=>{e&&!i&&u.prime()}),l&&!n.current&&(n.current=!0,(0,_transcriptPersistence.readTranscript)().then(e=>{e&&_askBuoyStore.askBuoyStore.hydrate({messages:e.messages,answers:e.answers,usage:e.usage,queued:e.queued})&&(a.current?.restore(e.history),e.ledger?.length&&a.current?.ledger.restore(e.ledger),e.pending&&_askBuoyStore.askBuoyStore.restorePending(e.pending))})),()=>{i=!0}},[c,e,g,h,l]),(0,_react.useEffect)(()=>{a.current?.setApprovalBypass(d)},[d]),(0,_react.useEffect)(()=>{a.current?.setReadOnly(y)},[y]);const f=t.messages,A=t.answers,b=t.usage,v=t.busy,m=t.pending,C=t.queued;(0,_react.useEffect)(()=>{if(!l)return;if(0===f.length)return;const e=()=>{(0,_transcriptPersistence.writeTranscript)((0,_transcriptPersistence.buildPayload)({messages:f,history:a.current?.messages??[],answers:A,usage:b,pending:m,ledger:_askBuoyStore.askBuoyStore.getLedger()?.list(),queued:C}))};if(!v)return void e();const t=setTimeout(e,SAVE_DEBOUNCE_MS);return()=>clearTimeout(t)},[l,v,f,A,b,m,C]);const w=(0,_react.useCallback)(e=>{if(!(0,_sharedUi.hasAccountAccess)()||!s.current)return;const t=a.current;if(!t)return;_askBuoyStore.askBuoyStore.beginTurn();const o=_askBuoyStore.askBuoyStore.startAssistant(),r=new AbortController;u.current=r,t.setAvailableActions(readAvailableActions());const n=i.current?.onEvent;(async()=>{try{for await(const s of t.send(e,r.signal))if(_askBuoyStore.askBuoyStore.applyEvent(o,s),n)try{n(s)}catch{}}catch(e){r.signal.aborted||_askBuoyStore.askBuoyStore.applyEvent(o,{type:"error",message:e instanceof Error?e.message:"Something went wrong talking to your AI endpoint."})}finally{r.signal.aborted&&_askBuoyStore.askBuoyStore.markStopped(o),_askBuoyStore.askBuoyStore.finishAssistant(o),u.current=null}})()},[]),T=(0,_react.useCallback)(e=>{if(!(0,_sharedUi.hasAccountAccess)()||!s.current)return;const t=e.trim();if(!a.current||!t)return;if(_askBuoyStore.askBuoyStore.getState().busy)return void _askBuoyStore.askBuoyStore.enqueue(t);const o=_askBuoyStore.askBuoyStore.getState().awaitingBlockId;o&&_askBuoyStore.askBuoyStore.recordAnswer({blockId:o,kind:"skipped"}),_askBuoyStore.askBuoyStore.addUser(t),w(t)},[w]),N=(0,_react.useCallback)(()=>{const{messages:e,busy:t}=_askBuoyStore.askBuoyStore.getState();if(t||!a.current)return;const o=[...e].reverse().find(e=>"user"===e.role);o&&w(o.text)},[w]),q=(0,_react.useCallback)(()=>{_askBuoyStore.askBuoyStore.requestStop(),_askBuoyStore.askBuoyStore.getState().pending&&_askBuoyStore.askBuoyStore.answerApproval(!1),u.current?.abort(),u.current=null},[]);(0,_react.useEffect)(()=>{const e=(0,_sharedUi.subscribeAccountAccess)(()=>{(0,_sharedUi.hasAccountAccess)()||q()});return()=>{e(),q()}},[q]),(0,_react.useEffect)(()=>{o||q()},[o,q]),(0,_react.useEffect)(()=>{if(0===t.queued.length)return;if("idle"!==(0,_askBuoyStore.turnPhaseOf)(t))return;if(null!==(0,_askBuoyStore.queuePauseReason)(t))return;const e=_askBuoyStore.askBuoyStore.shiftQueued();e&&T(e.text)},[t,T]);const R=(0,_react.useCallback)(e=>_askBuoyStore.askBuoyStore.takeQueuedToDraft(e),[]),O=(0,_react.useCallback)(e=>_askBuoyStore.askBuoyStore.removeQueued(e),[]),E=(0,_react.useCallback)(()=>{u.current?.abort(),u.current=null,(0,_resetConversation.clearConversation)()},[]),U=(0,_react.useCallback)(()=>(0,_resetConversation.resetConversation)({dispatch:_sharedUi.dispatchToolAction,undoFirst:!0}),[]),P=(0,_react.useCallback)(async t=>{const o=_askBuoyStore.askBuoyStore.getLedger();if(!o)return void _askBuoyStore.askBuoyStore.setNotice(`${t.label} couldn't run — no active Ask Buoy session.`);const s=e?.tools?.length?[..._agentCore.CATALOG,...e.tools]:void 0;if(t.targetDigest){const e=await(0,_agentCore.readTargetDigest)({toolId:t.toolId,action:t.action,params:t.params??{},dispatch:r,catalog:s});if(void 0!==e&&e!==t.targetDigest)return void _askBuoyStore.askBuoyStore.addNote(`“${t.label}” wasn't applied — what it would change has moved on since the app restarted. Nothing was written. Ask again if you still want it.`)}const a=await(0,_agentCore.runGatedAction)({toolId:t.toolId,action:t.action,params:t.params??{},dispatch:r,ledger:o,policy:S(),isRelease:isRelease,catalog:s});a.ok?_askBuoyStore.askBuoyStore.addNote(`Applied “${t.label}”, which was still waiting when the app restarted. Whatever else that answer was going to do is gone — ask again if there was more to it.`):_askBuoyStore.askBuoyStore.setNotice(`${t.label} failed — ${a.error}`)},[e,S]),I=(0,_react.useCallback)(e=>{const t=_askBuoyStore.askBuoyStore.getState().pending,o="boolean"==typeof e?e:e.approved;_askBuoyStore.askBuoyStore.answerApproval(e),t?.restored&&(o?P(t):_askBuoyStore.askBuoyStore.addNote(`Skipped “${t.label}”. Nothing was changed.`))},[P]),x=(0,_react.useCallback)(e=>{_askBuoyStore.askBuoyStore.recordAnswer(e);const t=questionBehind(e.blockId);T(t?`${t} — ${(0,_agentCore.answerToText)(e)}`:(0,_agentCore.answerToText)(e))},[T]),$=(0,_react.useCallback)(async(t,o)=>{if(!(0,_sharedUi.hasAccountAccess)()||!s.current)return void _askBuoyStore.askBuoyStore.setNotice("Ask Buoy requires Pro access.");if(t.send)return void T(t.send);if(!t.dispatch)return;const a=`${o}:${t.label}`,n=_askBuoyStore.askBuoyStore.getLedger();if(!n)return void _askBuoyStore.askBuoyStore.setNotice(`${t.label} failed — no active Ask Buoy session.`);_askBuoyStore.askBuoyStore.setActionState(a,"running");const u=await(0,_agentCore.runGatedAction)({toolId:t.dispatch.toolId,action:t.dispatch.action,params:t.dispatch.params??{},dispatch:r,ledger:n,policy:S(),isRelease:isRelease,catalog:e?.tools?.length?[..._agentCore.CATALOG,...e.tools]:void 0});u.ok?_askBuoyStore.askBuoyStore.setActionState(a,"done"):(_askBuoyStore.askBuoyStore.setActionState(a,"failed"),_askBuoyStore.askBuoyStore.setNotice(`${t.label} failed — ${u.error}`))},[T,e,S]);return{state:t,send:T,stop:q,reset:E,undoThenReset:U,approve:I,retry:N,answer:x,runAction:$,editQueued:R,removeQueued:O,configured:c,toolCount:Object.keys(g).length,availableToolIds:Object.keys(g)}}
@@ -1,14 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useAskBuoySettings = useAskBuoySettings;
7
- var _react = require("react");
8
- var _askBuoySettings = require("./askBuoySettings");
9
- /** Subscribe the sheet to Ask Buoy's own preferences. */
10
-
11
- function useAskBuoySettings() {
12
- return (0, _react.useSyncExternalStore)(_askBuoySettings.askBuoySettings.subscribe, _askBuoySettings.askBuoySettings.get, _askBuoySettings.askBuoySettings.get);
13
- }
14
- //# sourceMappingURL=useAskBuoySettings.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useAskBuoySettings=useAskBuoySettings;var _react=require("react"),_askBuoySettings=require("./askBuoySettings");function useAskBuoySettings(){return(0,_react.useSyncExternalStore)(_askBuoySettings.askBuoySettings.subscribe,_askBuoySettings.askBuoySettings.get,_askBuoySettings.askBuoySettings.get)}
@@ -1,119 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.askBuoySyncAdapter = exports.ASK_BUOY_ADAPTER_VERSION = void 0;
7
- var _wire = require("./wire");
8
- var _agentCore = require("@buoy-gg/agent-core");
9
- var _askBuoyStore = require("../store/askBuoyStore");
10
- /**
11
- * The sync adapter, so Buoy Desktop and MCP can see what Ask Buoy is doing.
12
- *
13
- * Read-heavy on purpose. There is no `send` action: letting a remote client
14
- * put words in the agent's mouth would mean anyone who can reach the broker —
15
- * which has no authentication at all, binds 0.0.0.0, and accepts any client
16
- * calling itself "Dashboard" — could drive a mutating agent on a tester's
17
- * device. The chat is initiated on-device, by a person, full stop.
18
- *
19
- * `undoAll` IS exposed, because the asymmetry is deliberate: putting things
20
- * back is the safe direction, and a dev watching from the desktop should be
21
- * able to clean up a device without walking over to it.
22
- *
23
- * The transcript is redacted before it crosses the wire. Action results the
24
- * agent read can contain storage values and response bodies, and this socket
25
- * broadcasts to every connected dashboard — it already leaks license keys the
26
- * same way.
27
- */
28
-
29
- const ASK_BUOY_ADAPTER_VERSION = exports.ASK_BUOY_ADAPTER_VERSION = 1;
30
- const askBuoySyncAdapter = exports.askBuoySyncAdapter = {
31
- version: ASK_BUOY_ADAPTER_VERSION,
32
- getSnapshot() {
33
- const state = _askBuoyStore.askBuoyStore.getState();
34
- const ledger = _askBuoyStore.askBuoyStore.getLedger();
35
- const entries = ledger?.list() ?? [];
36
- const outstanding = entries.filter(e => !e.undoneAt);
37
- return {
38
- version: ASK_BUOY_ADAPTER_VERSION,
39
- busy: state.busy,
40
- configured: state.configured,
41
- notice: state.notice,
42
- messageCount: state.messages.length,
43
- // Only the shape of the conversation, never tool payloads.
44
- messages: state.messages.map(m => ({
45
- id: m.id,
46
- role: m.role,
47
- text: (0, _wire.redactForWire)(m.text),
48
- streaming: !!m.streaming,
49
- toolCalls: m.toolCalls.map(c => ({
50
- toolId: c.toolId,
51
- action: c.action,
52
- status: c.status
53
- }))
54
- })),
55
- // Session token totals, so a desktop/MCP observer can meter cost.
56
- usage: state.usage,
57
- pendingApproval: state.pending ? {
58
- toolId: state.pending.toolId,
59
- action: state.pending.action,
60
- label: state.pending.label
61
- } : null,
62
- changes: {
63
- // Transients (navigation, taps) are one-shot actions, not changes —
64
- // same rule as the on-device bar, so desktop and device tell one story.
65
- reversible: outstanding.filter(e => (0, _agentCore.isReversible)(e.effect)).length,
66
- permanent: outstanding.filter(e => e.effect.kind !== "transient" && !(0, _agentCore.isReversible)(e.effect)).length,
67
- transients: outstanding.filter(e => e.effect.kind === "transient").length,
68
- items: outstanding.map(e => ({
69
- kind: e.effect.kind,
70
- label: e.effect.label
71
- }))
72
- }
73
- };
74
- },
75
- subscribe(onChange) {
76
- const offStore = _askBuoyStore.askBuoyStore.subscribe(onChange);
77
- const offLedger = _askBuoyStore.askBuoyStore.getLedger()?.subscribe(onChange);
78
- return () => {
79
- offStore();
80
- offLedger?.();
81
- };
82
- },
83
- actions: {
84
- /** What the agent changed, and whether it can be put back. */
85
- listChanges: () => {
86
- const entries = _askBuoyStore.askBuoyStore.getLedger()?.list() ?? [];
87
- return entries.filter(e => !e.undoneAt).map(e => ({
88
- id: e.id,
89
- at: e.at,
90
- toolId: e.toolId,
91
- action: e.action,
92
- kind: e.effect.kind,
93
- label: e.effect.label,
94
- reversible: (0, _agentCore.isReversible)(e.effect)
95
- }));
96
- },
97
- /** Put back everything that can be put back. Safe direction only. */
98
- undoAll: async () => {
99
- const ledger = _askBuoyStore.askBuoyStore.getLedger();
100
- if (!ledger) return {
101
- ok: false,
102
- error: "No Ask Buoy session on this device."
103
- };
104
- const outcome = await ledger.revertAll(_wire.dispatchToolAction);
105
- return {
106
- ok: true,
107
- ...outcome
108
- };
109
- },
110
- /** Clear the transcript and the ledger. Does not undo anything. */
111
- reset: () => {
112
- _askBuoyStore.askBuoyStore.reset();
113
- return {
114
- ok: true
115
- };
116
- }
117
- }
118
- };
119
- //# sourceMappingURL=askBuoySyncAdapter.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.askBuoySyncAdapter=exports.ASK_BUOY_ADAPTER_VERSION=void 0;var _resetConversation=require("../store/resetConversation"),_wire=require("./wire"),_agentCore=require("@buoy-gg/agent-core"),_askBuoyStore=require("../store/askBuoyStore");const ASK_BUOY_ADAPTER_VERSION=exports.ASK_BUOY_ADAPTER_VERSION=1,askBuoySyncAdapter=exports.askBuoySyncAdapter={version:ASK_BUOY_ADAPTER_VERSION,async dispose(e){const t=_askBuoyStore.askBuoyStore.getLedger();for(const o of t?.list()??[])o.undoneAt||"network-override"===o.effect.kind&&await e("network","deleteOverrideRule",{id:o.effect.ruleId})},getSnapshot(){const e=_askBuoyStore.askBuoyStore.getState(),t=_askBuoyStore.askBuoyStore.getLedger(),o=(t?.list()??[]).filter(e=>!e.undoneAt);return{version:ASK_BUOY_ADAPTER_VERSION,busy:e.busy,configured:e.configured,notice:e.notice,messageCount:e.messages.length,messages:e.messages.map(e=>({id:e.id,role:e.role,text:(0,_wire.redactForWire)(e.text),streaming:!!e.streaming,toolCalls:e.toolCalls.map(e=>({toolId:e.toolId,action:e.action,status:e.status}))})),usage:e.usage,pendingApproval:e.pending?{toolId:e.pending.toolId,action:e.pending.action,label:e.pending.label}:null,changes:{reversible:o.filter(e=>(0,_agentCore.isReversible)(e.effect)).length,permanent:o.filter(e=>"transient"!==e.effect.kind&&!(0,_agentCore.isReversible)(e.effect)).length,transients:o.filter(e=>"transient"===e.effect.kind).length,items:o.map(e=>({kind:e.effect.kind,label:e.effect.label}))}}},subscribe(e){const t=_askBuoyStore.askBuoyStore.subscribe(e),o=_askBuoyStore.askBuoyStore.getLedger()?.subscribe(e);return()=>{t(),o?.()}},actions:{listChanges:()=>(_askBuoyStore.askBuoyStore.getLedger()?.list()??[]).filter(e=>!e.undoneAt).map(e=>({id:e.id,at:e.at,toolId:e.toolId,action:e.action,kind:e.effect.kind,label:e.effect.label,reversible:(0,_agentCore.isReversible)(e.effect)})),undoAll:async()=>{const e=_askBuoyStore.askBuoyStore.getLedger();return e?{ok:!0,...await e.revertAll(_wire.dispatchToolAction)}:{ok:!1,error:"No Ask Buoy session on this device."}},reset:async()=>{const e=await(0,_resetConversation.resetConversation)({dispatch:_wire.dispatchToolAction,undoFirst:!0});return e.cleared?{ok:!0,reverted:e.reverted}:{ok:!1,error:`Couldn't undo ${e.failed.length} change${1===e.failed.length?"":"s"} — conversation kept.`,failed:e.failed}}}};