@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,90 +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 _AskBuoyIcon.ASK_BUOY_ICON_COLOR;
10
- }
11
- });
12
- Object.defineProperty(exports, "AskBuoyIcon", {
13
- enumerable: true,
14
- get: function () {
15
- return _AskBuoyIcon.AskBuoyIcon;
16
- }
17
- });
18
- exports.askBuoyToolPreset = void 0;
19
- exports.createAskBuoyTool = createAskBuoyTool;
20
- var _AskBuoyIcon = require("./components/AskBuoyIcon");
21
- var _AskBuoyModal = require("./components/AskBuoyModal");
22
- var _jsxRuntime = require("react/jsx-runtime");
23
- /**
24
- * The Ask Buoy tool preset.
25
- *
26
- * Manual chrome (`component` renders its own JsModal) rather than the
27
- * declarative `modal` config, because ToolModalShell forwards neither a footer
28
- * slot nor `initialHeight` — and a chat needs a sticky composer and more than
29
- * the default 400pt of sheet.
30
- *
31
- * The config is closed over at creation time rather than read from a store, so
32
- * the endpoint and headers come from the app's own code on every render and
33
- * there is never a copy of them sitting anywhere Buoy persists.
34
- */
35
-
36
- const askBuoyToolPreset = exports.askBuoyToolPreset = {
37
- id: "ask-buoy",
38
- name: "ASK BUOY",
39
- description: "Ask about this app in plain English",
40
- slot: "both",
41
- // Set here rather than in floating-tools-core's `toolColors` map: that map
42
- // is already missing half the shipped tools, so the web twin falls back to a
43
- // generic accent for them. A color on the preset is the one place both
44
- // native and web read.
45
- color: _AskBuoyIcon.ASK_BUOY_ICON_COLOR,
46
- icon: ({
47
- size,
48
- color
49
- }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_AskBuoyIcon.AskBuoyIcon, {
50
- size: size,
51
- color: color || _AskBuoyIcon.ASK_BUOY_ICON_COLOR
52
- }),
53
- component: _AskBuoyModal.AskBuoyModal
54
- };
55
-
56
- /**
57
- * `endpoint` and `model` are REQUIRED at the type level. This used to extend
58
- * Partial<AskBuoyConfig> with a cast, so a missing endpoint type-checked and
59
- * only surfaced as a runtime "not set up yet" — the wrong moment to learn it.
60
- */
61
-
62
- /**
63
- * Wire Ask Buoy to your team's AI endpoint.
64
- *
65
- * @example
66
- * createAskBuoyTool({
67
- * endpoint: "https://ai.acme.com/v1/messages",
68
- * model: "claude-opus-5",
69
- * headers: async () => ({ Authorization: `Bearer ${await auth.getToken()}` }),
70
- * context: { notes: ["user.rewards.points = loyalty points"] },
71
- * })
72
- */
73
- function createAskBuoyTool(config) {
74
- const {
75
- name,
76
- description,
77
- ...rest
78
- } = config;
79
- const resolved = rest;
80
- return {
81
- ...askBuoyToolPreset,
82
- name: name ?? askBuoyToolPreset.name,
83
- description: description ?? askBuoyToolPreset.description,
84
- component: props => /*#__PURE__*/(0, _jsxRuntime.jsx)(_AskBuoyModal.AskBuoyModal, {
85
- ...props,
86
- config: resolved
87
- })
88
- };
89
- }
90
- //# sourceMappingURL=preset.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ASK_BUOY_ICON_COLOR",{enumerable:!0,get:function(){return _AskBuoyIcon.ASK_BUOY_ICON_COLOR}}),Object.defineProperty(exports,"AskBuoyIcon",{enumerable:!0,get:function(){return _AskBuoyIcon.AskBuoyIcon}}),exports.askBuoyToolPreset=void 0,exports.createAskBuoyTool=createAskBuoyTool;var _AskBuoyIcon=require("./components/AskBuoyIcon"),_AskBuoyModal=require("./components/AskBuoyModal"),_jsxRuntime=require("react/jsx-runtime");const askBuoyToolPreset=exports.askBuoyToolPreset={id:"ask-buoy",name:"ASK BUOY",description:"Ask about this app in plain English",slot:"both",color:_AskBuoyIcon.ASK_BUOY_ICON_COLOR,icon:({size:o,slot:e})=>(0,_jsxRuntime.jsx)(_AskBuoyIcon.AskBuoyIcon,{size:"dial"===e?1.5*o:o}),component:_AskBuoyModal.AskBuoyModal};function createAskBuoyTool(o){const{name:e,description:s,...t}=o,n=t;return{...askBuoyToolPreset,name:e??askBuoyToolPreset.name,description:s??askBuoyToolPreset.description,component:o=>(0,_jsxRuntime.jsx)(_AskBuoyModal.AskBuoyModal,{...o,config:n})}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatElapsed=formatElapsed,exports.groupCalls=groupCalls,exports.turnFooter=turnFooter;var _agentCore=require("@buoy-gg/agent-core");const foldable=t=>"read"===t.effect&&"ok"===t.status;function groupCalls(t){const e=[];let o=[];const n=()=>{if(0!==o.length){if(1===o.length)e.push({kind:"call",call:o[0]});else{const t=[...new Set(o.map(t=>(0,_agentCore.toolTitle)(t.toolId)))];e.push({kind:"reads",id:o.map(t=>t.id).join("+"),calls:o,label:`Looked at ${joinNatural(t)}`,count:o.length})}o=[]}};for(const l of t)foldable(l)?o.push(l):(n(),e.push({kind:"call",call:l}));return n(),e}function joinNatural(t){return t.length<=1?t[0]??"":2===t.length?`${t[0]} and ${t[1]}`:`${t.slice(0,-1).join(", ")} and ${t[t.length-1]}`}function turnFooter(t){const e=[];void 0!==t.startedAt&&void 0!==t.endedAt&&t.endedAt>=t.startedAt&&e.push(formatElapsed(t.endedAt-t.startedAt));const o=t.toolCalls.length;if(o>0){e.push(`${o} action${1===o?"":"s"}`);const n=e=>t.toolCalls.filter(t=>t.status===e).length,l=n("failed"),r=n("refused"),a=n("declined"),s=n("stopped");l&&e.push(`${l} failed`),r&&e.push(`${r} refused`),a&&e.push(`${a} declined`),s&&e.push(`${s} not run`)}return e.length?e.join(" · "):null}function formatElapsed(t){const e=Math.max(0,Math.floor(t/1e3));if(e<60)return`${e}s`;const o=Math.floor(e/60);return o<60?`${o}m ${String(e%60).padStart(2,"0")}s`:`${Math.floor(o/60)}h ${String(o%60).padStart(2,"0")}m`}
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest"),_activityGroups=require("./activityGroups");const call=(t,e,a,s="ok")=>({id:t,toolId:e,action:"x",label:`${e} ${t}`,status:s,effect:a});(0,_vitest.describe)("groupCalls",()=>{(0,_vitest.it)("leaves a single read as an ordinary row",()=>{const t=(0,_activityGroups.groupCalls)([call("a","console","read")]);(0,_vitest.expect)(t).toEqual([{kind:"call",call:_vitest.expect.objectContaining({id:"a"})}])}),(0,_vitest.it)("folds consecutive successful reads and names the tools once each",()=>{const t=(0,_activityGroups.groupCalls)([call("a","network","read"),call("b","storage","read"),call("c","storage","read")]);(0,_vitest.expect)(t).toHaveLength(1);const e=t[0];(0,_vitest.expect)(e.kind).toBe("reads"),(0,_vitest.expect)("reads"===e.kind&&e.count).toBe(3),(0,_vitest.expect)("reads"===e.kind&&e.label).toBe("Looked at Network and Storage")}),(0,_vitest.it)("never folds a write, and never folds reads across one",()=>{const t=(0,_activityGroups.groupCalls)([call("a","network","read"),call("b","storage","read"),call("w","zustand","write"),call("c","storage","read"),call("d","console","read")]);(0,_vitest.expect)(t.map(t=>"reads"===t.kind?`reads:${t.count}`:`call:${t.call.id}`)).toEqual(["reads:2","call:w","reads:2"])}),(0,_vitest.it)("keeps failed, refused, declined, stopped and running reads as their own rows",()=>{const t=(0,_activityGroups.groupCalls)([call("a","network","read"),call("f","storage","read","failed"),call("b","storage","read"),call("r","storage","read","running")]);(0,_vitest.expect)(t.map(t=>t.kind)).toEqual(["call","call","call","call"])})}),(0,_vitest.describe)("turnFooter",()=>{(0,_vitest.it)("reports duration and action count",()=>{(0,_vitest.expect)((0,_activityGroups.turnFooter)({startedAt:1e3,endedAt:13e3,toolCalls:[call("a","network","read"),call("b","zustand","write")]})).toBe("12s · 2 actions")}),(0,_vitest.it)("separates the outcomes that were not plain successes",()=>{(0,_vitest.expect)((0,_activityGroups.turnFooter)({startedAt:0,endedAt:48e3,toolCalls:[call("a","network","read"),call("b","storage","write","failed"),call("c","storage","destructive","declined"),call("d","storage","write","stopped")]})).toBe("48s · 4 actions · 1 failed · 1 declined · 1 not run")}),(0,_vitest.it)("invents no duration for a note with no start time",()=>{(0,_vitest.expect)((0,_activityGroups.turnFooter)({endedAt:5e3,toolCalls:[]})).toBeNull(),(0,_vitest.expect)((0,_activityGroups.turnFooter)({endedAt:5e3,toolCalls:[call("a","network","read")]})).toBe("1 action")})}),(0,_vitest.describe)("formatElapsed",()=>{(0,_vitest.it)("is compact",()=>{(0,_vitest.expect)((0,_activityGroups.formatElapsed)(4200)).toBe("4s"),(0,_vitest.expect)((0,_activityGroups.formatElapsed)(64e3)).toBe("1m 04s"),(0,_vitest.expect)((0,_activityGroups.formatElapsed)(372e4)).toBe("1h 02m")})});
@@ -1,67 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.askBuoySettings = exports.DEFAULT_SETTINGS = void 0;
7
- var _sharedUi = require("@buoy-gg/shared-ui");
8
- /**
9
- * Ask Buoy's own preferences — the things a tester sets on the sheet, not the
10
- * things a developer sets in `askBuoy={{ … }}`.
11
- *
12
- * Module-level and subscribable for the same reason the transcript is: the
13
- * sheet unmounts whenever the tool is closed or minimised, and a preference
14
- * that reset on every close would not be a preference.
15
- */
16
-
17
- const DEFAULT_SETTINGS = exports.DEFAULT_SETTINGS = {
18
- showThinking: false
19
- };
20
- const store = (0, _sharedUi.definePersistedSetting)(`${_sharedUi.devToolsStorageKeys.base}_ask_buoy_settings`, DEFAULT_SETTINGS, {
21
- sanitize: merged => ({
22
- showThinking: merged.showThinking === true
23
- })
24
- });
25
- let current = DEFAULT_SETTINGS;
26
- let loaded = false;
27
- const listeners = new Set();
28
- function emit() {
29
- for (const fn of listeners) {
30
- try {
31
- fn();
32
- } catch {
33
- // A throwing subscriber must not take the sheet down.
34
- }
35
- }
36
- }
37
- const askBuoySettings = exports.askBuoySettings = {
38
- get: () => current,
39
- subscribe(fn) {
40
- listeners.add(fn);
41
- // First subscriber pays for the read; everyone after gets the cached value.
42
- if (!loaded) {
43
- loaded = true;
44
- void store.load().then(value => {
45
- current = value;
46
- emit();
47
- });
48
- }
49
- return () => listeners.delete(fn);
50
- },
51
- set(key, value) {
52
- if (current[key] === value) return;
53
- current = {
54
- ...current,
55
- [key]: value
56
- };
57
- emit();
58
- void store.save(current);
59
- },
60
- /** Tests only — the module cache would otherwise leak between them. */
61
- reset() {
62
- current = DEFAULT_SETTINGS;
63
- loaded = false;
64
- void store.clear();
65
- }
66
- };
67
- //# sourceMappingURL=askBuoySettings.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.askBuoySettings=exports.DEFAULT_SETTINGS=void 0;var _sharedUi=require("@buoy-gg/shared-ui");const DEFAULT_SETTINGS=exports.DEFAULT_SETTINGS={showThinking:!1,bypassApprovals:!1,readOnly:!1},store=(0,_sharedUi.definePersistedSetting)(`${_sharedUi.devToolsStorageKeys.base}_ask_buoy_settings`,DEFAULT_SETTINGS,{sanitize:e=>({showThinking:!0===e.showThinking,bypassApprovals:!0===e.bypassApprovals,readOnly:!0===e.readOnly})});let current=DEFAULT_SETTINGS,loaded=!1;const listeners=new Set;function emit(){for(const e of listeners)try{e()}catch{}}const askBuoySettings=exports.askBuoySettings={get:()=>current,subscribe:e=>(listeners.add(e),loaded||(loaded=!0,store.load().then(e=>{current=e,emit()})),()=>listeners.delete(e)),set(e,s){current[e]!==s&&(current={...current,[e]:s},emit(),store.save(current))},reset(){current=DEFAULT_SETTINGS,loaded=!1,store.clear()}};
@@ -1,365 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.askBuoyStore = void 0;
7
- var _agentCore = require("@buoy-gg/agent-core");
8
- /**
9
- * Conversation state for the sheet.
10
- *
11
- * A module-level store rather than component state for two reasons: the sheet
12
- * is unmounted whenever the tool is closed or minimised (and a conversation
13
- * that vanished because someone tapped away would be maddening), and the sync
14
- * adapter needs to read the same transcript to show it on the desktop.
15
- *
16
- * Persisted across restarts, on purpose, with the payloads left out — see
17
- * `transcriptPersistence.ts` for what is written and what that costs. The
18
- * store itself stays a plain in-memory store; saving is a subscriber, and
19
- * `hydrate` is the one way anything comes back in.
20
- */
21
-
22
- /** A block in a message, and (for receipts) the tool call that produced it. */
23
-
24
- /**
25
- * A stretch of the model's own reasoning, and where it fell.
26
- *
27
- * `afterCalls` is how many tool calls this message had already made when the
28
- * thought arrived, so the thinking view can lay reasoning and steps out in the
29
- * order they actually happened. One assistant bubble spans every turn of a
30
- * multi-step run, so "think, act, think, act" is the normal shape and showing
31
- * all the thoughts in a lump at the top would misreport it.
32
- */
33
-
34
- /**
35
- * Message ids carry this run's token — see agent-core's `runId`. A plain `m1`
36
- * collided head-on with the `m1` in a restored transcript, and the message
37
- * list keys on it.
38
- */
39
- const nextId = (0, _agentCore.idFactory)("m");
40
-
41
- /**
42
- * Params, as one readable line. Capped because a step can carry a whole
43
- * response body or a store's full state, and this is chrome inside a chat
44
- * bubble — the full value is a tool read away.
45
- */
46
- const MAX_PARAM_CHARS = 400;
47
- function encodeParams(params) {
48
- if (!params || Object.keys(params).length === 0) return undefined;
49
- try {
50
- const json = JSON.stringify(params);
51
- return json.length > MAX_PARAM_CHARS ? `${json.slice(0, MAX_PARAM_CHARS)}…` : json;
52
- } catch {
53
- return undefined;
54
- }
55
- }
56
- let state = {
57
- messages: [],
58
- busy: false,
59
- pending: null,
60
- notice: null,
61
- configured: false,
62
- answers: {},
63
- awaitingBlockId: null,
64
- actionState: {},
65
- queued: null,
66
- usage: {
67
- input: 0,
68
- output: 0,
69
- requests: 0
70
- },
71
- meta: {}
72
- };
73
- const listeners = new Set();
74
- let ledgerRef = null;
75
-
76
- /**
77
- * The session outlives the sheet the same way the transcript does. Session and
78
- * ledger used to be per-mount: closing and reopening the tool kept the visible
79
- * conversation but silently swapped in an empty ledger and a blank model
80
- * memory — the undo bar vanished while the agent's changes stayed live in the
81
- * app. Held here, keyed by a config signature so a real reconfiguration
82
- * (different endpoint/model/tool set) still rebuilds.
83
- */
84
- let heldSession = null;
85
- function set(next) {
86
- state = {
87
- ...state,
88
- ...next
89
- };
90
- for (const fn of listeners) {
91
- try {
92
- fn();
93
- } catch {
94
- // A throwing subscriber must not take the transcript down mid-answer.
95
- }
96
- }
97
- }
98
- const askBuoyStore = exports.askBuoyStore = {
99
- getState: () => state,
100
- subscribe(fn) {
101
- listeners.add(fn);
102
- return () => listeners.delete(fn);
103
- },
104
- setLedger(ledger) {
105
- ledgerRef = ledger;
106
- },
107
- getLedger() {
108
- return ledgerRef;
109
- },
110
- holdSession(session, signature) {
111
- heldSession = {
112
- session,
113
- signature
114
- };
115
- },
116
- getHeldSession() {
117
- return heldSession;
118
- },
119
- setNotice(notice) {
120
- set({
121
- notice
122
- });
123
- },
124
- setConfigured(configured) {
125
- if (configured !== state.configured) set({
126
- configured
127
- });
128
- },
129
- setMeta(meta) {
130
- const same = Object.keys(meta).every(k => state.meta[k] === meta[k]);
131
- if (!same) set({
132
- meta: {
133
- ...state.meta,
134
- ...meta
135
- }
136
- });
137
- },
138
- addUser(text) {
139
- set({
140
- messages: [...state.messages, {
141
- id: nextId(),
142
- role: "user",
143
- text,
144
- toolCalls: [],
145
- blocks: []
146
- }],
147
- busy: true
148
- });
149
- },
150
- /** Mark a turn as running without adding a bubble — the retry path. */
151
- beginTurn() {
152
- set({
153
- busy: true
154
- });
155
- },
156
- /** Park a message typed mid-turn instead of silently dropping it. */
157
- setQueued(text) {
158
- set({
159
- queued: text
160
- });
161
- },
162
- /** Drop one message — the failed assistant bubble a retry replaces. */
163
- removeMessage(id) {
164
- set({
165
- messages: state.messages.filter(m => m.id !== id)
166
- });
167
- },
168
- /** The user answered (or skipped) an Ask block. */
169
- recordAnswer(answer) {
170
- set({
171
- answers: {
172
- ...state.answers,
173
- [answer.blockId]: answer
174
- },
175
- awaitingBlockId: state.awaitingBlockId === answer.blockId ? null : state.awaitingBlockId
176
- });
177
- },
178
- setActionState(key, value) {
179
- const next = {
180
- ...state.actionState
181
- };
182
- if (value === null) delete next[key];else next[key] = value;
183
- set({
184
- actionState: next
185
- });
186
- },
187
- /** Open a new assistant bubble for the turn that is about to stream. */
188
- startAssistant() {
189
- const id = nextId();
190
- set({
191
- messages: [...state.messages, {
192
- id,
193
- role: "assistant",
194
- text: "",
195
- toolCalls: [],
196
- blocks: [],
197
- streaming: true,
198
- startedAt: Date.now()
199
- }]
200
- });
201
- return id;
202
- },
203
- /**
204
- * Fold one engine event into the open assistant message.
205
- *
206
- * Tool calls render as rows inside the bubble rather than as raw payloads:
207
- * the label is already domain-flavoured ("Set points to 1500"), which is the
208
- * only form a non-developer can actually check.
209
- */
210
- applyEvent(messageId, ev) {
211
- const messages = state.messages.map(m => {
212
- if (m.id !== messageId) return m;
213
- switch (ev.type) {
214
- case "text":
215
- return {
216
- ...m,
217
- text: m.breakBeforeNextText && m.text ? `${m.text.trimEnd()}\n\n${ev.delta}` : m.text + ev.delta,
218
- breakBeforeNextText: false
219
- };
220
- case "reasoning":
221
- return {
222
- ...m,
223
- breakBeforeNextText: true,
224
- reasoning: [...(m.reasoning ?? []), {
225
- text: ev.text,
226
- afterCalls: m.toolCalls.length
227
- }]
228
- };
229
- case "tool-start":
230
- return {
231
- ...m,
232
- toolCalls: [...m.toolCalls, {
233
- id: ev.id,
234
- toolId: ev.toolId,
235
- action: ev.action,
236
- label: ev.label,
237
- description: ev.description,
238
- status: "running",
239
- params: encodeParams(ev.params),
240
- effect: ev.effect,
241
- startedAt: Date.now()
242
- }]
243
- };
244
- case "tool-end":
245
- return {
246
- ...m,
247
- breakBeforeNextText: true,
248
- toolCalls: m.toolCalls.map(c => c.id === ev.id ? {
249
- ...c,
250
- status: !ev.ok && ev.summary === "refused" ? "refused" : ev.ok ? "ok" : "failed",
251
- summary: ev.summary,
252
- durationMs: ev.durationMs,
253
- result: ev.result
254
- } : c)
255
- };
256
- case "block":
257
- return {
258
- ...m,
259
- breakBeforeNextText: true,
260
- blocks: [...m.blocks, {
261
- block: ev.block,
262
- forToolCallId: ev.forToolCallId
263
- }]
264
- };
265
- case "usage":
266
- // Also folded into the session total below. Per MESSAGE as well,
267
- // because "which answer cost 40k tokens" is the question you ask
268
- // when a bill looks wrong, and a session total cannot answer it.
269
- return {
270
- ...m,
271
- usage: {
272
- input: (m.usage?.input ?? 0) + ev.input,
273
- output: (m.usage?.output ?? 0) + ev.output,
274
- requests: (m.usage?.requests ?? 0) + 1
275
- }
276
- };
277
- case "error":
278
- return {
279
- ...m,
280
- error: ev.message
281
- };
282
- default:
283
- return m;
284
- }
285
- });
286
- set({
287
- messages,
288
- ...(ev.type === "awaiting-user" ? {
289
- awaitingBlockId: ev.blockId
290
- } : {}),
291
- ...(ev.type === "usage" ? {
292
- usage: {
293
- input: state.usage.input + ev.input,
294
- output: state.usage.output + ev.output,
295
- requests: state.usage.requests + 1
296
- }
297
- } : {})
298
- });
299
- },
300
- finishAssistant(messageId) {
301
- set({
302
- messages: state.messages.map(m => m.id === messageId ? {
303
- ...m,
304
- streaming: false,
305
- endedAt: Date.now()
306
- } : m),
307
- busy: false
308
- });
309
- },
310
- askApproval(input) {
311
- return new Promise(resolve => {
312
- set({
313
- pending: {
314
- ...input,
315
- resolve
316
- }
317
- });
318
- });
319
- },
320
- answerApproval(approved) {
321
- const pending = state.pending;
322
- set({
323
- pending: null
324
- });
325
- pending?.resolve(approved);
326
- },
327
- /**
328
- * Put a saved conversation back, once, at open.
329
- *
330
- * Refuses if anything has been said already: a slow disk read landing after
331
- * the user has started typing must not shove an old chat in front of them.
332
- */
333
- hydrate(input) {
334
- if (state.messages.length > 0 || state.busy) return false;
335
- set({
336
- messages: input.messages,
337
- answers: input.answers,
338
- usage: input.usage
339
- });
340
- return true;
341
- },
342
- reset() {
343
- // Reject anything still waiting, or the turn hangs forever on a promise
344
- // whose only resolver just left the screen.
345
- state.pending?.resolve(false);
346
- set({
347
- messages: [],
348
- busy: false,
349
- pending: null,
350
- notice: null,
351
- answers: {},
352
- awaitingBlockId: null,
353
- actionState: {},
354
- queued: null,
355
- usage: {
356
- input: 0,
357
- output: 0,
358
- requests: 0
359
- }
360
- // `meta` survives: it describes the app and the endpoint, not the
361
- // conversation, and re-deriving it would need another render pass.
362
- });
363
- }
364
- };
365
- //# sourceMappingURL=askBuoyStore.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.askBuoyStore=void 0,exports.queuePauseReason=queuePauseReason,exports.turnPhaseOf=turnPhaseOf;var _agentCore=require("@buoy-gg/agent-core");const nextId=(0,_agentCore.idFactory)("m"),MAX_PARAM_CHARS=400;function encodeParams(e){if(e&&0!==Object.keys(e).length)try{const t=JSON.stringify(e);return t.length>400?`${t.slice(0,400)}…`:t}catch{return}}const nextQueuedId=(0,_agentCore.idFactory)("q");let state={messages:[],busy:!1,stopping:!1,pending:null,trusted:[],notice:null,configured:!1,answers:{},awaitingBlockId:null,actionState:{},queued:[],draft:null,usage:{input:0,output:0,requests:0},meta:{}};const listeners=new Set;let ledgerRef=null,heldSession=null;function set(e){state={...state,...e};for(const e of listeners)try{e()}catch{}}const askBuoyStore=exports.askBuoyStore={getState:()=>state,subscribe:e=>(listeners.add(e),()=>listeners.delete(e)),setLedger(e){ledgerRef=e},getLedger:()=>ledgerRef,holdSession(e,t){heldSession={session:e,signature:t}},getHeldSession:()=>heldSession,setNotice(e){set({notice:e})},setConfigured(e){e!==state.configured&&set({configured:e})},setMeta(e){Object.keys(e).every(t=>state.meta[t]===e[t])||set({meta:{...state.meta,...e}})},addUser(e){set({messages:[...state.messages,{id:nextId(),role:"user",text:e,toolCalls:[],blocks:[]}],busy:!0})},beginTurn(){set({busy:!0})},enqueue(e){const t={id:nextQueuedId(),text:e};return set({queued:[...state.queued,t]}),t},removeQueued(e){state.queued.some(t=>t.id===e)&&set({queued:state.queued.filter(t=>t.id!==e)})},shiftQueued(){const[e,...t]=state.queued;if(e)return set({queued:t}),e},takeQueuedToDraft(e){const t=state.queued.find(t=>t.id===e);t&&set({queued:state.queued.filter(t=>t.id!==e),draft:t.text})},requestStop(){state.busy&&!state.stopping&&set({stopping:!0})},clearDraft(){null!==state.draft&&set({draft:null})},removeMessage(e){set({messages:state.messages.filter(t=>t.id!==e)})},recordAnswer(e){set({answers:{...state.answers,[e.blockId]:e},awaitingBlockId:state.awaitingBlockId===e.blockId?null:state.awaitingBlockId})},setActionState(e,t){const s={...state.actionState};null===t?delete s[e]:s[e]=t,set({actionState:s})},startAssistant(){const e=nextId();return set({messages:[...state.messages,{id:e,role:"assistant",text:"",toolCalls:[],blocks:[],streaming:!0,startedAt:Date.now()}]}),e},applyEvent(e,t){if("history-trimmed"===t.type){const s=state.messages.findIndex(t=>t.id===e),a={id:nextId(),role:"assistant",system:!0,text:`Older messages were trimmed from the agent's memory (${t.droppedRounds} exchange${1===t.droppedRounds?"":"s"}).`+(t.droppedPinned?` ${1===t.droppedPinned?"One of them made a change that is":`${t.droppedPinned} of them made changes that are`} still applied — the changes bar still lists ${1===t.droppedPinned?"it":"them"}, but the agent no longer remembers making ${1===t.droppedPinned?"it":"them"}.`:" It may not recall setup from earlier in this chat — the changes bar still lists what is applied."),toolCalls:[],blocks:[],endedAt:Date.now()},n=[...state.messages];return n.splice(s<0?n.length:s,0,a),void set({messages:n})}set({messages:state.messages.map(s=>{if(s.id!==e)return s;switch(t.type){case"retrying":{const e=Math.max(1,Math.round(t.inMs/1e3));return{...s,waiting:"throttled"===t.reason?`Endpoint busy — retrying in ${e}s (${t.attempt} of ${t.maxAttempts})`:"Request too large — trimming older messages and retrying"}}case"text":return{...s,waiting:void 0,text:(s.breakBeforeNextText||t.breakBefore)&&s.text?`${s.text.trimEnd()}\n\n${t.delta}`:s.text+t.delta,breakBeforeNextText:!1};case"reasoning":return{...s,breakBeforeNextText:!0,reasoning:[...s.reasoning??[],{text:t.text,afterCalls:s.toolCalls.length}]};case"tool-start":return{...s,waiting:void 0,toolCalls:[...s.toolCalls,{id:t.id,toolId:t.toolId,action:t.action,label:t.label,description:t.description,status:"running",params:encodeParams(t.params),effect:t.effect,startedAt:Date.now()}]};case"tool-end":return{...s,breakBeforeNextText:!0,toolCalls:s.toolCalls.map(e=>e.id===t.id?{...e,status:t.ok||"refused"!==t.summary?t.ok||"declined"!==t.summary?t.ok||"stopped"!==t.summary?t.ok?"ok":"failed":"stopped":"declined":"refused",summary:t.summary,durationMs:t.durationMs,result:t.result}:e)};case"tool-verified":return{...s,toolCalls:s.toolCalls.map(e=>e.id===t.id?{...e,verification:t.verification}:e)};case"block":return{...s,breakBeforeNextText:!0,blocks:[...s.blocks,{block:t.block,forToolCallId:t.forToolCallId}]};case"usage":return{...s,usage:{input:(s.usage?.input??0)+t.input,output:(s.usage?.output??0)+t.output,requests:(s.usage?.requests??0)+1}};case"error":return{...s,waiting:void 0,error:t.message};default:return s}}),..."awaiting-user"===t.type?{awaitingBlockId:t.blockId}:{},..."usage"===t.type?{usage:{input:state.usage.input+t.input,output:state.usage.output+t.output,requests:state.usage.requests+1}}:{}})},markStopped(e){set({messages:state.messages.map(t=>t.id===e?{...t,stopped:!0}:t)})},finishAssistant(e){set({messages:state.messages.map(t=>t.id===e?{...t,streaming:!1,endedAt:Date.now()}:t),busy:!1,stopping:!1})},askApproval:e=>new Promise(t=>{set({pending:{...e,resolve:t}})}),answerApproval(e){const t=state.pending,s="boolean"==typeof e?e:e.approved,a="boolean"!=typeof e&&!0===e.trust&&s,n=t?`${t.toolId}.${t.action}`:"";set({pending:null,...a&&t&&!state.trusted.some(e=>e.key===n)?{trusted:[...state.trusted,{key:n,label:t.label}]}:{}}),t?.resolve(e)},untrust(e){heldSession?.session.untrust(e),set({trusted:state.trusted.filter(t=>t.key!==e)})},restorePending:e=>!state.pending&&!state.busy&&(set({pending:{...e,restored:!0,resolve:()=>{}}}),!0),addNote(e){set({messages:[...state.messages,{id:nextId(),role:"assistant",text:e,toolCalls:[],blocks:[],endedAt:Date.now()}]})},hydrate:e=>!(state.messages.length>0||state.busy||(set({messages:e.messages.map(e=>({...e,restored:!0})),answers:e.answers,usage:e.usage,queued:e.queued??[]}),0)),reset(){state.pending?.resolve(!1),set({messages:[],busy:!1,stopping:!1,pending:null,trusted:[],notice:null,answers:{},awaitingBlockId:null,actionState:{},queued:[],draft:null,usage:{input:0,output:0,requests:0}})}};function turnPhaseOf(e){return e.pending?"awaitingApproval":e.busy?e.stopping?"stopping":"running":e.awaitingBlockId?"awaitingAnswer":"idle"}function queuePauseReason(e){const t=turnPhaseOf(e);if("running"===t||"stopping"===t)return null;if("awaitingApproval"===t)return"Paused — answer the approval above first.";if("awaitingAnswer"===t)return"Paused — answer the question above first.";const s=e.messages[e.messages.length-1];return"assistant"===s?.role&&s.error?"Paused — the last turn failed.":"assistant"===s?.role&&s.stopped?"Paused — you stopped the last turn.":null}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.placeBlocks=placeBlocks;var _agentCore=require("@buoy-gg/agent-core");function nestsUnderStep({block:e,forToolCallId:o}){if(!o)return!1;const s="source"in e?e.source:void 0;return"live"===s||"mocked"===s}function placeBlocks(e,o){const s=new Set(o),t=new Map,l=[],r=[];for(const o of e)if((0,_agentCore.isAskBlock)(o.block))r.push(o);else if(nestsUnderStep(o)&&s.has(o.forToolCallId)){const e=t.get(o.forToolCallId)??[];e.push(o.block),t.set(o.forToolCallId,e)}else l.push(o);return{nested:t,afterText:l,ask:r}}
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest"),_blockPlacement=require("./blockPlacement");const placed=(e,t)=>({block:e,forToolCallId:t}),grid=(e="ui1")=>placed({id:e,kind:"imageGrid",source:"model",images:[{url:"https://cdn.example.com/25.png",alt:"Pikachu"}]},"call-ui");(0,_vitest.describe)("model-authored blocks",()=>{(0,_vitest.it)("renders in the answer, never nested under a step that has no row",()=>{const{afterText:e,nested:t}=(0,_blockPlacement.placeBlocks)([grid()],["c1"]);(0,_vitest.expect)(e.map(e=>e.block.id)).toEqual(["ui1"]),(0,_vitest.expect)(t.size).toBe(0)}),(0,_vitest.it)("still renders even when a step with that id somehow exists",()=>{const{afterText:e}=(0,_blockPlacement.placeBlocks)([grid()],["call-ui"]);(0,_vitest.expect)(e.map(e=>e.block.id)).toEqual(["ui1"])})}),(0,_vitest.describe)("receipts",()=>{(0,_vitest.it)("folds a read receipt into its own step row",()=>{const e=placed({id:"r1",kind:"keyValue",source:"live",pairs:[]},"c1"),{nested:t,afterText:c}=(0,_blockPlacement.placeBlocks)([e],["c1"]);(0,_vitest.expect)(c).toEqual([]),(0,_vitest.expect)(t.get("c1")?.map(e=>e.id)).toEqual(["r1"])}),(0,_vitest.it)("keeps a write receipt afterText — the user must see it without asking",()=>{const e=placed({id:"w1",kind:"diff",source:"changed",changes:[]},"c1"),{nested:t,afterText:c}=(0,_blockPlacement.placeBlocks)([e],["c1"]);(0,_vitest.expect)(t.size).toBe(0),(0,_vitest.expect)(c.map(e=>e.block.id)).toEqual(["w1"])}),(0,_vitest.it)("falls back to afterText when its step row was never drawn",()=>{const e=placed({id:"r2",kind:"keyValue",source:"live",pairs:[]},"gone"),{afterText:t}=(0,_blockPlacement.placeBlocks)([e],[]);(0,_vitest.expect)(t.map(e=>e.block.id)).toEqual(["r2"])})}),(0,_vitest.describe)("ask blocks",()=>{(0,_vitest.it)("come out in their own bucket, after the answer",()=>{const e=placed({id:"a1",kind:"confirm",source:"model",change:"Wipe storage"},"call-ui"),{ask:t,afterText:c,nested:i}=(0,_blockPlacement.placeBlocks)([e,grid("ui2")],["c1"]);(0,_vitest.expect)(t.map(e=>e.block.id)).toEqual(["a1"]),(0,_vitest.expect)(c.map(e=>e.block.id)).toEqual(["ui2"]),(0,_vitest.expect)(i.size).toBe(0)})}),(0,_vitest.describe)("the answer comes after the prose",()=>{(0,_vitest.it)("puts a model-authored card in the after-text bucket, never before it",()=>{const e=(0,_blockPlacement.placeBlocks)([grid()],["c1"]);(0,_vitest.expect)(e.afterText.map(e=>e.block.id)).toEqual(["ui1"]),(0,_vitest.expect)(e.nested.size).toBe(0)})});
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest"),_askBuoyStore=require("./askBuoyStore");(0,_vitest.beforeEach)(()=>_askBuoyStore.askBuoyStore.reset());const texts=()=>_askBuoyStore.askBuoyStore.getState().queued.map(t=>t.text);(0,_vitest.describe)("queue",()=>{(0,_vitest.it)("keeps every message, in the order typed",()=>{_askBuoyStore.askBuoyStore.enqueue("then set points to 1500"),_askBuoyStore.askBuoyStore.enqueue("and clear the cart after"),(0,_vitest.expect)(texts()).toEqual(["then set points to 1500","and clear the cart after"])}),(0,_vitest.it)("gives identical requests distinct ids",()=>{const t=_askBuoyStore.askBuoyStore.enqueue("again"),e=_askBuoyStore.askBuoyStore.enqueue("again");(0,_vitest.expect)(t.id).not.toBe(e.id),_askBuoyStore.askBuoyStore.removeQueued(t.id),(0,_vitest.expect)(texts()).toEqual(["again"])}),(0,_vitest.it)("delivers from the front, one at a time",()=>{_askBuoyStore.askBuoyStore.enqueue("one"),_askBuoyStore.askBuoyStore.enqueue("two"),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.shiftQueued()?.text).toBe("one"),(0,_vitest.expect)(texts()).toEqual(["two"]),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.shiftQueued()?.text).toBe("two"),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.shiftQueued()).toBeUndefined()}),(0,_vitest.it)("comes back from disk as unsent rows",()=>{const t=_askBuoyStore.askBuoyStore.hydrate({messages:[{id:"m1",role:"user",text:"hi",toolCalls:[],blocks:[]}],answers:{},usage:{input:0,output:0,requests:0},queued:[{id:"q1",text:"still waiting"}]});(0,_vitest.expect)(t).toBe(!0),(0,_vitest.expect)(texts()).toEqual(["still waiting"]),(0,_vitest.expect)((0,_askBuoyStore.turnPhaseOf)(_askBuoyStore.askBuoyStore.getState())).toBe("idle")}),(0,_vitest.it)("is emptied by a new conversation",()=>{_askBuoyStore.askBuoyStore.enqueue("gone"),_askBuoyStore.askBuoyStore.reset(),(0,_vitest.expect)(texts()).toEqual([])})}),(0,_vitest.describe)("turnPhase",()=>{(0,_vitest.it)("is idle with nothing going on",()=>{(0,_vitest.expect)((0,_askBuoyStore.turnPhaseOf)(_askBuoyStore.askBuoyStore.getState())).toBe("idle")}),(0,_vitest.it)("is running during a turn, and stopping once Stop is pressed",()=>{_askBuoyStore.askBuoyStore.addUser("go"),_askBuoyStore.askBuoyStore.startAssistant(),(0,_vitest.expect)((0,_askBuoyStore.turnPhaseOf)(_askBuoyStore.askBuoyStore.getState())).toBe("running"),_askBuoyStore.askBuoyStore.requestStop(),(0,_vitest.expect)((0,_askBuoyStore.turnPhaseOf)(_askBuoyStore.askBuoyStore.getState())).toBe("stopping")}),(0,_vitest.it)("is awaitingApproval while a card is up, even though the turn is busy",()=>{_askBuoyStore.askBuoyStore.addUser("wipe it"),_askBuoyStore.askBuoyStore.startAssistant(),_askBuoyStore.askBuoyStore.askApproval({id:"c1",toolId:"storage",action:"clearAll",label:"Clear all saved app data",reason:"Wipes everything"}),(0,_vitest.expect)((0,_askBuoyStore.turnPhaseOf)(_askBuoyStore.askBuoyStore.getState())).toBe("awaitingApproval")}),(0,_vitest.it)("is awaitingAnswer after a turn ends on an Ask block",()=>{const t=_askBuoyStore.askBuoyStore.startAssistant();_askBuoyStore.askBuoyStore.applyEvent(t,{type:"awaiting-user",blockId:"b1"}),_askBuoyStore.askBuoyStore.finishAssistant(t),(0,_vitest.expect)((0,_askBuoyStore.turnPhaseOf)(_askBuoyStore.askBuoyStore.getState())).toBe("awaitingAnswer")})}),(0,_vitest.describe)("when the queue holds",()=>{(0,_vitest.it)("delivers when idle and the last turn was fine",()=>{_askBuoyStore.askBuoyStore.addUser("hi");const t=_askBuoyStore.askBuoyStore.startAssistant();_askBuoyStore.askBuoyStore.applyEvent(t,{type:"text",delta:"Hello."}),_askBuoyStore.askBuoyStore.finishAssistant(t),(0,_vitest.expect)((0,_askBuoyStore.queuePauseReason)(_askBuoyStore.askBuoyStore.getState())).toBeNull()}),(0,_vitest.it)("holds after an error, and says so",()=>{_askBuoyStore.askBuoyStore.addUser("hi");const t=_askBuoyStore.askBuoyStore.startAssistant();_askBuoyStore.askBuoyStore.applyEvent(t,{type:"error",message:"fetch failed"}),_askBuoyStore.askBuoyStore.finishAssistant(t),(0,_vitest.expect)((0,_askBuoyStore.queuePauseReason)(_askBuoyStore.askBuoyStore.getState())).toMatch(/failed/)}),(0,_vitest.it)("holds while an approval card is up",()=>{_askBuoyStore.askBuoyStore.addUser("wipe"),_askBuoyStore.askBuoyStore.startAssistant(),_askBuoyStore.askBuoyStore.askApproval({id:"c1",toolId:"storage",action:"clearAll",label:"Clear all saved app data",reason:"Wipes everything"}),(0,_vitest.expect)((0,_askBuoyStore.queuePauseReason)(_askBuoyStore.askBuoyStore.getState())).toMatch(/approval/)}),(0,_vitest.it)("holds while a question is unanswered — a queued task is not the answer",()=>{const t=_askBuoyStore.askBuoyStore.startAssistant();_askBuoyStore.askBuoyStore.applyEvent(t,{type:"awaiting-user",blockId:"b1"}),_askBuoyStore.askBuoyStore.finishAssistant(t),(0,_vitest.expect)((0,_askBuoyStore.queuePauseReason)(_askBuoyStore.askBuoyStore.getState())).toMatch(/question/)}),(0,_vitest.it)("says nothing while a turn is still running — the queue is simply waiting",()=>{_askBuoyStore.askBuoyStore.addUser("go"),_askBuoyStore.askBuoyStore.startAssistant(),(0,_vitest.expect)((0,_askBuoyStore.queuePauseReason)(_askBuoyStore.askBuoyStore.getState())).toBeNull()})});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.clearConversation=clearConversation,exports.resetConversation=resetConversation;var _askBuoyStore=require("./askBuoyStore"),_transcriptPersistence=require("./transcriptPersistence");function clearConversation(){_askBuoyStore.askBuoyStore.getHeldSession()?.session.reset(),_askBuoyStore.askBuoyStore.reset(),(0,_transcriptPersistence.clearTranscript)()}async function resetConversation(e){if(_askBuoyStore.askBuoyStore.getState().busy)return{cleared:!1,reverted:0,failed:[{label:"A turn is running",error:"Stop it first."}]};const r=_askBuoyStore.askBuoyStore.getLedger();if(e.undoFirst&&r){const t=await r.revertAll(e.dispatch);return t.failed.length>0?{cleared:!1,reverted:t.reverted,failed:t.failed}:(clearConversation(),{cleared:!0,reverted:t.reverted,failed:[]})}return clearConversation(),{cleared:!0,reverted:0,failed:[]}}
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest"),_askBuoyStore=require("./askBuoyStore");const card={id:"c1",toolId:"zustand",action:"setState",label:"Update the Poké Mart bag store",reason:"This will change the app's state.",params:{storeName:"bag"}};(0,_vitest.beforeEach)(()=>_askBuoyStore.askBuoyStore.reset()),(0,_vitest.describe)("restorePending",()=>{(0,_vitest.it)("puts the card back on screen",()=>{(0,_vitest.expect)(_askBuoyStore.askBuoyStore.restorePending(card)).toBe(!0),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.getState().pending).toMatchObject({toolId:"zustand",action:"setState",params:{storeName:"bag"}})}),(0,_vitest.it)("marks it restored, so Allow runs the call instead of answering a dead promise",()=>{_askBuoyStore.askBuoyStore.restorePending(card),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.getState().pending?.restored).toBe(!0)}),(0,_vitest.it)("refuses once a turn is under way",()=>{_askBuoyStore.askBuoyStore.beginTurn(),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.restorePending(card)).toBe(!1),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.getState().pending).toBeNull()}),(0,_vitest.it)("refuses when a live card is already asking",()=>{_askBuoyStore.askBuoyStore.askApproval(card),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.restorePending({...card,id:"c2"})).toBe(!1),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.getState().pending?.id).toBe("c1")}),(0,_vitest.it)("answers without throwing, though nothing is waiting on it",()=>{_askBuoyStore.askBuoyStore.restorePending(card),(0,_vitest.expect)(()=>_askBuoyStore.askBuoyStore.answerApproval(!0)).not.toThrow(),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.getState().pending).toBeNull()})});
@@ -1,47 +1 @@
1
- "use strict";
2
-
3
- var _vitest = require("vitest");
4
- var _agentCore = require("@buoy-gg/agent-core");
5
- /**
6
- * Ids from a RESTORED transcript must never collide with a fresh run's.
7
- *
8
- * The bug this covers, in full: every id counter restarted at 1 with the
9
- * process, which was harmless until the transcript started outliving a reload.
10
- * A restored conversation came back holding `rc1`, `ui1` and `m1`; the next
11
- * turn minted `rc1` again; React saw two children with one key and rendered
12
- * one of them twice while dropping the other. On screen that was the same
13
- * store card appearing twice after a reload.
14
- *
15
- * Simulating a restart in one process is the whole difficulty — the module
16
- * caches its counter. `idFactory` is the seam: a second factory stands in for
17
- * the second run, and the shared RUN_ID is what has to differ between them.
18
- */
19
-
20
- (0, _vitest.describe)("ids across a restart", () => {
21
- (0, _vitest.it)("never reissues an id a restored transcript already holds", () => {
22
- // What a saved transcript carries, from a previous launch.
23
- const restored = ["rcOLDRUN-1", "rcOLDRUN-2", "uiOLDRUN-1", "mOLDRUN-1"];
24
- const rc = (0, _agentCore.idFactory)("rc");
25
- const ui = (0, _agentCore.idFactory)("ui");
26
- const m = (0, _agentCore.idFactory)("m");
27
- const fresh = [rc(), rc(), ui(), m()];
28
- for (const id of fresh) (0, _vitest.expect)(restored).not.toContain(id);
29
- });
30
- (0, _vitest.it)("still counts up within one run", () => {
31
- // The counter is what keeps two blocks in the SAME turn apart.
32
- const rc = (0, _agentCore.idFactory)("rc");
33
- const ids = [rc(), rc(), rc()];
34
- (0, _vitest.expect)(new Set(ids).size).toBe(3);
35
- });
36
- (0, _vitest.it)("keeps two prefixes apart even at the same count", () => {
37
- const rc = (0, _agentCore.idFactory)("rc");
38
- const ui = (0, _agentCore.idFactory)("ui");
39
- (0, _vitest.expect)(rc()).not.toBe(ui());
40
- });
41
- (0, _vitest.it)("stamps a run token that is not a fixed string", () => {
42
- // A constant here would put every install back where it started.
43
- (0, _vitest.expect)(_agentCore.RUN_ID).toMatch(/^[a-z0-9]{4,8}$/);
44
- (0, _vitest.expect)((0, _agentCore.idFactory)("rc")()).toBe(`rc${_agentCore.RUN_ID}-1`);
45
- });
46
- });
47
- //# sourceMappingURL=restoredIds.test.js.map
1
+ "use strict";var _vitest=require("vitest"),_agentCore=require("@buoy-gg/agent-core");(0,_vitest.describe)("ids across a restart",()=>{(0,_vitest.it)("never reissues an id a restored transcript already holds",()=>{const t=["rcOLDRUN-1","rcOLDRUN-2","uiOLDRUN-1","mOLDRUN-1"],e=(0,_agentCore.idFactory)("rc"),r=(0,_agentCore.idFactory)("ui"),i=(0,_agentCore.idFactory)("m"),o=[e(),e(),r(),i()];for(const e of o)(0,_vitest.expect)(t).not.toContain(e)}),(0,_vitest.it)("still counts up within one run",()=>{const t=(0,_agentCore.idFactory)("rc"),e=[t(),t(),t()];(0,_vitest.expect)(new Set(e).size).toBe(3)}),(0,_vitest.it)("keeps two prefixes apart even at the same count",()=>{const t=(0,_agentCore.idFactory)("rc"),e=(0,_agentCore.idFactory)("ui");(0,_vitest.expect)(t()).not.toBe(e())}),(0,_vitest.it)("stamps a run token that is not a fixed string",()=>{(0,_vitest.expect)(_agentCore.RUN_ID).toMatch(/^[a-z0-9]{4,8}$/),(0,_vitest.expect)((0,_agentCore.idFactory)("rc")()).toBe(`rc${_agentCore.RUN_ID}-1`)})});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.SUGGESTIONS=exports.MAX_SUGGESTIONS=void 0,exports.pickSuggestions=pickSuggestions;const SUGGESTIONS=exports.SUGGESTIONS=[{text:"Why is this screen empty?"},{text:"What did the last few network calls return?",needs:"network"},{text:"Show me what's saved for this user",needs:"storage"},{text:"Make the next request to this screen fail with a 500",needs:"network",write:!0,devOnly:!0},{text:"Who am I signed in as right now?"},{text:"Did anything crash or log an error recently?",needs:"console"}],MAX_SUGGESTIONS=exports.MAX_SUGGESTIONS=4;function pickSuggestions(e){const t=e.availableToolIds.length>0;return SUGGESTIONS.filter(s=>(!s.write||!e.readOnly)&&(!s.devOnly||!e.isRelease)&&(!s.needs||t&&e.availableToolIds.includes(s.needs))).slice(0,MAX_SUGGESTIONS).map(e=>e.text)}
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest"),_suggestions=require("./suggestions");const all=["network","storage","console","query"];(0,_vitest.describe)("pickSuggestions",()=>{(0,_vitest.it)("offers the simulation only on a dev build that may write",()=>{const e=(0,_suggestions.pickSuggestions)({availableToolIds:all,readOnly:!1,isRelease:!1});(0,_vitest.expect)(e).toContain("Make the next request to this screen fail with a 500");const t=(0,_suggestions.pickSuggestions)({availableToolIds:all,readOnly:!1,isRelease:!0});(0,_vitest.expect)(t).not.toContain("Make the next request to this screen fail with a 500");const s=(0,_suggestions.pickSuggestions)({availableToolIds:all,readOnly:!0,isRelease:!1});(0,_vitest.expect)(s).not.toContain("Make the next request to this screen fail with a 500")}),(0,_vitest.it)("drops chips whose tool is not on this device",()=>{const e=(0,_suggestions.pickSuggestions)({availableToolIds:["storage"],readOnly:!1,isRelease:!1});(0,_vitest.expect)(e).not.toContain("What did the last few network calls return?"),(0,_vitest.expect)(e).toContain("Show me what's saved for this user")}),(0,_vitest.it)("shows only tool-free chips until the registry has reported",()=>{const e=(0,_suggestions.pickSuggestions)({availableToolIds:[],readOnly:!1,isRelease:!1});(0,_vitest.expect)(e).toEqual(["Why is this screen empty?","Who am I signed in as right now?"])}),(0,_vitest.it)("never exceeds the cap and keeps the order",()=>{const e=(0,_suggestions.pickSuggestions)({availableToolIds:all,readOnly:!1,isRelease:!1});(0,_vitest.expect)(e.length).toBeLessThanOrEqual(_suggestions.MAX_SUGGESTIONS),(0,_vitest.expect)(e[0]).toBe("Why is this screen empty?")})});
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest"),_askBuoyStore=require("./askBuoyStore"),_transcriptPersistence=require("./transcriptPersistence");(0,_vitest.beforeEach)(()=>_askBuoyStore.askBuoyStore.reset()),(0,_vitest.describe)("history-trimmed",()=>{(0,_vitest.it)("inserts a system line before the answer it affects",()=>{_askBuoyStore.askBuoyStore.addUser("turn off that override");const t=_askBuoyStore.askBuoyStore.startAssistant();_askBuoyStore.askBuoyStore.applyEvent(t,{type:"history-trimmed",droppedRounds:3}),_askBuoyStore.askBuoyStore.applyEvent(t,{type:"text",delta:"Turning it off."});const e=_askBuoyStore.askBuoyStore.getState().messages.map(t=>t.system?"system":t.role);(0,_vitest.expect)(e).toEqual(["user","system","assistant"]);const s=_askBuoyStore.askBuoyStore.getState().messages[1];(0,_vitest.expect)(s.text).toMatch(/3 exchanges/),(0,_vitest.expect)(s.text).toMatch(/changes bar still lists/)}),(0,_vitest.it)("singular for one round",()=>{const t=_askBuoyStore.askBuoyStore.startAssistant();_askBuoyStore.askBuoyStore.applyEvent(t,{type:"history-trimmed",droppedRounds:1}),(0,_vitest.expect)(_askBuoyStore.askBuoyStore.getState().messages[0].text).toMatch(/1 exchange\)/)})}),(0,_vitest.describe)("restored approval freshness",()=>{(0,_vitest.it)("carries the target digest to disk and back, never the target",()=>{const t=(0,_transcriptPersistence.buildPayload)({messages:[{id:"m1",role:"user",text:"set it",toolCalls:[],blocks:[]}],history:[],answers:{},usage:{input:0,output:0,requests:0},pending:{id:"c1",toolId:"zustand",action:"setState",label:"Update the bag store",reason:"Replaces part of the store",params:{storeName:"bag",state:{qty:14}},targetDigest:"1a2b3c:512",resolve:()=>{}}}),e=JSON.stringify(t);(0,_vitest.expect)(e).toContain("1a2b3c:512");const s=(0,_transcriptPersistence.parsePayload)(e);(0,_vitest.expect)(s?.pending?.targetDigest).toBe("1a2b3c:512")})});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TICKET_PROMPT=void 0;const TICKET_PROMPT=exports.TICKET_PROMPT="Summarize this conversation as a bug ticket, using one buoy_ui finding block and nothing else. Title it with the problem in one line. Evidence rows, in this order: Steps (what we did), Expected, Observed, Build (dev or release, platform), Evidence (the exact requests, statuses, logs or values you actually saw this conversation), Still applied (overrides or changes from your changes list that are still live, or 'none'). Only facts you observed in this conversation; write 'unknown' where you don't know rather than guessing, and put anything you inferred rather than saw in a final row labelled Inference. Do not run any tool or change anything to produce this.";