@buoy-gg/ask-buoy 7.0.34 → 7.0.35

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 (239) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/blocks/AskBlocks.js +338 -1
  3. package/lib/commonjs/blocks/AskBlocks.js.map +1 -0
  4. package/lib/commonjs/blocks/BlockRenderer.js +250 -1
  5. package/lib/commonjs/blocks/BlockRenderer.js.map +1 -0
  6. package/lib/commonjs/blocks/ChromePrototypes.js +514 -1
  7. package/lib/commonjs/blocks/ChromePrototypes.js.map +1 -0
  8. package/lib/commonjs/blocks/DataBlocks.js +688 -1
  9. package/lib/commonjs/blocks/DataBlocks.js.map +1 -0
  10. package/lib/commonjs/blocks/ExtraBlocks.js +1854 -1
  11. package/lib/commonjs/blocks/ExtraBlocks.js.map +1 -0
  12. package/lib/commonjs/blocks/MediaBlocks.js +140 -1
  13. package/lib/commonjs/blocks/MediaBlocks.js.map +1 -0
  14. package/lib/commonjs/blocks/ReceiptBlocks.js +586 -1
  15. package/lib/commonjs/blocks/ReceiptBlocks.js.map +1 -0
  16. package/lib/commonjs/blocks/context.js +42 -1
  17. package/lib/commonjs/blocks/context.js.map +1 -0
  18. package/lib/commonjs/blocks/icons.js +96 -1
  19. package/lib/commonjs/blocks/icons.js.map +1 -0
  20. package/lib/commonjs/blocks/index.js +95 -1
  21. package/lib/commonjs/blocks/index.js.map +1 -0
  22. package/lib/commonjs/blocks/listRow.test.js +55 -0
  23. package/lib/commonjs/blocks/listRow.test.js.map +1 -0
  24. package/lib/commonjs/blocks/pageState.js +34 -0
  25. package/lib/commonjs/blocks/pageState.js.map +1 -0
  26. package/lib/commonjs/blocks/pageState.test.js +57 -0
  27. package/lib/commonjs/blocks/pageState.test.js.map +1 -0
  28. package/lib/commonjs/blocks/primitives.js +401 -1
  29. package/lib/commonjs/blocks/primitives.js.map +1 -0
  30. package/lib/commonjs/blocks/primitivesIndex.js +62 -1
  31. package/lib/commonjs/blocks/primitivesIndex.js.map +1 -0
  32. package/lib/commonjs/components/ApprovalCard.js +140 -1
  33. package/lib/commonjs/components/ApprovalCard.js.map +1 -0
  34. package/lib/commonjs/components/AskBuoyHeader.js +164 -1
  35. package/lib/commonjs/components/AskBuoyHeader.js.map +1 -0
  36. package/lib/commonjs/components/AskBuoyIcon.js +19 -1
  37. package/lib/commonjs/components/AskBuoyIcon.js.map +1 -0
  38. package/lib/commonjs/components/AskBuoyModal.js +353 -1
  39. package/lib/commonjs/components/AskBuoyModal.js.map +1 -0
  40. package/lib/commonjs/components/AskBuoySettings.js +69 -0
  41. package/lib/commonjs/components/AskBuoySettings.js.map +1 -0
  42. package/lib/commonjs/components/ChangesBar.js +211 -1
  43. package/lib/commonjs/components/ChangesBar.js.map +1 -0
  44. package/lib/commonjs/components/Composer.js +175 -1
  45. package/lib/commonjs/components/Composer.js.map +1 -0
  46. package/lib/commonjs/components/EmptyState.js +154 -1
  47. package/lib/commonjs/components/EmptyState.js.map +1 -0
  48. package/lib/commonjs/components/Markdown.js +252 -1
  49. package/lib/commonjs/components/Markdown.js.map +1 -0
  50. package/lib/commonjs/components/MessageList.js +683 -1
  51. package/lib/commonjs/components/MessageList.js.map +1 -0
  52. package/lib/commonjs/components/ThinkingStrip.js +223 -0
  53. package/lib/commonjs/components/ThinkingStrip.js.map +1 -0
  54. package/lib/commonjs/components/TypingDots.js +63 -1
  55. package/lib/commonjs/components/TypingDots.js.map +1 -0
  56. package/lib/commonjs/components/useCopyAction.js +50 -0
  57. package/lib/commonjs/components/useCopyAction.js.map +1 -0
  58. package/lib/commonjs/index.js +252 -1
  59. package/lib/commonjs/index.js.map +1 -0
  60. package/lib/commonjs/preset.js +90 -1
  61. package/lib/commonjs/preset.js.map +1 -0
  62. package/lib/commonjs/store/askBuoySettings.js +67 -0
  63. package/lib/commonjs/store/askBuoySettings.js.map +1 -0
  64. package/lib/commonjs/store/askBuoyStore.js +365 -1
  65. package/lib/commonjs/store/askBuoyStore.js.map +1 -0
  66. package/lib/commonjs/store/restoredIds.test.js +47 -0
  67. package/lib/commonjs/store/restoredIds.test.js.map +1 -0
  68. package/lib/commonjs/store/traceText.js +81 -0
  69. package/lib/commonjs/store/traceText.js.map +1 -0
  70. package/lib/commonjs/store/traceText.test.js +112 -0
  71. package/lib/commonjs/store/traceText.test.js.map +1 -0
  72. package/lib/commonjs/store/transcriptPersistence.js +208 -0
  73. package/lib/commonjs/store/transcriptPersistence.js.map +1 -0
  74. package/lib/commonjs/store/transcriptPersistence.test.js +185 -0
  75. package/lib/commonjs/store/transcriptPersistence.test.js.map +1 -0
  76. package/lib/commonjs/store/useAskBuoy.js +400 -1
  77. package/lib/commonjs/store/useAskBuoy.js.map +1 -0
  78. package/lib/commonjs/store/useAskBuoySettings.js +14 -0
  79. package/lib/commonjs/store/useAskBuoySettings.js.map +1 -0
  80. package/lib/commonjs/sync/askBuoySyncAdapter.js +119 -1
  81. package/lib/commonjs/sync/askBuoySyncAdapter.js.map +1 -0
  82. package/lib/commonjs/sync/askBuoySyncAdapter.test.js +141 -1
  83. package/lib/commonjs/sync/askBuoySyncAdapter.test.js.map +1 -0
  84. package/lib/commonjs/sync/wire.js +58 -1
  85. package/lib/commonjs/sync/wire.js.map +1 -0
  86. package/lib/commonjs/types.js +6 -1
  87. package/lib/commonjs/types.js.map +1 -0
  88. package/lib/module/blocks/AskBlocks.js +331 -1
  89. package/lib/module/blocks/AskBlocks.js.map +1 -0
  90. package/lib/module/blocks/BlockRenderer.js +245 -1
  91. package/lib/module/blocks/BlockRenderer.js.map +1 -0
  92. package/lib/module/blocks/ChromePrototypes.js +503 -1
  93. package/lib/module/blocks/ChromePrototypes.js.map +1 -0
  94. package/lib/module/blocks/DataBlocks.js +674 -1
  95. package/lib/module/blocks/DataBlocks.js.map +1 -0
  96. package/lib/module/blocks/ExtraBlocks.js +1827 -1
  97. package/lib/module/blocks/ExtraBlocks.js.map +1 -0
  98. package/lib/module/blocks/MediaBlocks.js +135 -1
  99. package/lib/module/blocks/MediaBlocks.js.map +1 -0
  100. package/lib/module/blocks/ReceiptBlocks.js +574 -1
  101. package/lib/module/blocks/ReceiptBlocks.js.map +1 -0
  102. package/lib/module/blocks/context.js +35 -1
  103. package/lib/module/blocks/context.js.map +1 -0
  104. package/lib/module/blocks/icons.js +91 -1
  105. package/lib/module/blocks/icons.js.map +1 -0
  106. package/lib/module/blocks/index.js +8 -1
  107. package/lib/module/blocks/index.js.map +1 -0
  108. package/lib/module/blocks/listRow.test.js +56 -0
  109. package/lib/module/blocks/listRow.test.js.map +1 -0
  110. package/lib/module/blocks/pageState.js +30 -0
  111. package/lib/module/blocks/pageState.js.map +1 -0
  112. package/lib/module/blocks/pageState.test.js +56 -0
  113. package/lib/module/blocks/pageState.test.js.map +1 -0
  114. package/lib/module/blocks/primitives.js +389 -1
  115. package/lib/module/blocks/primitives.js.map +1 -0
  116. package/lib/module/blocks/primitivesIndex.js +5 -1
  117. package/lib/module/blocks/primitivesIndex.js.map +1 -0
  118. package/lib/module/components/ApprovalCard.js +135 -1
  119. package/lib/module/components/ApprovalCard.js.map +1 -0
  120. package/lib/module/components/AskBuoyHeader.js +161 -1
  121. package/lib/module/components/AskBuoyHeader.js.map +1 -0
  122. package/lib/module/components/AskBuoyIcon.js +8 -1
  123. package/lib/module/components/AskBuoyIcon.js.map +1 -0
  124. package/lib/module/components/AskBuoyModal.js +348 -1
  125. package/lib/module/components/AskBuoyModal.js.map +1 -0
  126. package/lib/module/components/AskBuoySettings.js +64 -0
  127. package/lib/module/components/AskBuoySettings.js.map +1 -0
  128. package/lib/module/components/ChangesBar.js +206 -1
  129. package/lib/module/components/ChangesBar.js.map +1 -0
  130. package/lib/module/components/Composer.js +170 -1
  131. package/lib/module/components/Composer.js.map +1 -0
  132. package/lib/module/components/EmptyState.js +149 -1
  133. package/lib/module/components/EmptyState.js.map +1 -0
  134. package/lib/module/components/Markdown.js +246 -1
  135. package/lib/module/components/Markdown.js.map +1 -0
  136. package/lib/module/components/MessageList.js +677 -1
  137. package/lib/module/components/MessageList.js.map +1 -0
  138. package/lib/module/components/ThinkingStrip.js +218 -0
  139. package/lib/module/components/ThinkingStrip.js.map +1 -0
  140. package/lib/module/components/TypingDots.js +58 -1
  141. package/lib/module/components/TypingDots.js.map +1 -0
  142. package/lib/module/components/useCopyAction.js +46 -0
  143. package/lib/module/components/useCopyAction.js.map +1 -0
  144. package/lib/module/index.js +34 -1
  145. package/lib/module/index.js.map +1 -0
  146. package/lib/module/preset.js +73 -1
  147. package/lib/module/preset.js.map +1 -0
  148. package/lib/module/store/askBuoySettings.js +62 -0
  149. package/lib/module/store/askBuoySettings.js.map +1 -0
  150. package/lib/module/store/askBuoyStore.js +361 -1
  151. package/lib/module/store/askBuoyStore.js.map +1 -0
  152. package/lib/module/store/restoredIds.test.js +46 -0
  153. package/lib/module/store/restoredIds.test.js.map +1 -0
  154. package/lib/module/store/traceText.js +75 -0
  155. package/lib/module/store/traceText.js.map +1 -0
  156. package/lib/module/store/traceText.test.js +111 -0
  157. package/lib/module/store/traceText.test.js.map +1 -0
  158. package/lib/module/store/transcriptPersistence.js +198 -0
  159. package/lib/module/store/transcriptPersistence.js.map +1 -0
  160. package/lib/module/store/transcriptPersistence.test.js +184 -0
  161. package/lib/module/store/transcriptPersistence.test.js.map +1 -0
  162. package/lib/module/store/useAskBuoy.js +394 -1
  163. package/lib/module/store/useAskBuoy.js.map +1 -0
  164. package/lib/module/store/useAskBuoySettings.js +9 -0
  165. package/lib/module/store/useAskBuoySettings.js.map +1 -0
  166. package/lib/module/sync/askBuoySyncAdapter.js +114 -1
  167. package/lib/module/sync/askBuoySyncAdapter.js.map +1 -0
  168. package/lib/module/sync/askBuoySyncAdapter.test.js +140 -1
  169. package/lib/module/sync/askBuoySyncAdapter.test.js.map +1 -0
  170. package/lib/module/sync/wire.js +47 -1
  171. package/lib/module/sync/wire.js.map +1 -0
  172. package/lib/module/types.js +4 -1
  173. package/lib/module/types.js.map +1 -0
  174. package/lib/typescript/blocks/AskBlocks.d.ts.map +1 -0
  175. package/lib/typescript/blocks/BlockRenderer.d.ts.map +1 -0
  176. package/lib/typescript/blocks/ChromePrototypes.d.ts.map +1 -0
  177. package/lib/typescript/blocks/DataBlocks.d.ts +31 -0
  178. package/lib/typescript/blocks/DataBlocks.d.ts.map +1 -0
  179. package/lib/typescript/blocks/ExtraBlocks.d.ts +11 -0
  180. package/lib/typescript/blocks/ExtraBlocks.d.ts.map +1 -0
  181. package/lib/typescript/blocks/MediaBlocks.d.ts.map +1 -0
  182. package/lib/typescript/blocks/ReceiptBlocks.d.ts.map +1 -0
  183. package/lib/typescript/blocks/context.d.ts.map +1 -0
  184. package/lib/typescript/blocks/icons.d.ts.map +1 -0
  185. package/lib/typescript/blocks/index.d.ts.map +1 -0
  186. package/lib/typescript/blocks/listRow.test.d.ts +2 -0
  187. package/lib/typescript/blocks/listRow.test.d.ts.map +1 -0
  188. package/lib/typescript/blocks/pageState.d.ts +23 -0
  189. package/lib/typescript/blocks/pageState.d.ts.map +1 -0
  190. package/lib/typescript/blocks/pageState.test.d.ts +2 -0
  191. package/lib/typescript/blocks/pageState.test.d.ts.map +1 -0
  192. package/lib/typescript/blocks/primitives.d.ts +39 -9
  193. package/lib/typescript/blocks/primitives.d.ts.map +1 -0
  194. package/lib/typescript/blocks/primitivesIndex.d.ts +2 -1
  195. package/lib/typescript/blocks/primitivesIndex.d.ts.map +1 -0
  196. package/lib/typescript/components/ApprovalCard.d.ts.map +1 -0
  197. package/lib/typescript/components/AskBuoyHeader.d.ts +11 -1
  198. package/lib/typescript/components/AskBuoyHeader.d.ts.map +1 -0
  199. package/lib/typescript/components/AskBuoyIcon.d.ts.map +1 -0
  200. package/lib/typescript/components/AskBuoyModal.d.ts.map +1 -0
  201. package/lib/typescript/components/AskBuoySettings.d.ts +2 -0
  202. package/lib/typescript/components/AskBuoySettings.d.ts.map +1 -0
  203. package/lib/typescript/components/ChangesBar.d.ts.map +1 -0
  204. package/lib/typescript/components/Composer.d.ts.map +1 -0
  205. package/lib/typescript/components/EmptyState.d.ts.map +1 -0
  206. package/lib/typescript/components/Markdown.d.ts.map +1 -0
  207. package/lib/typescript/components/MessageList.d.ts +12 -5
  208. package/lib/typescript/components/MessageList.d.ts.map +1 -0
  209. package/lib/typescript/components/ThinkingStrip.d.ts +5 -0
  210. package/lib/typescript/components/ThinkingStrip.d.ts.map +1 -0
  211. package/lib/typescript/components/TypingDots.d.ts.map +1 -0
  212. package/lib/typescript/components/useCopyAction.d.ts +5 -0
  213. package/lib/typescript/components/useCopyAction.d.ts.map +1 -0
  214. package/lib/typescript/index.d.ts +5 -0
  215. package/lib/typescript/index.d.ts.map +1 -0
  216. package/lib/typescript/preset.d.ts.map +1 -0
  217. package/lib/typescript/store/askBuoySettings.d.ts +22 -0
  218. package/lib/typescript/store/askBuoySettings.d.ts.map +1 -0
  219. package/lib/typescript/store/askBuoyStore.d.ts +74 -13
  220. package/lib/typescript/store/askBuoyStore.d.ts.map +1 -0
  221. package/lib/typescript/store/restoredIds.test.d.ts +2 -0
  222. package/lib/typescript/store/restoredIds.test.d.ts.map +1 -0
  223. package/lib/typescript/store/traceText.d.ts +33 -0
  224. package/lib/typescript/store/traceText.d.ts.map +1 -0
  225. package/lib/typescript/store/traceText.test.d.ts +2 -0
  226. package/lib/typescript/store/traceText.test.d.ts.map +1 -0
  227. package/lib/typescript/store/transcriptPersistence.d.ts +40 -0
  228. package/lib/typescript/store/transcriptPersistence.d.ts.map +1 -0
  229. package/lib/typescript/store/transcriptPersistence.test.d.ts +2 -0
  230. package/lib/typescript/store/transcriptPersistence.test.d.ts.map +1 -0
  231. package/lib/typescript/store/useAskBuoy.d.ts.map +1 -0
  232. package/lib/typescript/store/useAskBuoySettings.d.ts +3 -0
  233. package/lib/typescript/store/useAskBuoySettings.d.ts.map +1 -0
  234. package/lib/typescript/sync/askBuoySyncAdapter.d.ts.map +1 -0
  235. package/lib/typescript/sync/askBuoySyncAdapter.test.d.ts.map +1 -0
  236. package/lib/typescript/sync/wire.d.ts.map +1 -0
  237. package/lib/typescript/types.d.ts +24 -1
  238. package/lib/typescript/types.d.ts.map +1 -0
  239. package/package.json +8 -8
