@buoy-gg/ask-buoy 7.0.41 → 7.0.43
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.
- package/README.md +13 -98
- package/lib/commonjs/blocks/AskBlocks.js +1 -338
- package/lib/commonjs/blocks/BlockRenderer.js +1 -262
- package/lib/commonjs/blocks/ChromePrototypes.js +1 -514
- package/lib/commonjs/blocks/DataBlocks.js +1 -783
- package/lib/commonjs/blocks/ExtraBlocks.js +1 -1862
- package/lib/commonjs/blocks/MediaBlocks.js +1 -158
- package/lib/commonjs/blocks/ReceiptBlocks.js +2 -592
- package/lib/commonjs/blocks/blockText.js +1 -60
- package/lib/commonjs/blocks/blockText.test.js +1 -53
- package/lib/commonjs/blocks/context.js +1 -42
- package/lib/commonjs/blocks/icons.js +1 -96
- package/lib/commonjs/blocks/index.js +1 -95
- package/lib/commonjs/blocks/listRow.test.js +1 -55
- package/lib/commonjs/blocks/pageState.js +1 -34
- package/lib/commonjs/blocks/pageState.test.js +1 -57
- package/lib/commonjs/blocks/primitives.js +1 -457
- package/lib/commonjs/blocks/primitivesIndex.js +1 -62
- package/lib/commonjs/blocks/ruleStates.js +1 -39
- package/lib/commonjs/components/ApprovalCard.js +1 -297
- package/lib/commonjs/components/AskBuoyHeader.js +1 -196
- package/lib/commonjs/components/AskBuoyIcon.js +1 -19
- package/lib/commonjs/components/AskBuoyModal.js +2 -482
- package/lib/commonjs/components/AskBuoySettings.js +1 -181
- package/lib/commonjs/components/ChangesBar.js +1 -212
- package/lib/commonjs/components/Composer.js +1 -255
- package/lib/commonjs/components/EmptyState.js +1 -161
- package/lib/commonjs/components/KeyboardPad.js +1 -80
- package/lib/commonjs/components/Markdown.js +1 -310
- package/lib/commonjs/components/MessageList.js +1 -970
- package/lib/commonjs/components/QueuedMessages.js +1 -145
- package/lib/commonjs/components/ThinkingStrip.js +1 -223
- package/lib/commonjs/components/TypingDots.js +1 -63
- package/lib/commonjs/components/markdownParse.js +1 -131
- package/lib/commonjs/components/markdownParse.test.js +1 -99
- package/lib/commonjs/components/useCopyAction.js +1 -50
- package/lib/commonjs/index.js +1 -252
- package/lib/commonjs/preset.js +1 -91
- package/lib/commonjs/store/activityGroups.js +1 -110
- package/lib/commonjs/store/activityGroups.test.js +1 -78
- package/lib/commonjs/store/askBuoySettings.js +1 -72
- package/lib/commonjs/store/askBuoyStore.js +2 -588
- package/lib/commonjs/store/blockPlacement.js +1 -64
- package/lib/commonjs/store/blockPlacement.test.js +1 -123
- package/lib/commonjs/store/queue.test.js +1 -150
- package/lib/commonjs/store/resetConversation.js +1 -77
- package/lib/commonjs/store/restorePending.test.js +1 -63
- package/lib/commonjs/store/restoredIds.test.js +1 -47
- package/lib/commonjs/store/suggestions.js +1 -54
- package/lib/commonjs/store/suggestions.test.js +1 -58
- package/lib/commonjs/store/systemLine.test.js +1 -77
- package/lib/commonjs/store/ticketPrompt.js +1 -17
- package/lib/commonjs/store/traceText.js +1 -81
- package/lib/commonjs/store/traceText.test.js +1 -112
- package/lib/commonjs/store/transcriptPersistence.js +1 -297
- package/lib/commonjs/store/transcriptPersistence.test.js +1 -333
- package/lib/commonjs/store/turnRendering.test.js +1 -151
- package/lib/commonjs/store/useAskBuoy.js +1 -651
- package/lib/commonjs/store/useAskBuoySettings.js +1 -14
- package/lib/commonjs/sync/askBuoySyncAdapter.js +1 -153
- package/lib/commonjs/sync/askBuoySyncAdapter.test.js +1 -141
- package/lib/commonjs/sync/wire.js +1 -58
- package/lib/commonjs/types.js +1 -6
- package/lib/module/blocks/AskBlocks.js +1 -331
- package/lib/module/blocks/BlockRenderer.js +1 -257
- package/lib/module/blocks/ChromePrototypes.js +1 -503
- package/lib/module/blocks/DataBlocks.js +1 -769
- package/lib/module/blocks/ExtraBlocks.js +1 -1835
- package/lib/module/blocks/MediaBlocks.js +1 -153
- package/lib/module/blocks/ReceiptBlocks.js +2 -580
- package/lib/module/blocks/blockText.js +1 -55
- package/lib/module/blocks/blockText.test.js +1 -53
- package/lib/module/blocks/context.js +1 -35
- package/lib/module/blocks/icons.js +1 -91
- package/lib/module/blocks/index.js +1 -8
- package/lib/module/blocks/listRow.test.js +1 -56
- package/lib/module/blocks/pageState.js +1 -30
- package/lib/module/blocks/pageState.test.js +1 -56
- package/lib/module/blocks/primitives.js +1 -445
- package/lib/module/blocks/primitivesIndex.js +1 -5
- package/lib/module/blocks/ruleStates.js +1 -35
- package/lib/module/components/ApprovalCard.js +1 -292
- package/lib/module/components/AskBuoyHeader.js +1 -193
- package/lib/module/components/AskBuoyIcon.js +1 -8
- package/lib/module/components/AskBuoyModal.js +2 -477
- package/lib/module/components/AskBuoySettings.js +1 -176
- package/lib/module/components/ChangesBar.js +1 -206
- package/lib/module/components/Composer.js +1 -250
- package/lib/module/components/EmptyState.js +1 -156
- package/lib/module/components/KeyboardPad.js +1 -75
- package/lib/module/components/Markdown.js +1 -305
- package/lib/module/components/MessageList.js +1 -964
- package/lib/module/components/QueuedMessages.js +1 -140
- package/lib/module/components/ThinkingStrip.js +1 -218
- package/lib/module/components/TypingDots.js +1 -58
- package/lib/module/components/markdownParse.js +1 -125
- package/lib/module/components/markdownParse.test.js +1 -98
- package/lib/module/components/useCopyAction.js +1 -46
- package/lib/module/index.js +1 -34
- package/lib/module/preset.js +1 -74
- package/lib/module/store/activityGroups.js +1 -103
- package/lib/module/store/activityGroups.test.js +1 -77
- package/lib/module/store/askBuoySettings.js +1 -67
- package/lib/module/store/askBuoyStore.js +2 -582
- package/lib/module/store/blockPlacement.js +1 -59
- package/lib/module/store/blockPlacement.test.js +1 -122
- package/lib/module/store/queue.test.js +1 -149
- package/lib/module/store/resetConversation.js +1 -72
- package/lib/module/store/restorePending.test.js +1 -62
- package/lib/module/store/restoredIds.test.js +1 -46
- package/lib/module/store/suggestions.js +1 -49
- package/lib/module/store/suggestions.test.js +1 -57
- package/lib/module/store/systemLine.test.js +1 -76
- package/lib/module/store/ticketPrompt.js +1 -13
- package/lib/module/store/traceText.js +1 -75
- package/lib/module/store/traceText.test.js +1 -111
- package/lib/module/store/transcriptPersistence.js +1 -287
- package/lib/module/store/transcriptPersistence.test.js +1 -332
- package/lib/module/store/turnRendering.test.js +1 -150
- package/lib/module/store/useAskBuoy.js +1 -646
- package/lib/module/store/useAskBuoySettings.js +1 -9
- package/lib/module/sync/askBuoySyncAdapter.js +1 -148
- package/lib/module/sync/askBuoySyncAdapter.test.js +1 -140
- package/lib/module/sync/wire.js +1 -47
- package/lib/module/types.js +1 -4
- package/lib/web/index.mjs +11 -12
- package/package.json +8 -12
- package/lib/commonjs/blocks/AskBlocks.js.map +0 -1
- package/lib/commonjs/blocks/BlockRenderer.js.map +0 -1
- package/lib/commonjs/blocks/ChromePrototypes.js.map +0 -1
- package/lib/commonjs/blocks/DataBlocks.js.map +0 -1
- package/lib/commonjs/blocks/ExtraBlocks.js.map +0 -1
- package/lib/commonjs/blocks/MediaBlocks.js.map +0 -1
- package/lib/commonjs/blocks/ReceiptBlocks.js.map +0 -1
- package/lib/commonjs/blocks/blockText.js.map +0 -1
- package/lib/commonjs/blocks/blockText.test.js.map +0 -1
- package/lib/commonjs/blocks/context.js.map +0 -1
- package/lib/commonjs/blocks/icons.js.map +0 -1
- package/lib/commonjs/blocks/index.js.map +0 -1
- package/lib/commonjs/blocks/listRow.test.js.map +0 -1
- package/lib/commonjs/blocks/pageState.js.map +0 -1
- package/lib/commonjs/blocks/pageState.test.js.map +0 -1
- package/lib/commonjs/blocks/primitives.js.map +0 -1
- package/lib/commonjs/blocks/primitivesIndex.js.map +0 -1
- package/lib/commonjs/blocks/ruleStates.js.map +0 -1
- package/lib/commonjs/components/ApprovalCard.js.map +0 -1
- package/lib/commonjs/components/AskBuoyHeader.js.map +0 -1
- package/lib/commonjs/components/AskBuoyIcon.js.map +0 -1
- package/lib/commonjs/components/AskBuoyModal.js.map +0 -1
- package/lib/commonjs/components/AskBuoySettings.js.map +0 -1
- package/lib/commonjs/components/ChangesBar.js.map +0 -1
- package/lib/commonjs/components/Composer.js.map +0 -1
- package/lib/commonjs/components/EmptyState.js.map +0 -1
- package/lib/commonjs/components/KeyboardPad.js.map +0 -1
- package/lib/commonjs/components/Markdown.js.map +0 -1
- package/lib/commonjs/components/MessageList.js.map +0 -1
- package/lib/commonjs/components/QueuedMessages.js.map +0 -1
- package/lib/commonjs/components/ThinkingStrip.js.map +0 -1
- package/lib/commonjs/components/TypingDots.js.map +0 -1
- package/lib/commonjs/components/markdownParse.js.map +0 -1
- package/lib/commonjs/components/markdownParse.test.js.map +0 -1
- package/lib/commonjs/components/useCopyAction.js.map +0 -1
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/preset.js.map +0 -1
- package/lib/commonjs/store/activityGroups.js.map +0 -1
- package/lib/commonjs/store/activityGroups.test.js.map +0 -1
- package/lib/commonjs/store/askBuoySettings.js.map +0 -1
- package/lib/commonjs/store/askBuoyStore.js.map +0 -1
- package/lib/commonjs/store/blockPlacement.js.map +0 -1
- package/lib/commonjs/store/blockPlacement.test.js.map +0 -1
- package/lib/commonjs/store/queue.test.js.map +0 -1
- package/lib/commonjs/store/resetConversation.js.map +0 -1
- package/lib/commonjs/store/restorePending.test.js.map +0 -1
- package/lib/commonjs/store/restoredIds.test.js.map +0 -1
- package/lib/commonjs/store/suggestions.js.map +0 -1
- package/lib/commonjs/store/suggestions.test.js.map +0 -1
- package/lib/commonjs/store/systemLine.test.js.map +0 -1
- package/lib/commonjs/store/ticketPrompt.js.map +0 -1
- package/lib/commonjs/store/traceText.js.map +0 -1
- package/lib/commonjs/store/traceText.test.js.map +0 -1
- package/lib/commonjs/store/transcriptPersistence.js.map +0 -1
- package/lib/commonjs/store/transcriptPersistence.test.js.map +0 -1
- package/lib/commonjs/store/turnRendering.test.js.map +0 -1
- package/lib/commonjs/store/useAskBuoy.js.map +0 -1
- package/lib/commonjs/store/useAskBuoySettings.js.map +0 -1
- package/lib/commonjs/sync/askBuoySyncAdapter.js.map +0 -1
- package/lib/commonjs/sync/askBuoySyncAdapter.test.js.map +0 -1
- package/lib/commonjs/sync/wire.js.map +0 -1
- package/lib/commonjs/types.js.map +0 -1
- package/lib/module/blocks/AskBlocks.js.map +0 -1
- package/lib/module/blocks/BlockRenderer.js.map +0 -1
- package/lib/module/blocks/ChromePrototypes.js.map +0 -1
- package/lib/module/blocks/DataBlocks.js.map +0 -1
- package/lib/module/blocks/ExtraBlocks.js.map +0 -1
- package/lib/module/blocks/MediaBlocks.js.map +0 -1
- package/lib/module/blocks/ReceiptBlocks.js.map +0 -1
- package/lib/module/blocks/blockText.js.map +0 -1
- package/lib/module/blocks/blockText.test.js.map +0 -1
- package/lib/module/blocks/context.js.map +0 -1
- package/lib/module/blocks/icons.js.map +0 -1
- package/lib/module/blocks/index.js.map +0 -1
- package/lib/module/blocks/listRow.test.js.map +0 -1
- package/lib/module/blocks/pageState.js.map +0 -1
- package/lib/module/blocks/pageState.test.js.map +0 -1
- package/lib/module/blocks/primitives.js.map +0 -1
- package/lib/module/blocks/primitivesIndex.js.map +0 -1
- package/lib/module/blocks/ruleStates.js.map +0 -1
- package/lib/module/components/ApprovalCard.js.map +0 -1
- package/lib/module/components/AskBuoyHeader.js.map +0 -1
- package/lib/module/components/AskBuoyIcon.js.map +0 -1
- package/lib/module/components/AskBuoyModal.js.map +0 -1
- package/lib/module/components/AskBuoySettings.js.map +0 -1
- package/lib/module/components/ChangesBar.js.map +0 -1
- package/lib/module/components/Composer.js.map +0 -1
- package/lib/module/components/EmptyState.js.map +0 -1
- package/lib/module/components/KeyboardPad.js.map +0 -1
- package/lib/module/components/Markdown.js.map +0 -1
- package/lib/module/components/MessageList.js.map +0 -1
- package/lib/module/components/QueuedMessages.js.map +0 -1
- package/lib/module/components/ThinkingStrip.js.map +0 -1
- package/lib/module/components/TypingDots.js.map +0 -1
- package/lib/module/components/markdownParse.js.map +0 -1
- package/lib/module/components/markdownParse.test.js.map +0 -1
- package/lib/module/components/useCopyAction.js.map +0 -1
- package/lib/module/index.js.map +0 -1
- package/lib/module/preset.js.map +0 -1
- package/lib/module/store/activityGroups.js.map +0 -1
- package/lib/module/store/activityGroups.test.js.map +0 -1
- package/lib/module/store/askBuoySettings.js.map +0 -1
- package/lib/module/store/askBuoyStore.js.map +0 -1
- package/lib/module/store/blockPlacement.js.map +0 -1
- package/lib/module/store/blockPlacement.test.js.map +0 -1
- package/lib/module/store/queue.test.js.map +0 -1
- package/lib/module/store/resetConversation.js.map +0 -1
- package/lib/module/store/restorePending.test.js.map +0 -1
- package/lib/module/store/restoredIds.test.js.map +0 -1
- package/lib/module/store/suggestions.js.map +0 -1
- package/lib/module/store/suggestions.test.js.map +0 -1
- package/lib/module/store/systemLine.test.js.map +0 -1
- package/lib/module/store/ticketPrompt.js.map +0 -1
- package/lib/module/store/traceText.js.map +0 -1
- package/lib/module/store/traceText.test.js.map +0 -1
- package/lib/module/store/transcriptPersistence.js.map +0 -1
- package/lib/module/store/transcriptPersistence.test.js.map +0 -1
- package/lib/module/store/turnRendering.test.js.map +0 -1
- package/lib/module/store/useAskBuoy.js.map +0 -1
- package/lib/module/store/useAskBuoySettings.js.map +0 -1
- package/lib/module/sync/askBuoySyncAdapter.js.map +0 -1
- package/lib/module/sync/askBuoySyncAdapter.test.js.map +0 -1
- package/lib/module/sync/wire.js.map +0 -1
- package/lib/module/types.js.map +0 -1
- package/lib/typescript/blocks/AskBlocks.d.ts.map +0 -1
- package/lib/typescript/blocks/BlockRenderer.d.ts.map +0 -1
- package/lib/typescript/blocks/ChromePrototypes.d.ts.map +0 -1
- package/lib/typescript/blocks/DataBlocks.d.ts.map +0 -1
- package/lib/typescript/blocks/ExtraBlocks.d.ts.map +0 -1
- package/lib/typescript/blocks/MediaBlocks.d.ts.map +0 -1
- package/lib/typescript/blocks/ReceiptBlocks.d.ts.map +0 -1
- package/lib/typescript/blocks/blockText.d.ts.map +0 -1
- package/lib/typescript/blocks/blockText.test.d.ts.map +0 -1
- package/lib/typescript/blocks/context.d.ts.map +0 -1
- package/lib/typescript/blocks/icons.d.ts.map +0 -1
- package/lib/typescript/blocks/index.d.ts.map +0 -1
- package/lib/typescript/blocks/listRow.test.d.ts.map +0 -1
- package/lib/typescript/blocks/pageState.d.ts.map +0 -1
- package/lib/typescript/blocks/pageState.test.d.ts.map +0 -1
- package/lib/typescript/blocks/primitives.d.ts.map +0 -1
- package/lib/typescript/blocks/primitivesIndex.d.ts.map +0 -1
- package/lib/typescript/blocks/ruleStates.d.ts.map +0 -1
- package/lib/typescript/components/ApprovalCard.d.ts.map +0 -1
- package/lib/typescript/components/AskBuoyHeader.d.ts.map +0 -1
- package/lib/typescript/components/AskBuoyIcon.d.ts.map +0 -1
- package/lib/typescript/components/AskBuoyModal.d.ts.map +0 -1
- package/lib/typescript/components/AskBuoySettings.d.ts.map +0 -1
- package/lib/typescript/components/ChangesBar.d.ts.map +0 -1
- package/lib/typescript/components/Composer.d.ts.map +0 -1
- package/lib/typescript/components/EmptyState.d.ts.map +0 -1
- package/lib/typescript/components/KeyboardPad.d.ts.map +0 -1
- package/lib/typescript/components/Markdown.d.ts.map +0 -1
- package/lib/typescript/components/MessageList.d.ts.map +0 -1
- package/lib/typescript/components/QueuedMessages.d.ts.map +0 -1
- package/lib/typescript/components/ThinkingStrip.d.ts.map +0 -1
- package/lib/typescript/components/TypingDots.d.ts.map +0 -1
- package/lib/typescript/components/markdownParse.d.ts.map +0 -1
- package/lib/typescript/components/markdownParse.test.d.ts.map +0 -1
- package/lib/typescript/components/useCopyAction.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/store/activityGroups.d.ts.map +0 -1
- package/lib/typescript/store/activityGroups.test.d.ts.map +0 -1
- package/lib/typescript/store/askBuoySettings.d.ts.map +0 -1
- package/lib/typescript/store/askBuoyStore.d.ts.map +0 -1
- package/lib/typescript/store/blockPlacement.d.ts.map +0 -1
- package/lib/typescript/store/blockPlacement.test.d.ts.map +0 -1
- package/lib/typescript/store/queue.test.d.ts.map +0 -1
- package/lib/typescript/store/resetConversation.d.ts.map +0 -1
- package/lib/typescript/store/restorePending.test.d.ts.map +0 -1
- package/lib/typescript/store/restoredIds.test.d.ts.map +0 -1
- package/lib/typescript/store/suggestions.d.ts.map +0 -1
- package/lib/typescript/store/suggestions.test.d.ts.map +0 -1
- package/lib/typescript/store/systemLine.test.d.ts.map +0 -1
- package/lib/typescript/store/ticketPrompt.d.ts.map +0 -1
- package/lib/typescript/store/traceText.d.ts.map +0 -1
- package/lib/typescript/store/traceText.test.d.ts.map +0 -1
- package/lib/typescript/store/transcriptPersistence.d.ts.map +0 -1
- package/lib/typescript/store/transcriptPersistence.test.d.ts.map +0 -1
- package/lib/typescript/store/turnRendering.test.d.ts.map +0 -1
- package/lib/typescript/store/useAskBuoy.d.ts.map +0 -1
- package/lib/typescript/store/useAskBuoySettings.d.ts.map +0 -1
- package/lib/typescript/sync/askBuoySyncAdapter.d.ts.map +0 -1
- package/lib/typescript/sync/askBuoySyncAdapter.test.d.ts.map +0 -1
- package/lib/typescript/sync/wire.d.ts.map +0 -1
- package/lib/typescript/types.d.ts.map +0 -1
|
@@ -1,478 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";import{useCallback as a,useEffect as g,useMemo as A,useRef as p,useState as P}from"react";import{Alert as W,Animated as I,StyleSheet as we,Text as Ce,View as G}from"react-native";import{isReversible as xe}from"@buoy-gg/agent-core";import{dispatchToolAction as Be,FeatureGate as $e,Info as Pe,JsModal as Ie,ModalHeader as H,night as f,setToolAttention as l,useSafeAreaInsets as He}from"@buoy-gg/shared-ui";import{BlockHandlersProvider as Le}from"../blocks";import{ApprovalCard as Me}from"./ApprovalCard";import{ChangesBar as Oe,useLedgerEntries as Re}from"./ChangesBar";import{ruleStatesFrom as De}from"../blocks/ruleStates";import{Composer as Ke}from"./Composer";import{KeyboardPad as Ee}from"./KeyboardPad";import{AskBuoyHeader as Ne}from"./AskBuoyHeader";import{AskBuoySettings as je}from"./AskBuoySettings";import{EmptyState as Fe}from"./EmptyState";import{MessageList as qe,transcriptToText as Ue}from"./MessageList";import{QueuedMessages as Ve}from"./QueuedMessages";import{askBuoyStore as i,queuePauseReason as _e}from"../store/askBuoyStore";import{TICKET_PROMPT as ze}from"../store/ticketPrompt";import{useAskBuoy as Qe}from"../store/useAskBuoy";import{useAskBuoySettings as We}from"../store/useAskBuoySettings";import{jsx as n,jsxs as T,Fragment as Ge}from"react/jsx-runtime";export function AskBuoyModal({visible:w,onClose:M,onBack:O,onMinimize:m,persistenceKey:J,config:y}){const{state:e,send:h,stop:C,reset:b,undoThenReset:R,approve:X,retry:Y,answer:D,runAction:K,editQueued:Z,removeQueued:ee,configured:x,toolCount:te,availableToolIds:se}=Qe(y);const[ne,oe]=P(false);const re=a(()=>{C();M()},[C,M]);const ae=a(()=>i.clearDraft(),[]);const[k,B]=P(false);const ie=a(()=>B(false),[]);const le=a(()=>B(true),[]);const u=!w;const E=!!e.pending||!!e.awaitingBlockId;const o=e.messages[e.messages.length-1];const v=p(false);const N=p(e.busy);g(()=>{if(u&&N.current&&!e.busy)v.current=true;if(!u)v.current=false;N.current=e.busy},[u,e.busy]);g(()=>{if(!u){l("ask-buoy",null);return}if(E){l("ask-buoy",{kind:"needsInput",label:e.pending?"Needs your approval":"Has a question for you"})}else if(v.current&&o?.role==="assistant"&&o.error){l("ask-buoy",{kind:"failed",label:"The last turn failed"})}else if(v.current&&!e.busy){l("ask-buoy",{kind:"done",label:"Finished"})}else{l("ask-buoy",null)}},[u,E,e.busy,e.pending,o]);g(()=>()=>l("ask-buoy",null),[]);g(()=>{if(e.pending&&k)B(false)},[e.pending,k]);const ue=He({minBottom:16});const[ce,de]=P("bottomSheet");const ge=ce==="floating"?0:ue.bottom;const pe=a(()=>{const t=i.getLedger();if(!t)return;void(async()=>{const s=await t.revertAll(Be);if(s.failed.length===0){i.setNotice(null);return}const r=s.failed.map(d=>`${d.label} (${d.error})`).join("; ");i.setNotice(`Couldn't undo ${s.failed.length} change${s.failed.length===1?"":"s"} \u2014 ${r}`)})()},[]);const fe=a(()=>oe(t=>!t),[]);const c=p(new I.Value(560)).current;const $=p(false);const j=a(()=>{if($.current)return;$.current=true;c.stopAnimation(t=>{const s=typeof t==="number"&&t>200?t:560;I.timing(c,{toValue:120,duration:220,useNativeDriver:false}).start(()=>{setTimeout(()=>{I.spring(c,{toValue:s,friction:9,useNativeDriver:false}).start(()=>{$.current=false})},2500)})})},[c]);const S=A(()=>{const t=e.messages[e.messages.length-1];if(!t||t.role!=="assistant")return"";const s=t.blocks.filter(r=>r.block.kind==="peek").length;return s>0?`${t.id}:${s}`:""},[e.messages]);const F=p("");g(()=>{if(S&&S!==F.current&&y?.peek!==false)j();F.current=S},[S,j,y]);const me=a(()=>{const t=i.getLedger();const s=t?.list().filter(r=>!r.undoneAt&&xe(r.effect)).length??0;if(s===0){b();return}W.alert("Undo changes first?",`Ask Buoy made ${s} change${s===1?"":"s"} that can still be undone. Clearing the conversation loses the only automatic undo for ${s===1?"it":"them"}.`,[{text:"Undo, then clear",onPress:()=>{void(async()=>{const r=await R();if(r.cleared)return;const d=r.reverted+r.failed.length;const Te=r.failed.map(Q=>`${Q.label} (${Q.error})`).join("\n");W.alert(`Couldn't undo ${r.failed.length} of ${d} change${d===1?"":"s"}`,`${Te}
|
|
2
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, StyleSheet, Text, View } from "react-native";
|
|
23
|
-
import { isReversible } from "@buoy-gg/agent-core";
|
|
24
|
-
import { dispatchToolAction, FeatureGate, Info, JsModal, ModalHeader, night, setToolAttention, useSafeAreaInsets } from "@buoy-gg/shared-ui";
|
|
25
|
-
import { BlockHandlersProvider } from "../blocks";
|
|
26
|
-
import { ApprovalCard } from "./ApprovalCard";
|
|
27
|
-
import { ChangesBar, useLedgerEntries } from "./ChangesBar";
|
|
28
|
-
import { ruleStatesFrom } from "../blocks/ruleStates";
|
|
29
|
-
import { Composer } from "./Composer";
|
|
30
|
-
import { KeyboardPad } from "./KeyboardPad";
|
|
31
|
-
import { AskBuoyHeader } from "./AskBuoyHeader";
|
|
32
|
-
import { AskBuoySettings } from "./AskBuoySettings";
|
|
33
|
-
import { EmptyState } from "./EmptyState";
|
|
34
|
-
import { MessageList, transcriptToText } from "./MessageList";
|
|
35
|
-
import { QueuedMessages } from "./QueuedMessages";
|
|
36
|
-
import { askBuoyStore, queuePauseReason } from "../store/askBuoyStore";
|
|
37
|
-
import { TICKET_PROMPT } from "../store/ticketPrompt";
|
|
38
|
-
import { useAskBuoy } from "../store/useAskBuoy";
|
|
39
|
-
import { useAskBuoySettings } from "../store/useAskBuoySettings";
|
|
40
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
41
|
-
export function AskBuoyModal({
|
|
42
|
-
visible,
|
|
43
|
-
onClose,
|
|
44
|
-
onBack,
|
|
45
|
-
onMinimize,
|
|
46
|
-
persistenceKey,
|
|
47
|
-
config
|
|
48
|
-
}) {
|
|
49
|
-
const {
|
|
50
|
-
state,
|
|
51
|
-
send,
|
|
52
|
-
stop,
|
|
53
|
-
reset,
|
|
54
|
-
undoThenReset,
|
|
55
|
-
approve,
|
|
56
|
-
retry,
|
|
57
|
-
answer,
|
|
58
|
-
runAction,
|
|
59
|
-
editQueued,
|
|
60
|
-
removeQueued,
|
|
61
|
-
configured,
|
|
62
|
-
toolCount,
|
|
63
|
-
availableToolIds
|
|
64
|
-
} = useAskBuoy(config);
|
|
65
|
-
const [changesOpen, setChangesOpen] = useState(false);
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Closing the sheet stops the turn.
|
|
69
|
-
*
|
|
70
|
-
* It did not, and the turn had no Stop left once the window was gone: closed
|
|
71
|
-
* mid-answer, the agent ran on invisibly — finishing tool calls and writing
|
|
72
|
-
* a full reply into a transcript nobody was watching. Dismissing the chat is
|
|
73
|
-
* the most natural "make it stop" gesture there is, and tool calls CHANGE
|
|
74
|
-
* THE APP, so a turn nobody can see or halt is the wrong thing to leave
|
|
75
|
-
* running. Minimise is the affordance for "keep going while I look" — that
|
|
76
|
-
* one deliberately does not stop anything.
|
|
77
|
-
*/
|
|
78
|
-
const closeAndStop = useCallback(() => {
|
|
79
|
-
stop();
|
|
80
|
-
onClose();
|
|
81
|
-
}, [stop, onClose]);
|
|
82
|
-
const takeDraft = useCallback(() => askBuoyStore.clearDraft(), []);
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Settings replaces the transcript in place rather than opening over it. The
|
|
86
|
-
* sheet's own back arrow is the way out, and the conversation is untouched
|
|
87
|
-
* underneath — a toggle you flip here should be visible the moment you go
|
|
88
|
-
* back, not after dismissing something.
|
|
89
|
-
*/
|
|
90
|
-
const [showSettings, setShowSettings] = useState(false);
|
|
91
|
-
const closeSettings = useCallback(() => setShowSettings(false), []);
|
|
92
|
-
const openSettings = useCallback(() => setShowSettings(true), []);
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* An approval that arrives while the sheet is hidden HOLDS, and the rail says
|
|
96
|
-
* so.
|
|
97
|
-
*
|
|
98
|
-
* It used to auto-decline: minimised, the card was simply not on screen —
|
|
99
|
-
* the host keeps this component mounted with `visible={false}` — so the turn
|
|
100
|
-
* parked on a promise nobody could answer, and failing safe meant declining
|
|
101
|
-
* the change and ending the turn. Which made minimise mean "stop", the
|
|
102
|
-
* opposite of what it is for ("keep going while I look at the app").
|
|
103
|
-
*
|
|
104
|
-
* Now the chip in the minimised rail gets a badge — "!" for needs-input, a
|
|
105
|
-
* dot for finished or failed — through the `setToolAttention` seam, and
|
|
106
|
-
* tapping the chip is the existing restore path, so the card is one tap
|
|
107
|
-
* away rather than gone. The approval wait is already excluded from the
|
|
108
|
-
* turn's deadline, so holding costs nothing. Closing the sheet still stops.
|
|
109
|
-
*
|
|
110
|
-
* The settings view hides the card while `visible` stays true, so a question
|
|
111
|
-
* arriving there flips back to the chat: a card you cannot see is the
|
|
112
|
-
* original bug in a different coat.
|
|
113
|
-
*/
|
|
114
|
-
const hidden = !visible;
|
|
115
|
-
const awaitingUser = !!state.pending || !!state.awaitingBlockId;
|
|
116
|
-
const lastMessage = state.messages[state.messages.length - 1];
|
|
117
|
-
const finishedWhileHidden = useRef(false);
|
|
118
|
-
const wasBusy = useRef(state.busy);
|
|
119
|
-
useEffect(() => {
|
|
120
|
-
if (hidden && wasBusy.current && !state.busy) finishedWhileHidden.current = true;
|
|
121
|
-
if (!hidden) finishedWhileHidden.current = false;
|
|
122
|
-
wasBusy.current = state.busy;
|
|
123
|
-
}, [hidden, state.busy]);
|
|
124
|
-
useEffect(() => {
|
|
125
|
-
if (!hidden) {
|
|
126
|
-
setToolAttention("ask-buoy", null);
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
if (awaitingUser) {
|
|
130
|
-
setToolAttention("ask-buoy", {
|
|
131
|
-
kind: "needsInput",
|
|
132
|
-
label: state.pending ? "Needs your approval" : "Has a question for you"
|
|
133
|
-
});
|
|
134
|
-
} else if (finishedWhileHidden.current && lastMessage?.role === "assistant" && lastMessage.error) {
|
|
135
|
-
setToolAttention("ask-buoy", {
|
|
136
|
-
kind: "failed",
|
|
137
|
-
label: "The last turn failed"
|
|
138
|
-
});
|
|
139
|
-
} else if (finishedWhileHidden.current && !state.busy) {
|
|
140
|
-
setToolAttention("ask-buoy", {
|
|
141
|
-
kind: "done",
|
|
142
|
-
label: "Finished"
|
|
143
|
-
});
|
|
144
|
-
} else {
|
|
145
|
-
setToolAttention("ask-buoy", null);
|
|
146
|
-
}
|
|
147
|
-
}, [hidden, awaitingUser, state.busy, state.pending, lastMessage]);
|
|
148
|
-
useEffect(() => () => setToolAttention("ask-buoy", null), []);
|
|
149
|
-
useEffect(() => {
|
|
150
|
-
if (state.pending && showSettings) setShowSettings(false);
|
|
151
|
-
}, [state.pending, showSettings]);
|
|
152
|
-
// A hardcoded device map, not the native library — an unmapped phone
|
|
153
|
-
// silently returns bottom: 0, which is how footers ended up sitting on the
|
|
154
|
-
// home indicator.
|
|
155
|
-
const insets = useSafeAreaInsets({
|
|
156
|
-
minBottom: 16
|
|
157
|
-
});
|
|
158
|
-
/**
|
|
159
|
-
* The safe-area inset is for the HOME INDICATOR, and only a bottom sheet
|
|
160
|
-
* touches it. A floating window is positioned away from the screen edge and
|
|
161
|
-
* clips its own rounded corner, so the same padding is just a band of dead
|
|
162
|
-
* space under the composer in the smallest layout the tool has.
|
|
163
|
-
*
|
|
164
|
-
* JsModal owns the mode (it restores a persisted one on mount and reports it
|
|
165
|
-
* here), so this mirrors rather than decides. Default matches JsModal's own:
|
|
166
|
-
* a sheet until told otherwise.
|
|
167
|
-
*/
|
|
168
|
-
const [mode, setMode] = useState("bottomSheet");
|
|
169
|
-
const bottomInset = mode === "floating" ? 0 : insets.bottom;
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* `dispatchToolAction` is imported STATICALLY at the top of this file, not
|
|
173
|
-
* with `import()`. A dynamic import here resolves through Metro's
|
|
174
|
-
* async-require path, which in a lazy dev bundle rejects with "Expected
|
|
175
|
-
* HMRClient.setup() call at startup" — and because the promise was voided,
|
|
176
|
-
* Undo did nothing at all while the bar went on claiming the changes were
|
|
177
|
-
* undoable. shared-ui is already a static dependency of this component.
|
|
178
|
-
*
|
|
179
|
-
* A failed revert is SHOWN. `revertAll` reports what it could not put back,
|
|
180
|
-
* and swallowing that is the same failure in a quieter form: the whole
|
|
181
|
-
* reason mutations may auto-run is that undo is real.
|
|
182
|
-
*/
|
|
183
|
-
const undoAll = useCallback(() => {
|
|
184
|
-
const ledger = askBuoyStore.getLedger();
|
|
185
|
-
if (!ledger) return;
|
|
186
|
-
void (async () => {
|
|
187
|
-
const outcome = await ledger.revertAll(dispatchToolAction);
|
|
188
|
-
if (outcome.failed.length === 0) {
|
|
189
|
-
askBuoyStore.setNotice(null);
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
const detail = outcome.failed.map(f => `${f.label} (${f.error})`).join("; ");
|
|
193
|
-
askBuoyStore.setNotice(`Couldn't undo ${outcome.failed.length} change${outcome.failed.length === 1 ? "" : "s"} — ${detail}`);
|
|
194
|
-
})();
|
|
195
|
-
}, []);
|
|
196
|
-
const toggleChanges = useCallback(() => setChangesOpen(v => !v), []);
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* PEEK. When the agent navigates or taps, the sheet drops to a 120pt strip
|
|
200
|
-
* for ~2.5s so the user watches the app do it, then springs back to the
|
|
201
|
-
* height it had (including a user's drag-resize — the value is read live,
|
|
202
|
-
* never assumed). Rides JsModal's external `animatedHeight` seam, so the
|
|
203
|
-
* modal's own drag-resize keeps working on the same value.
|
|
204
|
-
*/
|
|
205
|
-
const sheetHeight = useRef(new Animated.Value(560)).current;
|
|
206
|
-
const peeking = useRef(false);
|
|
207
|
-
const runPeek = useCallback(() => {
|
|
208
|
-
if (peeking.current) return;
|
|
209
|
-
peeking.current = true;
|
|
210
|
-
sheetHeight.stopAnimation(from => {
|
|
211
|
-
const restoreTo = typeof from === "number" && from > 200 ? from : 560;
|
|
212
|
-
Animated.timing(sheetHeight, {
|
|
213
|
-
toValue: 120,
|
|
214
|
-
duration: 220,
|
|
215
|
-
useNativeDriver: false
|
|
216
|
-
}).start(() => {
|
|
217
|
-
setTimeout(() => {
|
|
218
|
-
Animated.spring(sheetHeight, {
|
|
219
|
-
toValue: restoreTo,
|
|
220
|
-
friction: 9,
|
|
221
|
-
useNativeDriver: false
|
|
222
|
-
}).start(() => {
|
|
223
|
-
peeking.current = false;
|
|
224
|
-
});
|
|
225
|
-
}, 2500);
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
}, [sheetHeight]);
|
|
229
|
-
|
|
230
|
-
// A new `peek` receipt (navigate, tap) triggers the shrink. Keyed by
|
|
231
|
-
// message id + count so a fresh assistant message restarts the count.
|
|
232
|
-
const peekKey = useMemo(() => {
|
|
233
|
-
const last = state.messages[state.messages.length - 1];
|
|
234
|
-
if (!last || last.role !== "assistant") return "";
|
|
235
|
-
const peeks = last.blocks.filter(p => p.block.kind === "peek").length;
|
|
236
|
-
return peeks > 0 ? `${last.id}:${peeks}` : "";
|
|
237
|
-
}, [state.messages]);
|
|
238
|
-
const prevPeekKey = useRef("");
|
|
239
|
-
useEffect(() => {
|
|
240
|
-
if (peekKey && peekKey !== prevPeekKey.current && config?.peek !== false) runPeek();
|
|
241
|
-
prevPeekKey.current = peekKey;
|
|
242
|
-
}, [peekKey, runPeek, config]);
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* New conversation, guarded. Clearing the session clears the ledger — the
|
|
246
|
-
* ONLY undo surface — while the agent's changes stay live in the app, so
|
|
247
|
-
* with reversible changes outstanding the user chooses their fate first.
|
|
248
|
-
*
|
|
249
|
-
* "Undo, then clear" reads the outcome. It did not: two of five reverts
|
|
250
|
-
* would fail (a key changed since) and the conversation cleared anyway,
|
|
251
|
-
* leaving two changes live with no record. Now a failed undo keeps the
|
|
252
|
-
* conversation and names what is still applied; clearing is a second,
|
|
253
|
-
* explicit tap. See resetConversation.ts.
|
|
254
|
-
*/
|
|
255
|
-
const confirmReset = useCallback(() => {
|
|
256
|
-
const ledger = askBuoyStore.getLedger();
|
|
257
|
-
const reversible = ledger?.list().filter(e => !e.undoneAt && isReversible(e.effect)).length ?? 0;
|
|
258
|
-
if (reversible === 0) {
|
|
259
|
-
reset();
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
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"}.`, [{
|
|
263
|
-
text: "Undo, then clear",
|
|
264
|
-
onPress: () => {
|
|
265
|
-
void (async () => {
|
|
266
|
-
const outcome = await undoThenReset();
|
|
267
|
-
if (outcome.cleared) return;
|
|
268
|
-
const total = outcome.reverted + outcome.failed.length;
|
|
269
|
-
const stillApplied = outcome.failed.map(f => `${f.label} (${f.error})`).join("\n");
|
|
270
|
-
Alert.alert(`Couldn't undo ${outcome.failed.length} of ${total} change${total === 1 ? "" : "s"}`, `${stillApplied}\n\nStill applied in the app. Clear the conversation anyway?`, [{
|
|
271
|
-
text: "Keep conversation",
|
|
272
|
-
style: "cancel"
|
|
273
|
-
}, {
|
|
274
|
-
text: "Clear anyway",
|
|
275
|
-
style: "destructive",
|
|
276
|
-
onPress: reset
|
|
277
|
-
}]);
|
|
278
|
-
})();
|
|
279
|
-
}
|
|
280
|
-
}, {
|
|
281
|
-
text: "Clear anyway",
|
|
282
|
-
style: "destructive",
|
|
283
|
-
onPress: reset
|
|
284
|
-
}, {
|
|
285
|
-
text: "Cancel",
|
|
286
|
-
style: "cancel"
|
|
287
|
-
}]);
|
|
288
|
-
}, [reset, undoThenReset]);
|
|
289
|
-
|
|
290
|
-
// The header's live status: the title of whichever tool call is in flight.
|
|
291
|
-
const activeLabel = useMemo(() => {
|
|
292
|
-
const last = state.messages[state.messages.length - 1];
|
|
293
|
-
if (!last || last.role !== "assistant" || !last.streaming) return null;
|
|
294
|
-
return last.toolCalls.find(c => c.status === "running")?.label ?? null;
|
|
295
|
-
}, [state.messages]);
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* What a block can do in THIS host. `minimize` collapses the sheet to the
|
|
299
|
-
* rail so the user can look at the app (the peek chip). `openTool` has no
|
|
300
|
-
* seam yet, so those buttons don't render here rather than render dead.
|
|
301
|
-
*/
|
|
302
|
-
const ledgerEntries = useLedgerEntries(askBuoyStore.getLedger());
|
|
303
|
-
const ruleStates = useMemo(() => ruleStatesFrom(ledgerEntries), [ledgerEntries]);
|
|
304
|
-
const blockHandlers = useMemo(() => ({
|
|
305
|
-
answer,
|
|
306
|
-
runAction: (action, blockId) => {
|
|
307
|
-
if (action.minimize) {
|
|
308
|
-
onMinimize?.({
|
|
309
|
-
mode: "bottomSheet"
|
|
310
|
-
});
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
return runAction(action, blockId);
|
|
314
|
-
},
|
|
315
|
-
answered: state.answers,
|
|
316
|
-
actionState: state.actionState,
|
|
317
|
-
busy: state.busy,
|
|
318
|
-
supports: {
|
|
319
|
-
openTool: false,
|
|
320
|
-
minimize: !!onMinimize,
|
|
321
|
-
dispatch: true
|
|
322
|
-
},
|
|
323
|
-
rules: ruleStates
|
|
324
|
-
}), [answer, runAction, onMinimize, state.answers, state.actionState, state.busy, ruleStates]);
|
|
325
|
-
|
|
326
|
-
// The last assistant turn carrying an error is the only "it went wrong"
|
|
327
|
-
// signal the header can read; it clears as soon as the next send starts.
|
|
328
|
-
const failed = !state.busy && lastMessage?.role === "assistant" && !!lastMessage.error;
|
|
329
|
-
/**
|
|
330
|
-
* Stop invites a redirect. The turn just ended because the user said so;
|
|
331
|
-
* the likeliest next move is "do this instead", not "do that again" — so
|
|
332
|
-
* the composer takes focus with that prompt. Keyed by the stopped message so
|
|
333
|
-
* it happens once per stop, and only while the sheet is on screen.
|
|
334
|
-
*/
|
|
335
|
-
const redirectKey = !state.busy && lastMessage?.role === "assistant" && lastMessage.stopped && !lastMessage.error ? lastMessage.id : null;
|
|
336
|
-
const queuePaused = queuePauseReason(state);
|
|
337
|
-
|
|
338
|
-
// Built on press, not on render — a streaming answer would otherwise rebuild
|
|
339
|
-
// the whole transcript on every frame for a button nobody tapped.
|
|
340
|
-
const {
|
|
341
|
-
showThinking,
|
|
342
|
-
readOnly
|
|
343
|
-
} = useAskBuoySettings();
|
|
344
|
-
const getTranscript = useCallback(() => transcriptToText(state.messages, showThinking), [state.messages, showThinking]);
|
|
345
|
-
const requestTicket = useCallback(() => send(TICKET_PROMPT), [send]);
|
|
346
|
-
const header = showSettings ? /*#__PURE__*/_jsxs(ModalHeader, {
|
|
347
|
-
children: [/*#__PURE__*/_jsx(ModalHeader.Navigation, {
|
|
348
|
-
onBack: closeSettings
|
|
349
|
-
}), /*#__PURE__*/_jsx(ModalHeader.Content, {
|
|
350
|
-
title: "Settings",
|
|
351
|
-
subtitle: "Ask Buoy",
|
|
352
|
-
testID: "buoy-ask-buoy-settings-title"
|
|
353
|
-
})]
|
|
354
|
-
}) : /*#__PURE__*/_jsx(AskBuoyHeader, {
|
|
355
|
-
configured: configured,
|
|
356
|
-
busy: state.busy,
|
|
357
|
-
failed: failed,
|
|
358
|
-
activeLabel: activeLabel,
|
|
359
|
-
awaitingApproval: !!state.pending,
|
|
360
|
-
startedAt: lastMessage?.role === "assistant" && lastMessage.streaming ? lastMessage.startedAt ?? null : null,
|
|
361
|
-
stopping: state.stopping,
|
|
362
|
-
readOnly: readOnly,
|
|
363
|
-
toolCount: toolCount,
|
|
364
|
-
hasMessages: state.messages.length > 0,
|
|
365
|
-
onBack: onBack,
|
|
366
|
-
onReset: confirmReset,
|
|
367
|
-
getTranscript: getTranscript,
|
|
368
|
-
onOpenSettings: openSettings,
|
|
369
|
-
onTicket: requestTicket
|
|
370
|
-
});
|
|
371
|
-
return /*#__PURE__*/_jsx(JsModal, {
|
|
372
|
-
visible: visible,
|
|
373
|
-
onClose: closeAndStop
|
|
374
|
-
// The message list is the only scroller. JsModal's default wrapper is
|
|
375
|
-
// flexGrow:1, which makes a nested flex:1 scroller resolve against the
|
|
376
|
-
// content and never scroll at all.
|
|
377
|
-
,
|
|
378
|
-
disableScrollWrapper: true
|
|
379
|
-
// ToolBackground is an animated star field. A chat re-renders on every
|
|
380
|
-
// streamed token; two continuous animations competing is a dropped
|
|
381
|
-
// frame budget for no benefit.
|
|
382
|
-
,
|
|
383
|
-
background: false,
|
|
384
|
-
initialHeight: 560,
|
|
385
|
-
animatedHeight: sheetHeight,
|
|
386
|
-
header: {
|
|
387
|
-
customContent: header,
|
|
388
|
-
showToggleButton: false
|
|
389
|
-
},
|
|
390
|
-
onBack: onBack,
|
|
391
|
-
onMinimize: onMinimize,
|
|
392
|
-
onModeChange: setMode,
|
|
393
|
-
persistenceKey: persistenceKey ?? "buoy-ask-buoy",
|
|
394
|
-
enablePersistence: true,
|
|
395
|
-
children: /*#__PURE__*/_jsx(BlockHandlersProvider, {
|
|
396
|
-
value: blockHandlers,
|
|
397
|
-
children: /*#__PURE__*/_jsxs(View, {
|
|
398
|
-
style: [styles.root, {
|
|
399
|
-
paddingBottom: bottomInset
|
|
400
|
-
}],
|
|
401
|
-
children: [/*#__PURE__*/_jsx(ChangesBar, {
|
|
402
|
-
ledger: askBuoyStore.getLedger(),
|
|
403
|
-
onUndoAll: undoAll,
|
|
404
|
-
expanded: changesOpen,
|
|
405
|
-
onToggle: toggleChanges
|
|
406
|
-
}), state.notice && /*#__PURE__*/_jsxs(View, {
|
|
407
|
-
style: styles.notice,
|
|
408
|
-
testID: "buoy-ask-buoy-notice",
|
|
409
|
-
children: [/*#__PURE__*/_jsx(Info, {
|
|
410
|
-
size: 14,
|
|
411
|
-
color: night.color.info
|
|
412
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
413
|
-
style: styles.noticeText,
|
|
414
|
-
children: state.notice
|
|
415
|
-
})]
|
|
416
|
-
}), /*#__PURE__*/_jsx(KeyboardPad, {
|
|
417
|
-
children: /*#__PURE__*/_jsx(FeatureGate, {
|
|
418
|
-
featureName: "Ask Buoy",
|
|
419
|
-
children: showSettings ? /*#__PURE__*/_jsx(AskBuoySettings, {}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
420
|
-
children: [/*#__PURE__*/_jsx(MessageList, {
|
|
421
|
-
messages: state.messages,
|
|
422
|
-
onRetry: retry,
|
|
423
|
-
waitingOnUser: !!state.pending || !!state.awaitingBlockId,
|
|
424
|
-
ListEmptyComponent: /*#__PURE__*/_jsx(EmptyState, {
|
|
425
|
-
configured: configured,
|
|
426
|
-
onPick: send,
|
|
427
|
-
availableToolIds: availableToolIds,
|
|
428
|
-
readOnly: readOnly || !!config?.policy?.readOnly
|
|
429
|
-
})
|
|
430
|
-
}), /*#__PURE__*/_jsx(QueuedMessages, {
|
|
431
|
-
items: state.queued,
|
|
432
|
-
paused: queuePaused,
|
|
433
|
-
onEdit: editQueued,
|
|
434
|
-
onRemove: removeQueued
|
|
435
|
-
}), state.pending && /*#__PURE__*/_jsx(ApprovalCard, {
|
|
436
|
-
pending: state.pending,
|
|
437
|
-
onAnswer: approve
|
|
438
|
-
}), /*#__PURE__*/_jsx(Composer, {
|
|
439
|
-
onSend: send,
|
|
440
|
-
onStop: stop,
|
|
441
|
-
busy: state.busy,
|
|
442
|
-
draft: state.draft,
|
|
443
|
-
onDraftTaken: takeDraft,
|
|
444
|
-
disabled: !configured,
|
|
445
|
-
focusKey: redirectKey,
|
|
446
|
-
canFocus: visible,
|
|
447
|
-
placeholder: redirectKey ? "Tell it what to do differently…" : state.awaitingBlockId ? "Pick an option above, or type…" : undefined
|
|
448
|
-
})]
|
|
449
|
-
})
|
|
450
|
-
})
|
|
451
|
-
})]
|
|
452
|
-
})
|
|
453
|
-
})
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
const styles = StyleSheet.create({
|
|
457
|
-
// Transparent or it paints over the sheet's own chrome — the convention is
|
|
458
|
-
// repeated verbatim across every Buoy tool body.
|
|
459
|
-
root: {
|
|
460
|
-
flex: 1,
|
|
461
|
-
backgroundColor: "transparent"
|
|
462
|
-
},
|
|
463
|
-
notice: {
|
|
464
|
-
flexDirection: "row",
|
|
465
|
-
alignItems: "flex-start",
|
|
466
|
-
gap: 8,
|
|
467
|
-
paddingHorizontal: night.gutter,
|
|
468
|
-
paddingVertical: 10,
|
|
469
|
-
backgroundColor: night.color.infoSoft
|
|
470
|
-
},
|
|
471
|
-
noticeText: {
|
|
472
|
-
flex: 1,
|
|
473
|
-
color: night.color.text,
|
|
474
|
-
fontSize: night.font.caption,
|
|
475
|
-
lineHeight: 18
|
|
476
|
-
}
|
|
477
|
-
});
|
|
478
|
-
//# sourceMappingURL=AskBuoyModal.js.map
|
|
3
|
+
Still applied in the app. Clear the conversation anyway?`,[{text:"Keep conversation",style:"cancel"},{text:"Clear anyway",style:"destructive",onPress:b}])})()}},{text:"Clear anyway",style:"destructive",onPress:b},{text:"Cancel",style:"cancel"}])},[b,R]);const ye=A(()=>{const t=e.messages[e.messages.length-1];if(!t||t.role!=="assistant"||!t.streaming)return null;return t.toolCalls.find(s=>s.status==="running")?.label??null},[e.messages]);const q=Re(i.getLedger());const U=A(()=>De(q),[q]);const he=A(()=>({answer:D,runAction:(t,s)=>{if(t.minimize){m?.({mode:"bottomSheet"});return}return K(t,s)},answered:e.answers,actionState:e.actionState,busy:e.busy,supports:{openTool:false,minimize:!!m,dispatch:true},rules:U}),[D,K,m,e.answers,e.actionState,e.busy,U]);const be=!e.busy&&o?.role==="assistant"&&!!o.error;const V=!e.busy&&o?.role==="assistant"&&o.stopped&&!o.error?o.id:null;const ke=_e(e);const{showThinking:_,readOnly:z}=We();const ve=a(()=>Ue(e.messages,_),[e.messages,_]);const Se=a(()=>h(ze),[h]);const Ae=k?T(H,{children:[n(H.Navigation,{onBack:ie}),n(H.Content,{title:"Settings",subtitle:"Ask Buoy",testID:"buoy-ask-buoy-settings-title"})]}):n(Ne,{configured:x,busy:e.busy,failed:be,activeLabel:ye,awaitingApproval:!!e.pending,startedAt:o?.role==="assistant"&&o.streaming?o.startedAt??null:null,stopping:e.stopping,readOnly:z,toolCount:te,hasMessages:e.messages.length>0,onBack:O,onReset:me,getTranscript:ve,onOpenSettings:le,onTicket:Se});return n(Ie,{visible:w,onClose:re,disableScrollWrapper:true,background:false,initialHeight:560,animatedHeight:c,header:{customContent:Ae,showToggleButton:false},onBack:O,onMinimize:m,onModeChange:de,persistenceKey:J??"buoy-ask-buoy",enablePersistence:true,children:n(Le,{value:he,children:T(G,{style:[L.root,{paddingBottom:ge}],children:[n(Oe,{ledger:i.getLedger(),onUndoAll:pe,expanded:ne,onToggle:fe}),e.notice&&T(G,{style:L.notice,testID:"buoy-ask-buoy-notice",children:[n(Pe,{size:14,color:f.color.info}),n(Ce,{style:L.noticeText,children:e.notice})]}),n(Ee,{children:n($e,{featureName:"Ask Buoy",children:k?n(je,{}):T(Ge,{children:[n(qe,{messages:e.messages,onRetry:Y,waitingOnUser:!!e.pending||!!e.awaitingBlockId,ListEmptyComponent:n(Fe,{configured:x,onPick:h,availableToolIds:se,readOnly:z||!!y?.policy?.readOnly})}),n(Ve,{items:e.queued,paused:ke,onEdit:Z,onRemove:ee}),e.pending&&n(Me,{pending:e.pending,onAnswer:X}),n(Ke,{onSend:h,onStop:C,busy:e.busy,draft:e.draft,onDraftTaken:ae,disabled:!x,focusKey:V,canFocus:w,placeholder:V?"Tell it what to do differently\u2026":e.awaitingBlockId?"Pick an option above, or type\u2026":void 0})]})})})]})})})}const L=we.create({root:{flex:1,backgroundColor:"transparent"},notice:{flexDirection:"row",alignItems:"flex-start",gap:8,paddingHorizontal:f.gutter,paddingVertical:10,backgroundColor:f.color.infoSoft},noticeText:{flex:1,color:f.color.text,fontSize:f.font.caption,lineHeight:18}});
|
|
@@ -1,176 +1 @@
|
|
|
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 { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
|
|
15
|
-
import { AlertTriangle, night, ToggleRow } from "@buoy-gg/shared-ui";
|
|
16
|
-
import { useAskBuoySettings } from "../store/useAskBuoySettings";
|
|
17
|
-
import { askBuoySettings } from "../store/askBuoySettings";
|
|
18
|
-
import { askBuoyStore } from "../store/askBuoyStore";
|
|
19
|
-
import { useAskBuoyState } from "../store/useAskBuoy";
|
|
20
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
21
|
-
export function AskBuoySettings() {
|
|
22
|
-
const settings = useAskBuoySettings();
|
|
23
|
-
const trusted = useAskBuoyState().trusted;
|
|
24
|
-
return /*#__PURE__*/_jsxs(ScrollView, {
|
|
25
|
-
style: styles.scroll,
|
|
26
|
-
contentContainerStyle: styles.content,
|
|
27
|
-
testID: "buoy-ask-buoy-settings",
|
|
28
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
29
|
-
style: styles.section,
|
|
30
|
-
children: "CHAT"
|
|
31
|
-
}), /*#__PURE__*/_jsx(ToggleRow, {
|
|
32
|
-
testID: "buoy-ask-buoy-setting-thinking",
|
|
33
|
-
label: "Show agent thinking",
|
|
34
|
-
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.",
|
|
35
|
-
value: settings.showThinking,
|
|
36
|
-
onValueChange: next => askBuoySettings.set("showThinking", next)
|
|
37
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
38
|
-
style: styles.note,
|
|
39
|
-
children: "Not every model reports reasoning. Claude thinks by default; most OpenAI models return none, and the strip then shows the steps alone."
|
|
40
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
41
|
-
style: styles.section,
|
|
42
|
-
children: "PERMISSIONS"
|
|
43
|
-
}), /*#__PURE__*/_jsx(ToggleRow, {
|
|
44
|
-
testID: "buoy-ask-buoy-setting-readonly",
|
|
45
|
-
label: "Read only",
|
|
46
|
-
description: "Inspect the app, change nothing. Every write and simulation is refused until this is off. Undo still works \u2014 putting things back is the safe direction.",
|
|
47
|
-
value: settings.readOnly,
|
|
48
|
-
onValueChange: next => askBuoySettings.set("readOnly", next)
|
|
49
|
-
}), settings.readOnly ? /*#__PURE__*/_jsx(Text, {
|
|
50
|
-
style: styles.note,
|
|
51
|
-
testID: "buoy-ask-buoy-readonly-note",
|
|
52
|
-
children: "On across reloads until you turn it off here. The header says \u201CRead only\u201D while it is on. It adds to whatever this app already restricts \u2014 it never loosens anything."
|
|
53
|
-
}) : null, /*#__PURE__*/_jsx(ToggleRow, {
|
|
54
|
-
testID: "buoy-ask-buoy-setting-bypass",
|
|
55
|
-
tone: "warning",
|
|
56
|
-
emphasizeLabel: settings.bypassApprovals,
|
|
57
|
-
disabled: settings.readOnly,
|
|
58
|
-
label: "Skip approval prompts",
|
|
59
|
-
description: settings.readOnly ? "Unavailable while Read only is on — nothing can be approved." : "Runs every action the moment the agent calls it, with no Allow card — including the destructive ones that wipe or reset data.",
|
|
60
|
-
value: settings.bypassApprovals,
|
|
61
|
-
onValueChange: next => askBuoySettings.set("bypassApprovals", next)
|
|
62
|
-
}), settings.bypassApprovals && !settings.readOnly ? /*#__PURE__*/_jsxs(View, {
|
|
63
|
-
style: styles.warning,
|
|
64
|
-
testID: "buoy-ask-buoy-bypass-warning",
|
|
65
|
-
children: [/*#__PURE__*/_jsx(AlertTriangle, {
|
|
66
|
-
size: 14,
|
|
67
|
-
color: night.color.warning
|
|
68
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
69
|
-
style: styles.warningText,
|
|
70
|
-
children: "Nothing will ask before a change lands. A wipe or a reset runs on the model's word alone, and Undo only reverses the changes that can be reversed \u2014 the bar tells you which. This stays on across reloads and app restarts until you turn it off here, so leave it off on any device holding data you care about. It does not widen what the agent may reach: read-only mode, this app's deny list and the release-build refusals still apply."
|
|
71
|
-
})]
|
|
72
|
-
}) : /*#__PURE__*/_jsx(Text, {
|
|
73
|
-
style: styles.note,
|
|
74
|
-
children: "On by default for destructive actions only \u2014 reads and ordinary writes already run without asking, and the changes bar records them."
|
|
75
|
-
}), trusted.length > 0 ? /*#__PURE__*/_jsxs(View, {
|
|
76
|
-
style: styles.trustedBox,
|
|
77
|
-
testID: "buoy-ask-buoy-trusted",
|
|
78
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
79
|
-
style: styles.section,
|
|
80
|
-
children: "ALLOWED WITHOUT ASKING \u2014 THIS CHAT"
|
|
81
|
-
}), trusted.map(t => /*#__PURE__*/_jsxs(View, {
|
|
82
|
-
style: styles.trustedRow,
|
|
83
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
84
|
-
style: styles.trustedLabel,
|
|
85
|
-
numberOfLines: 2,
|
|
86
|
-
children: t.label
|
|
87
|
-
}), /*#__PURE__*/_jsx(Pressable, {
|
|
88
|
-
testID: `buoy-ask-buoy-untrust-${t.key}`,
|
|
89
|
-
accessibilityRole: "button",
|
|
90
|
-
onPress: () => askBuoyStore.untrust(t.key),
|
|
91
|
-
style: ({
|
|
92
|
-
pressed
|
|
93
|
-
}) => [styles.forget, pressed && {
|
|
94
|
-
opacity: 0.7
|
|
95
|
-
}],
|
|
96
|
-
hitSlop: 6,
|
|
97
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
98
|
-
style: styles.forgetText,
|
|
99
|
-
children: "Ask again"
|
|
100
|
-
})
|
|
101
|
-
})]
|
|
102
|
-
}, t.key))]
|
|
103
|
-
}) : null]
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
const styles = StyleSheet.create({
|
|
107
|
-
scroll: {
|
|
108
|
-
flex: 1
|
|
109
|
-
},
|
|
110
|
-
content: {
|
|
111
|
-
padding: night.gutter,
|
|
112
|
-
gap: 10,
|
|
113
|
-
paddingBottom: 32
|
|
114
|
-
},
|
|
115
|
-
section: {
|
|
116
|
-
color: night.color.textTertiary,
|
|
117
|
-
fontSize: 10,
|
|
118
|
-
fontWeight: "700",
|
|
119
|
-
letterSpacing: 0.6,
|
|
120
|
-
paddingHorizontal: 4,
|
|
121
|
-
paddingTop: 4
|
|
122
|
-
},
|
|
123
|
-
warning: {
|
|
124
|
-
flexDirection: "row",
|
|
125
|
-
gap: 8,
|
|
126
|
-
padding: night.cardPad,
|
|
127
|
-
borderRadius: night.radius.card,
|
|
128
|
-
borderWidth: StyleSheet.hairlineWidth,
|
|
129
|
-
borderColor: night.color.warning,
|
|
130
|
-
backgroundColor: night.color.surface
|
|
131
|
-
},
|
|
132
|
-
warningText: {
|
|
133
|
-
flex: 1,
|
|
134
|
-
color: night.color.warning,
|
|
135
|
-
fontSize: night.font.micro,
|
|
136
|
-
lineHeight: 16
|
|
137
|
-
},
|
|
138
|
-
trustedBox: {
|
|
139
|
-
gap: 6,
|
|
140
|
-
paddingTop: 6
|
|
141
|
-
},
|
|
142
|
-
trustedRow: {
|
|
143
|
-
flexDirection: "row",
|
|
144
|
-
alignItems: "center",
|
|
145
|
-
gap: 10,
|
|
146
|
-
padding: night.cardPad,
|
|
147
|
-
borderRadius: night.radius.card,
|
|
148
|
-
borderWidth: StyleSheet.hairlineWidth,
|
|
149
|
-
borderColor: night.color.border,
|
|
150
|
-
backgroundColor: night.color.surface
|
|
151
|
-
},
|
|
152
|
-
trustedLabel: {
|
|
153
|
-
flex: 1,
|
|
154
|
-
color: night.color.text,
|
|
155
|
-
fontSize: night.font.caption,
|
|
156
|
-
lineHeight: 18
|
|
157
|
-
},
|
|
158
|
-
forget: {
|
|
159
|
-
paddingHorizontal: 10,
|
|
160
|
-
paddingVertical: 6,
|
|
161
|
-
borderRadius: night.radius.row,
|
|
162
|
-
backgroundColor: night.color.button
|
|
163
|
-
},
|
|
164
|
-
forgetText: {
|
|
165
|
-
color: night.color.text,
|
|
166
|
-
fontSize: night.font.micro,
|
|
167
|
-
fontWeight: "600"
|
|
168
|
-
},
|
|
169
|
-
note: {
|
|
170
|
-
color: night.color.textTertiary,
|
|
171
|
-
fontSize: night.font.micro,
|
|
172
|
-
lineHeight: 16,
|
|
173
|
-
paddingHorizontal: 4
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
//# sourceMappingURL=AskBuoySettings.js.map
|
|
1
|
+
"use strict";import{Pressable as y,ScrollView as p,StyleSheet as i,Text as s,View as l}from"react-native";import{AlertTriangle as g,night as e,ToggleRow as d}from"@buoy-gg/shared-ui";import{useAskBuoySettings as b}from"../store/useAskBuoySettings";import{askBuoySettings as u}from"../store/askBuoySettings";import{askBuoyStore as f}from"../store/askBuoyStore";import{useAskBuoyState as w}from"../store/useAskBuoy";import{jsx as o,jsxs as a}from"react/jsx-runtime";export function AskBuoySettings(){const r=b();const c=w().trusted;return a(p,{style:t.scroll,contentContainerStyle:t.content,testID:"buoy-ask-buoy-settings",children:[o(s,{style:t.section,children:"CHAT"}),o(d,{testID:"buoy-ask-buoy-setting-thinking",label:"Show agent thinking",description:"Adds a collapsed strip under each answer: the model's reasoning, and every step it ran with its parameters, result, duration and token cost. Copy includes the steps and reasoning while this is on, so you can read the run outside the app.",value:r.showThinking,onValueChange:n=>u.set("showThinking",n)}),o(s,{style:t.note,children:"Not every model reports reasoning. Claude thinks by default; most OpenAI models return none, and the strip then shows the steps alone."}),o(s,{style:t.section,children:"PERMISSIONS"}),o(d,{testID:"buoy-ask-buoy-setting-readonly",label:"Read only",description:"Inspect the app, change nothing. Every write and simulation is refused until this is off. Undo still works \u2014 putting things back is the safe direction.",value:r.readOnly,onValueChange:n=>u.set("readOnly",n)}),r.readOnly?o(s,{style:t.note,testID:"buoy-ask-buoy-readonly-note",children:"On across reloads until you turn it off here. The header says \u201CRead only\u201D while it is on. It adds to whatever this app already restricts \u2014 it never loosens anything."}):null,o(d,{testID:"buoy-ask-buoy-setting-bypass",tone:"warning",emphasizeLabel:r.bypassApprovals,disabled:r.readOnly,label:"Skip approval prompts",description:r.readOnly?"Unavailable while Read only is on \u2014 nothing can be approved.":"Runs every action the moment the agent calls it, with no Allow card \u2014 including the destructive ones that wipe or reset data.",value:r.bypassApprovals,onValueChange:n=>u.set("bypassApprovals",n)}),r.bypassApprovals&&!r.readOnly?a(l,{style:t.warning,testID:"buoy-ask-buoy-bypass-warning",children:[o(g,{size:14,color:e.color.warning}),o(s,{style:t.warningText,children:"Nothing will ask before a change lands. A wipe or a reset runs on the model's word alone, and Undo only reverses the changes that can be reversed \u2014 the bar tells you which. This stays on across reloads and app restarts until you turn it off here, so leave it off on any device holding data you care about. It does not widen what the agent may reach: read-only mode, this app's deny list and the release-build refusals still apply."})]}):o(s,{style:t.note,children:"On by default for destructive actions only \u2014 reads and ordinary writes already run without asking, and the changes bar records them."}),c.length>0?a(l,{style:t.trustedBox,testID:"buoy-ask-buoy-trusted",children:[o(s,{style:t.section,children:"ALLOWED WITHOUT ASKING \u2014 THIS CHAT"}),c.map(n=>a(l,{style:t.trustedRow,children:[o(s,{style:t.trustedLabel,numberOfLines:2,children:n.label}),o(y,{testID:`buoy-ask-buoy-untrust-${n.key}`,accessibilityRole:"button",onPress:()=>f.untrust(n.key),style:({pressed:h})=>[t.forget,h&&{opacity:.7}],hitSlop:6,children:o(s,{style:t.forgetText,children:"Ask again"})})]},n.key))]}):null]})}const t=i.create({scroll:{flex:1},content:{padding:e.gutter,gap:10,paddingBottom:32},section:{color:e.color.textTertiary,fontSize:10,fontWeight:"700",letterSpacing:.6,paddingHorizontal:4,paddingTop:4},warning:{flexDirection:"row",gap:8,padding:e.cardPad,borderRadius:e.radius.card,borderWidth:i.hairlineWidth,borderColor:e.color.warning,backgroundColor:e.color.surface},warningText:{flex:1,color:e.color.warning,fontSize:e.font.micro,lineHeight:16},trustedBox:{gap:6,paddingTop:6},trustedRow:{flexDirection:"row",alignItems:"center",gap:10,padding:e.cardPad,borderRadius:e.radius.card,borderWidth:i.hairlineWidth,borderColor:e.color.border,backgroundColor:e.color.surface},trustedLabel:{flex:1,color:e.color.text,fontSize:e.font.caption,lineHeight:18},forget:{paddingHorizontal:10,paddingVertical:6,borderRadius:e.radius.row,backgroundColor:e.color.button},forgetText:{color:e.color.text,fontSize:e.font.micro,fontWeight:"600"},note:{color:e.color.textTertiary,fontSize:e.font.micro,lineHeight:16,paddingHorizontal:4}});
|