@@ -1 +1,348 @@
1
- "use strict";import{useCallback,useEffect,useMemo,useRef,useState}from"react";import{Alert,Animated,KeyboardAvoidingView,Platform,StyleSheet,Text,View}from"react-native";import{isReversible}from"@buoy-gg/agent-core";import{dispatchToolAction,FeatureGate,Info,JsModal,night,useSafeAreaInsets}from"@buoy-gg/shared-ui";import{BlockHandlersProvider}from"../blocks";import{ApprovalCard}from"./ApprovalCard";import{ChangesBar}from"./ChangesBar";import{Composer}from"./Composer";import{AskBuoyHeader}from"./AskBuoyHeader";import{EmptyState}from"./EmptyState";import{MessageList}from"./MessageList";import{askBuoyStore}from"../store/askBuoyStore";import{useAskBuoy}from"../store/useAskBuoy";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export function AskBuoyModal({visible:e,onClose:t,onBack:o,onMinimize:s,persistenceKey:n,config:r}){const{state:a,send:i,stop:l,reset:u,approve:c,retry:d,answer:m,runAction:g,configured:f,toolCount:p}=useAskBuoy(r),[y,h]=useState(!1),b=useSafeAreaInsets({minBottom:16}),k=useCallback(()=>{const e=askBuoyStore.getLedger();e&&(async()=>{const t=await e.revertAll(dispatchToolAction);if(0===t.failed.length)return void askBuoyStore.setNotice(null);const o=t.failed.map(e=>`${e.label} (${e.error})`).join("; ");askBuoyStore.setNotice(`Couldn't undo ${t.failed.length} change${1===t.failed.length?"":"s"} — ${o}`)})()},[]),x=useCallback(()=>h(e=>!e),[]),A=useRef(new Animated.Value(560)).current,S=useRef(!1),B=useCallback(()=>{S.current||(S.current=!0,A.stopAnimation(e=>{const t="number"==typeof e&&e>200?e:560;Animated.timing(A,{toValue:120,duration:220,useNativeDriver:!1}).start(()=>{setTimeout(()=>{Animated.spring(A,{toValue:t,friction:9,useNativeDriver:!1}).start(()=>{S.current=!1})},2500)})}))},[A]),v=useMemo(()=>{const e=a.messages[a.messages.length-1];if(!e||"assistant"!==e.role)return"";const t=e.blocks.filter(e=>"peek"===e.block.kind).length;return t>0?`${e.id}:${t}`:""},[a.messages]),C=useRef("");useEffect(()=>{v&&v!==C.current&&!1!==r?.peek&&B(),C.current=v},[v,B,r]);const j=useCallback(()=>{const e=askBuoyStore.getLedger(),t=e?.list().filter(e=>!e.undoneAt&&isReversible(e.effect)).length??0;0!==t?Alert.alert("Undo changes first?",`Ask Buoy made ${t} change${1===t?"":"s"} that can still be undone. Clearing the conversation loses the only automatic undo for ${1===t?"it":"them"}.`,[{text:"Undo, then clear",onPress:()=>{(async()=>{const e=askBuoyStore.getLedger();e&&await e.revertAll(dispatchToolAction),u()})()}},{text:"Clear anyway",style:"destructive",onPress:u},{text:"Cancel",style:"cancel"}]):u()},[u]),w=useMemo(()=>{const e=a.messages[a.messages.length-1];return e&&"assistant"===e.role&&e.streaming?e.toolCalls.find(e=>"running"===e.status)?.label??null:null},[a.messages]),_=useMemo(()=>({answer:m,runAction:(e,t)=>{if(!e.minimize)return g(e,t);s?.({mode:"bottomSheet"})},answered:a.answers,actionState:a.actionState,busy:a.busy,supports:{openTool:!1,minimize:!!s,dispatch:!0}}),[m,g,s,a.answers,a.actionState,a.busy]),M=a.messages[a.messages.length-1],T=!a.busy&&"assistant"===M?.role&&!!M.error,P=_jsx(AskBuoyHeader,{configured:f,busy:a.busy,failed:T,activeLabel:w,toolCount:p,hasMessages:a.messages.length>0,onBack:o,onReset:j});return _jsx(JsModal,{visible:e,onClose:t,disableScrollWrapper:!0,background:!1,initialHeight:560,animatedHeight:A,header:{customContent:P,showToggleButton:!1},onBack:o,onMinimize:s,persistenceKey:n??"buoy-ask-buoy",enablePersistence:!0,children:_jsx(BlockHandlersProvider,{value:_,children:_jsxs(View,{style:[styles.root,{paddingBottom:b.bottom}],children:[_jsx(ChangesBar,{ledger:askBuoyStore.getLedger(),onUndoAll:k,expanded:y,onToggle:x}),a.notice&&_jsxs(View,{style:styles.notice,testID:"buoy-ask-buoy-notice",children:[_jsx(Info,{size:14,color:night.color.info}),_jsx(Text,{style:styles.noticeText,children:a.notice})]}),_jsx(KeyboardAvoidingView,{style:styles.flex,behavior:"ios"===Platform.OS?"padding":void 0,enabled:"ios"===Platform.OS,keyboardVerticalOffset:b.bottom,children:_jsxs(FeatureGate,{featureName:"Ask Buoy",children:[_jsx(MessageList,{messages:a.messages,onRetry:d,ListEmptyComponent:_jsx(EmptyState,{configured:f,onPick:i})}),a.pending&&_jsx(ApprovalCard,{pending:a.pending,onAnswer:c}),_jsx(Composer,{onSend:i,onStop:l,busy:a.busy,disabled:!f,placeholder:a.queued?"Queued — sends when this turn finishes":a.awaitingBlockId?"Pick an option above, or type…":void 0})]})})]})})})}const styles=StyleSheet.create({root:{flex:1,backgroundColor:"transparent"},flex:{flex:1},notice:{flexDirection:"row",alignItems:"flex-start",gap:8,paddingHorizontal:night.gutter,paddingVertical:10,backgroundColor:night.color.infoSoft},noticeText:{flex:1,color:night.color.text,fontSize:night.font.caption,lineHeight:18}});
1
+ "use strict";
2
+
3
+ /**
4
+ * Ask Buoy — the sheet.
5
+ *
6
+ * Manual JsModal chrome rather than the declarative `InstalledApp.modal` path,
7
+ * because `ToolModalShell` forwards neither `footer`/`footerHeight` nor
8
+ * `initialHeight`, and a conversation in a 400pt sheet with no sticky composer
9
+ * is not usable.
10
+ *
11
+ * The layout rules here are all learned ones, each noted at its line: one
12
+ * scroller owned by the message list, no animated background competing with
13
+ * streaming text, transparent containers so the sheet's own chrome shows, and
14
+ * an iOS-only keyboard offset.
15
+ *
16
+ * Top to bottom: header (title, live status, new-conversation) · changes bar
17
+ * (only once something has been changed) · transcript · approval card (only
18
+ * with `requireApproval`) · composer. Nothing else. The old "New conversation"
19
+ * text link under the composer is gone — it is the header's + button now.
20
+ */
21
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
22
+ import { Alert, Animated, KeyboardAvoidingView, Platform, StyleSheet, Text, View } from "react-native";
23
+ import { isReversible } from "@buoy-gg/agent-core";
24
+ import { dispatchToolAction, FeatureGate, Info, JsModal, ModalHeader, night, useSafeAreaInsets } from "@buoy-gg/shared-ui";
25
+ import { BlockHandlersProvider } from "../blocks";
26
+ import { ApprovalCard } from "./ApprovalCard";
27
+ import { ChangesBar } from "./ChangesBar";
28
+ import { Composer } from "./Composer";
29
+ import { AskBuoyHeader } from "./AskBuoyHeader";
30
+ import { AskBuoySettings } from "./AskBuoySettings";
31
+ import { EmptyState } from "./EmptyState";
32
+ import { MessageList, transcriptToText } from "./MessageList";
33
+ import { askBuoyStore } from "../store/askBuoyStore";
34
+ import { useAskBuoy } from "../store/useAskBuoy";
35
+ import { useAskBuoySettings } from "../store/useAskBuoySettings";
36
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
37
+ export function AskBuoyModal({
38
+ visible,
39
+ onClose,
40
+ onBack,
41
+ onMinimize,
42
+ persistenceKey,
43
+ config
44
+ }) {
45
+ const {
46
+ state,
47
+ send,
48
+ stop,
49
+ reset,
50
+ approve,
51
+ retry,
52
+ answer,
53
+ runAction,
54
+ configured,
55
+ toolCount
56
+ } = useAskBuoy(config);
57
+ const [changesOpen, setChangesOpen] = useState(false);
58
+ // A hardcoded device map, not the native library — an unmapped phone
59
+ // silently returns bottom: 0, which is how footers ended up sitting on the
60
+ // home indicator.
61
+ const insets = useSafeAreaInsets({
62
+ minBottom: 16
63
+ });
64
+
65
+ /**
66
+ * `dispatchToolAction` is imported STATICALLY at the top of this file, not
67
+ * with `import()`. A dynamic import here resolves through Metro's
68
+ * async-require path, which in a lazy dev bundle rejects with "Expected
69
+ * HMRClient.setup() call at startup" — and because the promise was voided,
70
+ * Undo did nothing at all while the bar went on claiming the changes were
71
+ * undoable. shared-ui is already a static dependency of this component.
72
+ *
73
+ * A failed revert is SHOWN. `revertAll` reports what it could not put back,
74
+ * and swallowing that is the same failure in a quieter form: the whole
75
+ * reason mutations may auto-run is that undo is real.
76
+ */
77
+ const undoAll = useCallback(() => {
78
+ const ledger = askBuoyStore.getLedger();
79
+ if (!ledger) return;
80
+ void (async () => {
81
+ const outcome = await ledger.revertAll(dispatchToolAction);
82
+ if (outcome.failed.length === 0) {
83
+ askBuoyStore.setNotice(null);
84
+ return;
85
+ }
86
+ const detail = outcome.failed.map(f => `${f.label} (${f.error})`).join("; ");
87
+ askBuoyStore.setNotice(`Couldn't undo ${outcome.failed.length} change${outcome.failed.length === 1 ? "" : "s"} — ${detail}`);
88
+ })();
89
+ }, []);
90
+ const toggleChanges = useCallback(() => setChangesOpen(v => !v), []);
91
+
92
+ /**
93
+ * PEEK. When the agent navigates or taps, the sheet drops to a 120pt strip
94
+ * for ~2.5s so the user watches the app do it, then springs back to the
95
+ * height it had (including a user's drag-resize — the value is read live,
96
+ * never assumed). Rides JsModal's external `animatedHeight` seam, so the
97
+ * modal's own drag-resize keeps working on the same value.
98
+ */
99
+ const sheetHeight = useRef(new Animated.Value(560)).current;
100
+ const peeking = useRef(false);
101
+ const runPeek = useCallback(() => {
102
+ if (peeking.current) return;
103
+ peeking.current = true;
104
+ sheetHeight.stopAnimation(from => {
105
+ const restoreTo = typeof from === "number" && from > 200 ? from : 560;
106
+ Animated.timing(sheetHeight, {
107
+ toValue: 120,
108
+ duration: 220,
109
+ useNativeDriver: false
110
+ }).start(() => {
111
+ setTimeout(() => {
112
+ Animated.spring(sheetHeight, {
113
+ toValue: restoreTo,
114
+ friction: 9,
115
+ useNativeDriver: false
116
+ }).start(() => {
117
+ peeking.current = false;
118
+ });
119
+ }, 2500);
120
+ });
121
+ });
122
+ }, [sheetHeight]);
123
+
124
+ // A new `peek` receipt (navigate, tap) triggers the shrink. Keyed by
125
+ // message id + count so a fresh assistant message restarts the count.
126
+ const peekKey = useMemo(() => {
127
+ const last = state.messages[state.messages.length - 1];
128
+ if (!last || last.role !== "assistant") return "";
129
+ const peeks = last.blocks.filter(p => p.block.kind === "peek").length;
130
+ return peeks > 0 ? `${last.id}:${peeks}` : "";
131
+ }, [state.messages]);
132
+ const prevPeekKey = useRef("");
133
+ useEffect(() => {
134
+ if (peekKey && peekKey !== prevPeekKey.current && config?.peek !== false) runPeek();
135
+ prevPeekKey.current = peekKey;
136
+ }, [peekKey, runPeek, config]);
137
+
138
+ /**
139
+ * New conversation, guarded. Clearing the session clears the ledger — the
140
+ * ONLY undo surface — while the agent's changes stay live in the app, so
141
+ * with reversible changes outstanding the user chooses their fate first.
142
+ */
143
+ const confirmReset = useCallback(() => {
144
+ const ledger = askBuoyStore.getLedger();
145
+ const reversible = ledger?.list().filter(e => !e.undoneAt && isReversible(e.effect)).length ?? 0;
146
+ if (reversible === 0) {
147
+ reset();
148
+ return;
149
+ }
150
+ Alert.alert("Undo changes first?", `Ask Buoy made ${reversible} change${reversible === 1 ? "" : "s"} that can still be undone. Clearing the conversation loses the only automatic undo for ${reversible === 1 ? "it" : "them"}.`, [{
151
+ text: "Undo, then clear",
152
+ onPress: () => {
153
+ void (async () => {
154
+ const l = askBuoyStore.getLedger();
155
+ if (l) await l.revertAll(dispatchToolAction);
156
+ reset();
157
+ })();
158
+ }
159
+ }, {
160
+ text: "Clear anyway",
161
+ style: "destructive",
162
+ onPress: reset
163
+ }, {
164
+ text: "Cancel",
165
+ style: "cancel"
166
+ }]);
167
+ }, [reset]);
168
+
169
+ // The header's live status: the title of whichever tool call is in flight.
170
+ const activeLabel = useMemo(() => {
171
+ const last = state.messages[state.messages.length - 1];
172
+ if (!last || last.role !== "assistant" || !last.streaming) return null;
173
+ return last.toolCalls.find(c => c.status === "running")?.label ?? null;
174
+ }, [state.messages]);
175
+
176
+ /**
177
+ * What a block can do in THIS host. `minimize` collapses the sheet to the
178
+ * rail so the user can look at the app (the peek chip). `openTool` has no
179
+ * seam yet, so those buttons don't render here rather than render dead.
180
+ */
181
+ const blockHandlers = useMemo(() => ({
182
+ answer,
183
+ runAction: (action, blockId) => {
184
+ if (action.minimize) {
185
+ onMinimize?.({
186
+ mode: "bottomSheet"
187
+ });
188
+ return;
189
+ }
190
+ return runAction(action, blockId);
191
+ },
192
+ answered: state.answers,
193
+ actionState: state.actionState,
194
+ busy: state.busy,
195
+ supports: {
196
+ openTool: false,
197
+ minimize: !!onMinimize,
198
+ dispatch: true
199
+ }
200
+ }), [answer, runAction, onMinimize, state.answers, state.actionState, state.busy]);
201
+
202
+ // The last assistant turn carrying an error is the only "it went wrong"
203
+ // signal the header can read; it clears as soon as the next send starts.
204
+ const lastMessage = state.messages[state.messages.length - 1];
205
+ const failed = !state.busy && lastMessage?.role === "assistant" && !!lastMessage.error;
206
+
207
+ // Built on press, not on render — a streaming answer would otherwise rebuild
208
+ // the whole transcript on every frame for a button nobody tapped.
209
+ const {
210
+ showThinking
211
+ } = useAskBuoySettings();
212
+ const getTranscript = useCallback(() => transcriptToText(state.messages, showThinking), [state.messages, showThinking]);
213
+
214
+ /**
215
+ * Settings replaces the transcript in place rather than opening over it. The
216
+ * sheet's own back arrow is the way out, and the conversation is untouched
217
+ * underneath — a toggle you flip here should be visible the moment you go
218
+ * back, not after dismissing something.
219
+ */
220
+ const [showSettings, setShowSettings] = useState(false);
221
+ const closeSettings = useCallback(() => setShowSettings(false), []);
222
+ const openSettings = useCallback(() => setShowSettings(true), []);
223
+ const header = showSettings ? /*#__PURE__*/_jsxs(ModalHeader, {
224
+ children: [/*#__PURE__*/_jsx(ModalHeader.Navigation, {
225
+ onBack: closeSettings
226
+ }), /*#__PURE__*/_jsx(ModalHeader.Content, {
227
+ title: "Settings",
228
+ subtitle: "Ask Buoy",
229
+ testID: "buoy-ask-buoy-settings-title"
230
+ })]
231
+ }) : /*#__PURE__*/_jsx(AskBuoyHeader, {
232
+ configured: configured,
233
+ busy: state.busy,
234
+ failed: failed,
235
+ activeLabel: activeLabel,
236
+ toolCount: toolCount,
237
+ hasMessages: state.messages.length > 0,
238
+ onBack: onBack,
239
+ onReset: confirmReset,
240
+ getTranscript: getTranscript,
241
+ onOpenSettings: openSettings
242
+ });
243
+ return /*#__PURE__*/_jsx(JsModal, {
244
+ visible: visible,
245
+ onClose: onClose
246
+ // The message list is the only scroller. JsModal's default wrapper is
247
+ // flexGrow:1, which makes a nested flex:1 scroller resolve against the
248
+ // content and never scroll at all.
249
+ ,
250
+ disableScrollWrapper: true
251
+ // ToolBackground is an animated star field. A chat re-renders on every
252
+ // streamed token; two continuous animations competing is a dropped
253
+ // frame budget for no benefit.
254
+ ,
255
+ background: false,
256
+ initialHeight: 560,
257
+ animatedHeight: sheetHeight,
258
+ header: {
259
+ customContent: header,
260
+ showToggleButton: false
261
+ },
262
+ onBack: onBack,
263
+ onMinimize: onMinimize,
264
+ persistenceKey: persistenceKey ?? "buoy-ask-buoy",
265
+ enablePersistence: true,
266
+ children: /*#__PURE__*/_jsx(BlockHandlersProvider, {
267
+ value: blockHandlers,
268
+ children: /*#__PURE__*/_jsxs(View, {
269
+ style: [styles.root, {
270
+ paddingBottom: insets.bottom
271
+ }],
272
+ children: [/*#__PURE__*/_jsx(ChangesBar, {
273
+ ledger: askBuoyStore.getLedger(),
274
+ onUndoAll: undoAll,
275
+ expanded: changesOpen,
276
+ onToggle: toggleChanges
277
+ }), state.notice && /*#__PURE__*/_jsxs(View, {
278
+ style: styles.notice,
279
+ testID: "buoy-ask-buoy-notice",
280
+ children: [/*#__PURE__*/_jsx(Info, {
281
+ size: 14,
282
+ color: night.color.info
283
+ }), /*#__PURE__*/_jsx(Text, {
284
+ style: styles.noticeText,
285
+ children: state.notice
286
+ })]
287
+ }), /*#__PURE__*/_jsx(KeyboardAvoidingView, {
288
+ style: styles.flex
289
+ // iOS only: Android's default softwareKeyboardLayoutMode is "resize",
290
+ // so the window shrinks and a bottom-anchored view rides up already.
291
+ // Padding on both would lift the composer twice.
292
+ ,
293
+ behavior: Platform.OS === "ios" ? "padding" : undefined,
294
+ enabled: Platform.OS === "ios",
295
+ keyboardVerticalOffset: insets.bottom,
296
+ children: /*#__PURE__*/_jsx(FeatureGate, {
297
+ featureName: "Ask Buoy",
298
+ children: showSettings ? /*#__PURE__*/_jsx(AskBuoySettings, {}) : /*#__PURE__*/_jsxs(_Fragment, {
299
+ children: [/*#__PURE__*/_jsx(MessageList, {
300
+ messages: state.messages,
301
+ onRetry: retry,
302
+ ListEmptyComponent: /*#__PURE__*/_jsx(EmptyState, {
303
+ configured: configured,
304
+ onPick: send
305
+ })
306
+ }), state.pending && /*#__PURE__*/_jsx(ApprovalCard, {
307
+ pending: state.pending,
308
+ onAnswer: approve
309
+ }), /*#__PURE__*/_jsx(Composer, {
310
+ onSend: send,
311
+ onStop: stop,
312
+ busy: state.busy,
313
+ disabled: !configured,
314
+ placeholder: state.queued ? "Queued — sends when this turn finishes" : state.awaitingBlockId ? "Pick an option above, or type…" : undefined
315
+ })]
316
+ })
317
+ })
318
+ })]
319
+ })
320
+ })
321
+ });
322
+ }
323
+ const styles = StyleSheet.create({
324
+ // Transparent or it paints over the sheet's own chrome — the convention is
325
+ // repeated verbatim across every Buoy tool body.
326
+ root: {
327
+ flex: 1,
328
+ backgroundColor: "transparent"
329
+ },
330
+ flex: {
331
+ flex: 1
332
+ },
333
+ notice: {
334
+ flexDirection: "row",
335
+ alignItems: "flex-start",
336
+ gap: 8,
337
+ paddingHorizontal: night.gutter,
338
+ paddingVertical: 10,
339
+ backgroundColor: night.color.infoSoft
340
+ },
341
+ noticeText: {
342
+ flex: 1,
343
+ color: night.color.text,
344
+ fontSize: night.font.caption,
345
+ lineHeight: 18
346
+ }
347
+ });
348
+ //# sourceMappingURL=AskBuoyModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","Alert","Animated","KeyboardAvoidingView","Platform","StyleSheet","Text","View","isReversible","dispatchToolAction","FeatureGate","Info","JsModal","ModalHeader","night","useSafeAreaInsets","BlockHandlersProvider","ApprovalCard","ChangesBar","Composer","AskBuoyHeader","AskBuoySettings","EmptyState","MessageList","transcriptToText","askBuoyStore","useAskBuoy","useAskBuoySettings","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","AskBuoyModal","visible","onClose","onBack","onMinimize","persistenceKey","config","state","send","stop","reset","approve","retry","answer","runAction","configured","toolCount","changesOpen","setChangesOpen","insets","minBottom","undoAll","ledger","getLedger","outcome","revertAll","failed","length","setNotice","detail","map","f","label","error","join","toggleChanges","v","sheetHeight","Value","current","peeking","runPeek","stopAnimation","from","restoreTo","timing","toValue","duration","useNativeDriver","start","setTimeout","spring","friction","peekKey","last","messages","role","peeks","blocks","filter","p","block","kind","id","prevPeekKey","peek","confirmReset","reversible","list","e","undoneAt","effect","alert","text","onPress","l","style","activeLabel","streaming","toolCalls","find","c","status","blockHandlers","action","blockId","minimize","mode","answered","answers","actionState","busy","supports","openTool","dispatch","lastMessage","showThinking","getTranscript","showSettings","setShowSettings","closeSettings","openSettings","header","children","Navigation","Content","title","subtitle","testID","hasMessages","onReset","onOpenSettings","disableScrollWrapper","background","initialHeight","animatedHeight","customContent","showToggleButton","enablePersistence","value","styles","root","paddingBottom","bottom","onUndoAll","expanded","onToggle","notice","size","color","info","noticeText","flex","behavior","OS","undefined","enabled","keyboardVerticalOffset","featureName","onRetry","ListEmptyComponent","onPick","pending","onAnswer","onSend","onStop","disabled","placeholder","queued","awaitingBlockId","create","backgroundColor","flexDirection","alignItems","gap","paddingHorizontal","gutter","paddingVertical","infoSoft","fontSize","font","caption","lineHeight"],"sourceRoot":"../../../src","sources":["components/AskBuoyModal.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The sheet's settings, reached from the header.
5
+ *
6
+ * A view inside the sheet rather than a second modal: a settings panel that
7
+ * covers the conversation you are configuring makes the effect of a toggle
8
+ * invisible until you dismiss it. Back returns to the chat with the
9
+ * transcript exactly where it was.
10
+ *
11
+ * Sections are by subject, not by implementation. "Chat" is what a tester
12
+ * calls the thing they are looking at.
13
+ */
14
+ import { ScrollView, StyleSheet, Text } from "react-native";
15
+ import { night, ToggleRow } from "@buoy-gg/shared-ui";
16
+ import { useAskBuoySettings } from "../store/useAskBuoySettings";
17
+ import { askBuoySettings } from "../store/askBuoySettings";
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ export function AskBuoySettings() {
20
+ const settings = useAskBuoySettings();
21
+ return /*#__PURE__*/_jsxs(ScrollView, {
22
+ style: styles.scroll,
23
+ contentContainerStyle: styles.content,
24
+ testID: "buoy-ask-buoy-settings",
25
+ children: [/*#__PURE__*/_jsx(Text, {
26
+ style: styles.section,
27
+ children: "CHAT"
28
+ }), /*#__PURE__*/_jsx(ToggleRow, {
29
+ testID: "buoy-ask-buoy-setting-thinking",
30
+ label: "Show agent thinking",
31
+ description: "Adds a collapsed strip under each answer: the model's reasoning, and every step it ran with its parameters, result, duration and token cost. Copy includes the steps and reasoning while this is on, so you can read the run outside the app.",
32
+ value: settings.showThinking,
33
+ onValueChange: next => askBuoySettings.set("showThinking", next)
34
+ }), /*#__PURE__*/_jsx(Text, {
35
+ style: styles.note,
36
+ children: "Not every model reports reasoning. Claude thinks by default; most OpenAI models return none, and the strip then shows the steps alone."
37
+ })]
38
+ });
39
+ }
40
+ const styles = StyleSheet.create({
41
+ scroll: {
42
+ flex: 1
43
+ },
44
+ content: {
45
+ padding: night.gutter,
46
+ gap: 10,
47
+ paddingBottom: 32
48
+ },
49
+ section: {
50
+ color: night.color.textTertiary,
51
+ fontSize: 10,
52
+ fontWeight: "700",
53
+ letterSpacing: 0.6,
54
+ paddingHorizontal: 4,
55
+ paddingTop: 4
56
+ },
57
+ note: {
58
+ color: night.color.textTertiary,
59
+ fontSize: night.font.micro,
60
+ lineHeight: 16,
61
+ paddingHorizontal: 4
62
+ }
63
+ });
64
+ //# sourceMappingURL=AskBuoySettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["ScrollView","StyleSheet","Text","night","ToggleRow","useAskBuoySettings","askBuoySettings","jsx","_jsx","jsxs","_jsxs","AskBuoySettings","settings","style","styles","scroll","contentContainerStyle","content","testID","children","section","label","description","value","showThinking","onValueChange","next","set","note","create","flex","padding","gutter","gap","paddingBottom","color","textTertiary","fontSize","fontWeight","letterSpacing","paddingHorizontal","paddingTop","font","micro","lineHeight"],"sourceRoot":"../../../src","sources":["components/AskBuoySettings.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,UAAU,EAAEC,UAAU,EAAEC,IAAI,QAAc,cAAc;AACjE,SAASC,KAAK,EAAEC,SAAS,QAAQ,oBAAoB;AAErD,SAASC,kBAAkB,QAAQ,6BAA6B;AAChE,SAASC,eAAe,QAAQ,0BAA0B;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAE3D,OAAO,SAASC,eAAeA,CAAA,EAAG;EAChC,MAAMC,QAAQ,GAAGP,kBAAkB,CAAC,CAAC;EACrC,oBACEK,KAAA,CAACV,UAAU;IACTa,KAAK,EAAEC,MAAM,CAACC,MAAO;IACrBC,qBAAqB,EAAEF,MAAM,CAACG,OAAQ;IACtCC,MAAM,EAAC,wBAAwB;IAAAC,QAAA,gBAE/BX,IAAA,CAACN,IAAI;MAACW,KAAK,EAAEC,MAAM,CAACM,OAAQ;MAAAD,QAAA,EAAC;IAAI,CAAM,CAAC,eACxCX,IAAA,CAACJ,SAAS;MACRc,MAAM,EAAC,gCAAgC;MACvCG,KAAK,EAAC,qBAAqB;MAC3BC,WAAW,EAAC,+OAA+O;MAC3PC,KAAK,EAAEX,QAAQ,CAACY,YAAa;MAC7BC,aAAa,EAAGC,IAAI,IAAKpB,eAAe,CAACqB,GAAG,CAAC,cAAc,EAAED,IAAI;IAAE,CACpE,CAAC,eACFlB,IAAA,CAACN,IAAI;MAACW,KAAK,EAAEC,MAAM,CAACc,IAAK;MAAAT,QAAA,EAAC;IAG1B,CAAM,CAAC;EAAA,CACG,CAAC;AAEjB;AAEA,MAAML,MAAM,GAAGb,UAAU,CAAC4B,MAAM,CAAC;EAC/Bd,MAAM,EAAE;IAAEe,IAAI,EAAE;EAAE,CAAC;EACnBb,OAAO,EAAE;IAAEc,OAAO,EAAE5B,KAAK,CAAC6B,MAAM;IAAEC,GAAG,EAAE,EAAE;IAAEC,aAAa,EAAE;EAAG,CAAC;EAC9Dd,OAAO,EAAE;IACPe,KAAK,EAAEhC,KAAK,CAACgC,KAAK,CAACC,YAAY;IAC/BC,QAAQ,EAAE,EAAE;IACZC,UAAU,EAAE,KAAK;IACjBC,aAAa,EAAE,GAAG;IAClBC,iBAAiB,EAAE,CAAC;IACpBC,UAAU,EAAE;EACd,CAAC;EACDb,IAAI,EAAE;IACJO,KAAK,EAAEhC,KAAK,CAACgC,KAAK,CAACC,YAAY;IAC/BC,QAAQ,EAAElC,KAAK,CAACuC,IAAI,CAACC,KAAK;IAC1BC,UAAU,EAAE,EAAE;IACdJ,iBAAiB,EAAE;EACrB;AACF,CAAC,CAAC","ignoreList":[]}
@@ -1 +1,206 @@
1
- "use strict";import{useSyncExternalStore}from"react";import{Pressable,ScrollView,StyleSheet,Text,View}from"react-native";import{ChevronDown,ChevronRight,night}from"@buoy-gg/shared-ui";import{isReversible}from"@buoy-gg/agent-core";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const EMPTY=[];function useLedgerEntries(e){return useSyncExternalStore(t=>e?.subscribe(t)??(()=>{}),()=>e?.list()??EMPTY,()=>e?.list()??EMPTY)}export function ChangesBar({ledger:e,onUndoAll:t,expanded:o,onToggle:n}){const r=useLedgerEntries(e).filter(e=>!e.undoneAt),s=r.filter(e=>"transient"!==e.effect.kind);if(0===s.length)return null;const l=s.filter(e=>isReversible(e.effect)),i=s.length-l.length,a=r.length-s.length,c=o?ChevronDown:ChevronRight,d=[l.length>0?`${l.length} undoable`:null,i>0?`${i} permanent`:null].filter(Boolean).join(" · ");return _jsxs(View,{style:styles.wrap,children:[_jsxs(Pressable,{testID:"buoy-ask-buoy-changes-bar",accessibilityRole:"button",accessibilityState:{expanded:o},onPress:n,style:styles.bar,children:[_jsx(View,{style:styles.dot}),_jsx(Text,{style:styles.summary,numberOfLines:1,children:"Changed this app"}),_jsx(Text,{style:styles.counts,numberOfLines:1,children:d}),_jsx(c,{size:12,color:night.color.textSecondary})]}),o&&_jsxs(View,{style:styles.panel,children:[_jsxs(ScrollView,{style:styles.panelScroll,testID:"buoy-ask-buoy-changes-scroll",keyboardShouldPersistTaps:"handled",children:[s.map(e=>{const t=!isReversible(e.effect);return _jsxs(View,{style:styles.row,children:[_jsx(Text,{style:styles.rowLabel,children:e.effect.label}),_jsx(Text,{style:[styles.rowTag,t&&styles.rowTagMuted],children:t?"Permanent":"Undoable"})]},e.id)}),a>0&&_jsx(View,{style:styles.row,children:_jsxs(Text,{style:[styles.rowLabel,styles.rowLabelMuted],children:["Also did ",a," one-shot action",1===a?"":"s"," (navigation, taps) — nothing to undo."]})})]}),_jsxs(View,{style:styles.footer,children:[l.length>0&&_jsx(Pressable,{testID:"buoy-ask-buoy-undo-all",accessibilityRole:"button",onPress:t,style:({pressed:e})=>[styles.undo,e&&styles.pressed],children:_jsxs(Text,{style:styles.undoText,children:["Undo ",l.length," change",1===l.length?"":"s"]})}),i>0&&_jsx(Text,{style:styles.footnote,children:"Permanent changes can't be undone from here."})]})]})]})}const styles=StyleSheet.create({wrap:{borderBottomWidth:StyleSheet.hairlineWidth,borderBottomColor:night.color.border,backgroundColor:night.color.warningSoft},bar:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:night.gutter,paddingVertical:10},dot:{width:7,height:7,borderRadius:4,backgroundColor:night.color.warning},summary:{color:night.color.text,fontSize:night.font.caption,fontWeight:"600"},counts:{flex:1,color:night.color.textSecondary,fontSize:night.font.caption},panel:{paddingHorizontal:night.gutter,paddingBottom:12,gap:10},panelScroll:{maxHeight:180},row:{flexDirection:"row",alignItems:"flex-start",gap:10,paddingVertical:8,borderTopWidth:StyleSheet.hairlineWidth,borderTopColor:night.color.separator},rowLabel:{flex:1,color:night.color.text,fontSize:night.font.caption,lineHeight:18},rowTag:{color:night.color.accent,fontSize:night.font.micro,fontWeight:"600",letterSpacing:.6,textTransform:"uppercase",paddingTop:2},rowTagMuted:{color:night.color.textTertiary},rowLabelMuted:{color:night.color.textTertiary},footer:{flexDirection:"row",alignItems:"center",gap:12,flexWrap:"wrap"},undo:{paddingHorizontal:14,paddingVertical:8,borderRadius:night.radius.row,backgroundColor:night.color.button},undoText:{color:night.color.accent,fontSize:night.font.caption,fontWeight:"600"},footnote:{flex:1,color:night.color.textTertiary,fontSize:night.font.micro},pressed:{opacity:.7}});
1
+ "use strict";
2
+
3
+ /**
4
+ * "The agent changed things" — the bar, and the list behind it.
5
+ *
6
+ * Ask Buoy mutates without asking, so this is what keeps the user in control:
7
+ * if reality has been bent, you can never not know it. Same principle as the
8
+ * impersonate and override banners.
9
+ *
10
+ * It counts REVERSIBLE and ONE-SHOT effects separately, which is the one place
11
+ * this deliberately differs from the Scenarios banner. That one folds
12
+ * transients into a single "N changes" total and then silently no-ops on them
13
+ * at revert — a user who taps Undo, sees "4 changes", and finds three of them
14
+ * still in place learns not to trust the bar. Better to say "1 undoable ·
15
+ * 1 permanent" and be believed.
16
+ */
17
+ import { useSyncExternalStore } from "react";
18
+ import { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
19
+ import { ChevronDown, ChevronRight, night } from "@buoy-gg/shared-ui";
20
+ import { isReversible } from "@buoy-gg/agent-core";
21
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
+ const EMPTY = [];
23
+ function useLedgerEntries(ledger) {
24
+ return useSyncExternalStore(fn => ledger?.subscribe(fn) ?? (() => {}), () => ledger?.list() ?? EMPTY, () => ledger?.list() ?? EMPTY);
25
+ }
26
+ export function ChangesBar({
27
+ ledger,
28
+ onUndoAll,
29
+ expanded,
30
+ onToggle
31
+ }) {
32
+ const entries = useLedgerEntries(ledger);
33
+ const outstanding = entries.filter(e => !e.undoneAt);
34
+ // Transients — navigation, taps — are one-shot ACTIONS, not changes. Counting
35
+ // them here read "Changed this app · 9 permanent" after a read-only tour,
36
+ // which is the bar lying in the alarming direction. They still appear in the
37
+ // expanded panel's footnote, because honesty, but they raise no banner.
38
+ const changes = outstanding.filter(e => e.effect.kind !== "transient");
39
+ if (changes.length === 0) return null;
40
+ const reversible = changes.filter(e => isReversible(e.effect));
41
+ const permanent = changes.length - reversible.length;
42
+ const transients = outstanding.length - changes.length;
43
+ const Chevron = expanded ? ChevronDown : ChevronRight;
44
+ const counts = [reversible.length > 0 ? `${reversible.length} undoable` : null, permanent > 0 ? `${permanent} permanent` : null].filter(Boolean).join(" · ");
45
+ return /*#__PURE__*/_jsxs(View, {
46
+ style: styles.wrap,
47
+ children: [/*#__PURE__*/_jsxs(Pressable, {
48
+ testID: "buoy-ask-buoy-changes-bar",
49
+ accessibilityRole: "button",
50
+ accessibilityState: {
51
+ expanded
52
+ },
53
+ onPress: onToggle,
54
+ style: styles.bar,
55
+ children: [/*#__PURE__*/_jsx(View, {
56
+ style: styles.dot
57
+ }), /*#__PURE__*/_jsx(Text, {
58
+ style: styles.summary,
59
+ numberOfLines: 1,
60
+ children: "Changed this app"
61
+ }), /*#__PURE__*/_jsx(Text, {
62
+ style: styles.counts,
63
+ numberOfLines: 1,
64
+ children: counts
65
+ }), /*#__PURE__*/_jsx(Chevron, {
66
+ size: 12,
67
+ color: night.color.textSecondary
68
+ })]
69
+ }), expanded && /*#__PURE__*/_jsxs(View, {
70
+ style: styles.panel,
71
+ children: [/*#__PURE__*/_jsxs(ScrollView, {
72
+ style: styles.panelScroll,
73
+ testID: "buoy-ask-buoy-changes-scroll",
74
+ keyboardShouldPersistTaps: "handled",
75
+ children: [changes.map(entry => {
76
+ const oneOff = !isReversible(entry.effect);
77
+ return /*#__PURE__*/_jsxs(View, {
78
+ style: styles.row,
79
+ children: [/*#__PURE__*/_jsx(Text, {
80
+ style: styles.rowLabel,
81
+ children: entry.effect.label
82
+ }), /*#__PURE__*/_jsx(Text, {
83
+ style: [styles.rowTag, oneOff && styles.rowTagMuted],
84
+ children: oneOff ? "Permanent" : "Undoable"
85
+ })]
86
+ }, entry.id);
87
+ }), transients > 0 && /*#__PURE__*/_jsx(View, {
88
+ style: styles.row,
89
+ children: /*#__PURE__*/_jsxs(Text, {
90
+ style: [styles.rowLabel, styles.rowLabelMuted],
91
+ children: ["Also did ", transients, " one-shot action", transients === 1 ? "" : "s", " (navigation, taps) \u2014 nothing to undo."]
92
+ })
93
+ })]
94
+ }), /*#__PURE__*/_jsxs(View, {
95
+ style: styles.footer,
96
+ children: [reversible.length > 0 && /*#__PURE__*/_jsx(Pressable, {
97
+ testID: "buoy-ask-buoy-undo-all",
98
+ accessibilityRole: "button",
99
+ onPress: onUndoAll,
100
+ style: ({
101
+ pressed
102
+ }) => [styles.undo, pressed && styles.pressed],
103
+ children: /*#__PURE__*/_jsxs(Text, {
104
+ style: styles.undoText,
105
+ children: ["Undo ", reversible.length, " change", reversible.length === 1 ? "" : "s"]
106
+ })
107
+ }), permanent > 0 && /*#__PURE__*/_jsx(Text, {
108
+ style: styles.footnote,
109
+ children: "Permanent changes can't be undone from here."
110
+ })]
111
+ })]
112
+ })]
113
+ });
114
+ }
115
+ const styles = StyleSheet.create({
116
+ wrap: {
117
+ borderBottomWidth: StyleSheet.hairlineWidth,
118
+ borderBottomColor: night.color.border,
119
+ backgroundColor: night.color.warningSoft
120
+ },
121
+ bar: {
122
+ flexDirection: "row",
123
+ alignItems: "center",
124
+ gap: 8,
125
+ paddingHorizontal: night.gutter,
126
+ paddingVertical: 10
127
+ },
128
+ dot: {
129
+ width: 7,
130
+ height: 7,
131
+ borderRadius: 4,
132
+ backgroundColor: night.color.warning
133
+ },
134
+ summary: {
135
+ color: night.color.text,
136
+ fontSize: night.font.caption,
137
+ fontWeight: "600"
138
+ },
139
+ counts: {
140
+ flex: 1,
141
+ color: night.color.textSecondary,
142
+ fontSize: night.font.caption
143
+ },
144
+ panel: {
145
+ paddingHorizontal: night.gutter,
146
+ paddingBottom: 12,
147
+ gap: 10
148
+ },
149
+ panelScroll: {
150
+ maxHeight: 180
151
+ },
152
+ row: {
153
+ flexDirection: "row",
154
+ alignItems: "flex-start",
155
+ gap: 10,
156
+ paddingVertical: 8,
157
+ borderTopWidth: StyleSheet.hairlineWidth,
158
+ borderTopColor: night.color.separator
159
+ },
160
+ rowLabel: {
161
+ flex: 1,
162
+ color: night.color.text,
163
+ fontSize: night.font.caption,
164
+ lineHeight: 18
165
+ },
166
+ rowTag: {
167
+ color: night.color.accent,
168
+ fontSize: night.font.micro,
169
+ fontWeight: "600",
170
+ letterSpacing: 0.6,
171
+ textTransform: "uppercase",
172
+ paddingTop: 2
173
+ },
174
+ rowTagMuted: {
175
+ color: night.color.textTertiary
176
+ },
177
+ rowLabelMuted: {
178
+ color: night.color.textTertiary
179
+ },
180
+ footer: {
181
+ flexDirection: "row",
182
+ alignItems: "center",
183
+ gap: 12,
184
+ flexWrap: "wrap"
185
+ },
186
+ undo: {
187
+ paddingHorizontal: 14,
188
+ paddingVertical: 8,
189
+ borderRadius: night.radius.row,
190
+ backgroundColor: night.color.button
191
+ },
192
+ undoText: {
193
+ color: night.color.accent,
194
+ fontSize: night.font.caption,
195
+ fontWeight: "600"
196
+ },
197
+ footnote: {
198
+ flex: 1,
199
+ color: night.color.textTertiary,
200
+ fontSize: night.font.micro
201
+ },
202
+ pressed: {
203
+ opacity: 0.7
204
+ }
205
+ });
206
+ //# sourceMappingURL=ChangesBar.js.map