@buoy-gg/ask-buoy 7.0.33 → 7.0.34

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 (153) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/blocks/AskBlocks.js +1 -338
  3. package/lib/commonjs/blocks/BlockRenderer.js +1 -250
  4. package/lib/commonjs/blocks/ChromePrototypes.js +1 -514
  5. package/lib/commonjs/blocks/DataBlocks.js +1 -545
  6. package/lib/commonjs/blocks/ExtraBlocks.js +1 -1821
  7. package/lib/commonjs/blocks/MediaBlocks.js +1 -140
  8. package/lib/commonjs/blocks/ReceiptBlocks.js +1 -596
  9. package/lib/commonjs/blocks/context.js +1 -42
  10. package/lib/commonjs/blocks/icons.js +1 -96
  11. package/lib/commonjs/blocks/index.js +1 -95
  12. package/lib/commonjs/blocks/primitives.js +1 -312
  13. package/lib/commonjs/blocks/primitivesIndex.js +1 -56
  14. package/lib/commonjs/components/ApprovalCard.js +1 -140
  15. package/lib/commonjs/components/AskBuoyHeader.js +1 -127
  16. package/lib/commonjs/components/AskBuoyIcon.js +1 -19
  17. package/lib/commonjs/components/AskBuoyModal.js +1 -322
  18. package/lib/commonjs/components/ChangesBar.js +1 -211
  19. package/lib/commonjs/components/Composer.js +1 -175
  20. package/lib/commonjs/components/EmptyState.js +1 -154
  21. package/lib/commonjs/components/Markdown.js +1 -252
  22. package/lib/commonjs/components/MessageList.js +1 -648
  23. package/lib/commonjs/components/TypingDots.js +1 -63
  24. package/lib/commonjs/index.js +1 -205
  25. package/lib/commonjs/preset.js +1 -90
  26. package/lib/commonjs/store/askBuoyStore.js +1 -279
  27. package/lib/commonjs/store/useAskBuoy.js +1 -299
  28. package/lib/commonjs/sync/askBuoySyncAdapter.js +1 -119
  29. package/lib/commonjs/sync/askBuoySyncAdapter.test.js +1 -136
  30. package/lib/commonjs/sync/wire.js +1 -58
  31. package/lib/commonjs/types.js +1 -6
  32. package/lib/module/blocks/AskBlocks.js +1 -331
  33. package/lib/module/blocks/BlockRenderer.js +1 -245
  34. package/lib/module/blocks/ChromePrototypes.js +1 -503
  35. package/lib/module/blocks/DataBlocks.js +1 -532
  36. package/lib/module/blocks/ExtraBlocks.js +1 -1794
  37. package/lib/module/blocks/MediaBlocks.js +1 -135
  38. package/lib/module/blocks/ReceiptBlocks.js +1 -584
  39. package/lib/module/blocks/context.js +1 -35
  40. package/lib/module/blocks/icons.js +1 -91
  41. package/lib/module/blocks/index.js +1 -8
  42. package/lib/module/blocks/primitives.js +1 -301
  43. package/lib/module/blocks/primitivesIndex.js +1 -5
  44. package/lib/module/components/ApprovalCard.js +1 -135
  45. package/lib/module/components/AskBuoyHeader.js +1 -124
  46. package/lib/module/components/AskBuoyIcon.js +1 -8
  47. package/lib/module/components/AskBuoyModal.js +1 -317
  48. package/lib/module/components/ChangesBar.js +1 -206
  49. package/lib/module/components/Composer.js +1 -170
  50. package/lib/module/components/EmptyState.js +1 -149
  51. package/lib/module/components/Markdown.js +1 -246
  52. package/lib/module/components/MessageList.js +1 -642
  53. package/lib/module/components/TypingDots.js +1 -58
  54. package/lib/module/index.js +1 -29
  55. package/lib/module/preset.js +1 -73
  56. package/lib/module/store/askBuoyStore.js +1 -275
  57. package/lib/module/store/useAskBuoy.js +1 -293
  58. package/lib/module/sync/askBuoySyncAdapter.js +1 -114
  59. package/lib/module/sync/askBuoySyncAdapter.test.js +1 -135
  60. package/lib/module/sync/wire.js +1 -47
  61. package/lib/module/types.js +1 -4
  62. package/lib/typescript/preset.d.ts +1 -1
  63. package/package.json +8 -8
  64. package/lib/commonjs/blocks/AskBlocks.js.map +0 -1
  65. package/lib/commonjs/blocks/BlockRenderer.js.map +0 -1
  66. package/lib/commonjs/blocks/ChromePrototypes.js.map +0 -1
  67. package/lib/commonjs/blocks/DataBlocks.js.map +0 -1
  68. package/lib/commonjs/blocks/ExtraBlocks.js.map +0 -1
  69. package/lib/commonjs/blocks/MediaBlocks.js.map +0 -1
  70. package/lib/commonjs/blocks/ReceiptBlocks.js.map +0 -1
  71. package/lib/commonjs/blocks/context.js.map +0 -1
  72. package/lib/commonjs/blocks/icons.js.map +0 -1
  73. package/lib/commonjs/blocks/index.js.map +0 -1
  74. package/lib/commonjs/blocks/primitives.js.map +0 -1
  75. package/lib/commonjs/blocks/primitivesIndex.js.map +0 -1
  76. package/lib/commonjs/components/ApprovalCard.js.map +0 -1
  77. package/lib/commonjs/components/AskBuoyHeader.js.map +0 -1
  78. package/lib/commonjs/components/AskBuoyIcon.js.map +0 -1
  79. package/lib/commonjs/components/AskBuoyModal.js.map +0 -1
  80. package/lib/commonjs/components/ChangesBar.js.map +0 -1
  81. package/lib/commonjs/components/Composer.js.map +0 -1
  82. package/lib/commonjs/components/EmptyState.js.map +0 -1
  83. package/lib/commonjs/components/Markdown.js.map +0 -1
  84. package/lib/commonjs/components/MessageList.js.map +0 -1
  85. package/lib/commonjs/components/TypingDots.js.map +0 -1
  86. package/lib/commonjs/index.js.map +0 -1
  87. package/lib/commonjs/preset.js.map +0 -1
  88. package/lib/commonjs/store/askBuoyStore.js.map +0 -1
  89. package/lib/commonjs/store/useAskBuoy.js.map +0 -1
  90. package/lib/commonjs/sync/askBuoySyncAdapter.js.map +0 -1
  91. package/lib/commonjs/sync/askBuoySyncAdapter.test.js.map +0 -1
  92. package/lib/commonjs/sync/wire.js.map +0 -1
  93. package/lib/commonjs/types.js.map +0 -1
  94. package/lib/module/blocks/AskBlocks.js.map +0 -1
  95. package/lib/module/blocks/BlockRenderer.js.map +0 -1
  96. package/lib/module/blocks/ChromePrototypes.js.map +0 -1
  97. package/lib/module/blocks/DataBlocks.js.map +0 -1
  98. package/lib/module/blocks/ExtraBlocks.js.map +0 -1
  99. package/lib/module/blocks/MediaBlocks.js.map +0 -1
  100. package/lib/module/blocks/ReceiptBlocks.js.map +0 -1
  101. package/lib/module/blocks/context.js.map +0 -1
  102. package/lib/module/blocks/icons.js.map +0 -1
  103. package/lib/module/blocks/index.js.map +0 -1
  104. package/lib/module/blocks/primitives.js.map +0 -1
  105. package/lib/module/blocks/primitivesIndex.js.map +0 -1
  106. package/lib/module/components/ApprovalCard.js.map +0 -1
  107. package/lib/module/components/AskBuoyHeader.js.map +0 -1
  108. package/lib/module/components/AskBuoyIcon.js.map +0 -1
  109. package/lib/module/components/AskBuoyModal.js.map +0 -1
  110. package/lib/module/components/ChangesBar.js.map +0 -1
  111. package/lib/module/components/Composer.js.map +0 -1
  112. package/lib/module/components/EmptyState.js.map +0 -1
  113. package/lib/module/components/Markdown.js.map +0 -1
  114. package/lib/module/components/MessageList.js.map +0 -1
  115. package/lib/module/components/TypingDots.js.map +0 -1
  116. package/lib/module/index.js.map +0 -1
  117. package/lib/module/preset.js.map +0 -1
  118. package/lib/module/store/askBuoyStore.js.map +0 -1
  119. package/lib/module/store/useAskBuoy.js.map +0 -1
  120. package/lib/module/sync/askBuoySyncAdapter.js.map +0 -1
  121. package/lib/module/sync/askBuoySyncAdapter.test.js.map +0 -1
  122. package/lib/module/sync/wire.js.map +0 -1
  123. package/lib/module/types.js.map +0 -1
  124. package/lib/typescript/blocks/AskBlocks.d.ts.map +0 -1
  125. package/lib/typescript/blocks/BlockRenderer.d.ts.map +0 -1
  126. package/lib/typescript/blocks/ChromePrototypes.d.ts.map +0 -1
  127. package/lib/typescript/blocks/DataBlocks.d.ts.map +0 -1
  128. package/lib/typescript/blocks/ExtraBlocks.d.ts.map +0 -1
  129. package/lib/typescript/blocks/MediaBlocks.d.ts.map +0 -1
  130. package/lib/typescript/blocks/ReceiptBlocks.d.ts.map +0 -1
  131. package/lib/typescript/blocks/context.d.ts.map +0 -1
  132. package/lib/typescript/blocks/icons.d.ts.map +0 -1
  133. package/lib/typescript/blocks/index.d.ts.map +0 -1
  134. package/lib/typescript/blocks/primitives.d.ts.map +0 -1
  135. package/lib/typescript/blocks/primitivesIndex.d.ts.map +0 -1
  136. package/lib/typescript/components/ApprovalCard.d.ts.map +0 -1
  137. package/lib/typescript/components/AskBuoyHeader.d.ts.map +0 -1
  138. package/lib/typescript/components/AskBuoyIcon.d.ts.map +0 -1
  139. package/lib/typescript/components/AskBuoyModal.d.ts.map +0 -1
  140. package/lib/typescript/components/ChangesBar.d.ts.map +0 -1
  141. package/lib/typescript/components/Composer.d.ts.map +0 -1
  142. package/lib/typescript/components/EmptyState.d.ts.map +0 -1
  143. package/lib/typescript/components/Markdown.d.ts.map +0 -1
  144. package/lib/typescript/components/MessageList.d.ts.map +0 -1
  145. package/lib/typescript/components/TypingDots.d.ts.map +0 -1
  146. package/lib/typescript/index.d.ts.map +0 -1
  147. package/lib/typescript/preset.d.ts.map +0 -1
  148. package/lib/typescript/store/askBuoyStore.d.ts.map +0 -1
  149. package/lib/typescript/store/useAskBuoy.d.ts.map +0 -1
  150. package/lib/typescript/sync/askBuoySyncAdapter.d.ts.map +0 -1
  151. package/lib/typescript/sync/askBuoySyncAdapter.test.d.ts.map +0 -1
  152. package/lib/typescript/sync/wire.d.ts.map +0 -1
  153. package/lib/typescript/types.d.ts.map +0 -1
@@ -1,170 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * The message box.
5
- *
6
- * This is the first keyboard-safe BOTTOM input in Buoy, and the reason none
7
- * existed before is that JsModal has no keyboard handling at all: the sheet is
8
- * `position:absolute; bottom:0` inside the app tree, not an RN `Modal`, so on
9
- * iOS the keyboard simply draws over it. Two other tools hit this and chose to
10
- * dodge it — NetworkNumberPrompt and StorageValueEditModal both say so in
11
- * comments and pin their inputs to the TOP of the screen. A chat cannot.
12
- *
13
- * What makes it work:
14
- * - `KeyboardAvoidingView` with `behavior="padding"`, iOS only. On Android
15
- * Expo's default `softwareKeyboardLayoutMode: "resize"` shrinks the window
16
- * and a bottom-anchored view rides up for free; adding padding there would
17
- * lift it twice.
18
- * - The parent list carries `keyboardShouldPersistTaps="handled"`. Without it
19
- * the first tap after typing only dismisses the keyboard and Send never
20
- * fires — a real shipped bug in Time Machine, and invisible to Detox because
21
- * `replaceText` opens no keyboard.
22
- * - `keyboardType="ascii-capable"`, because iOS Smart Punctuation rewrites
23
- * straight quotes as curly ones. That permanently broke the raw-JSON editor
24
- * in Storage, and a tester pasting a JSON blob here would hit the same wall.
25
- *
26
- * While the agent is working the send button becomes a STOP button — a
27
- * square, the universal glyph — rather than a spinner in a circle, which
28
- * looked like a disabled control and gave no hint it was tappable.
29
- */
30
- import { useCallback, useState } from "react";
31
- import { Platform, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
32
- import { night } from "@buoy-gg/shared-ui";
33
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
34
- export function Composer({
35
- onSend,
36
- onStop,
37
- busy,
38
- disabled,
39
- placeholder
40
- }) {
41
- const [text, setText] = useState("");
42
- const submit = useCallback(() => {
43
- const value = text.trim();
44
- if (!value) return;
45
- setText("");
46
- onSend(value);
47
- }, [text, onSend]);
48
- const canSend = text.trim().length > 0 && !busy && !disabled;
49
- return /*#__PURE__*/_jsxs(View, {
50
- style: styles.wrap,
51
- children: [/*#__PURE__*/_jsx(View, {
52
- style: [styles.field, disabled && styles.fieldDisabled],
53
- children: /*#__PURE__*/_jsx(TextInput, {
54
- testID: "buoy-ask-buoy-input",
55
- style: styles.input,
56
- value: text,
57
- onChangeText: setText,
58
- placeholder: placeholder ?? (disabled ? "Ask Buoy isn't set up yet" : "Ask, or tell it what to change…"),
59
- placeholderTextColor: night.color.placeholder,
60
- multiline: true,
61
- editable: !disabled
62
- // Straight quotes only — see the header note.
63
- ,
64
- keyboardType: "ascii-capable",
65
- autoCorrect: true,
66
- autoCapitalize: "sentences"
67
- // Enter sends; Shift-Enter is not a thing on a phone keyboard, and a
68
- // multiline box with no submit affordance strands people.
69
- ,
70
- blurOnSubmit: false,
71
- onSubmitEditing: submit,
72
- returnKeyType: "send",
73
- maxLength: 4000
74
- })
75
- }), busy ? /*#__PURE__*/_jsx(Pressable, {
76
- testID: "buoy-ask-buoy-stop",
77
- accessibilityRole: "button",
78
- accessibilityLabel: "Stop",
79
- onPress: onStop,
80
- style: ({
81
- pressed
82
- }) => [styles.button, styles.stop, pressed && styles.pressed],
83
- children: /*#__PURE__*/_jsx(View, {
84
- style: styles.stopGlyph
85
- })
86
- }) : /*#__PURE__*/_jsx(Pressable, {
87
- testID: "buoy-ask-buoy-send",
88
- accessibilityRole: "button",
89
- accessibilityLabel: "Send",
90
- disabled: !canSend,
91
- onPress: submit,
92
- style: ({
93
- pressed
94
- }) => [styles.button, canSend ? styles.sendOn : styles.sendOff, pressed && canSend && styles.pressed],
95
- children: /*#__PURE__*/_jsx(Text, {
96
- style: [styles.sendGlyph, {
97
- color: canSend ? night.color.onAccent : night.color.textTertiary
98
- }],
99
- children: "\u2191"
100
- })
101
- })]
102
- });
103
- }
104
- const styles = StyleSheet.create({
105
- wrap: {
106
- flexDirection: "row",
107
- alignItems: "flex-end",
108
- gap: 8,
109
- paddingHorizontal: night.gutter,
110
- paddingTop: 10,
111
- paddingBottom: 6,
112
- borderTopWidth: StyleSheet.hairlineWidth,
113
- borderTopColor: night.color.border,
114
- // Opaque: messages scroll UNDER the composer, and a translucent bar over
115
- // moving text is unreadable.
116
- backgroundColor: night.color.bg
117
- },
118
- field: {
119
- flex: 1,
120
- minHeight: 40,
121
- justifyContent: "center",
122
- borderRadius: 20,
123
- borderWidth: StyleSheet.hairlineWidth,
124
- borderColor: night.color.border,
125
- backgroundColor: night.color.surfaceElevated
126
- },
127
- fieldDisabled: {
128
- opacity: 0.6
129
- },
130
- input: {
131
- maxHeight: 120,
132
- paddingHorizontal: 16,
133
- paddingTop: Platform.OS === "ios" ? 10 : 6,
134
- paddingBottom: Platform.OS === "ios" ? 10 : 6,
135
- color: night.color.text,
136
- fontSize: night.font.row,
137
- lineHeight: 20
138
- },
139
- button: {
140
- width: 40,
141
- height: 40,
142
- borderRadius: 20,
143
- alignItems: "center",
144
- justifyContent: "center"
145
- },
146
- sendGlyph: {
147
- fontSize: 20,
148
- fontWeight: "700",
149
- lineHeight: 22
150
- },
151
- sendOn: {
152
- backgroundColor: night.color.accent
153
- },
154
- sendOff: {
155
- backgroundColor: night.color.fill
156
- },
157
- stop: {
158
- backgroundColor: night.color.fillTertiary
159
- },
160
- stopGlyph: {
161
- width: 12,
162
- height: 12,
163
- borderRadius: 2,
164
- backgroundColor: night.color.text
165
- },
166
- pressed: {
167
- opacity: 0.7
168
- }
169
- });
170
- //# sourceMappingURL=Composer.js.map
1
+ "use strict";import{useCallback,useState}from"react";import{Platform,Pressable,StyleSheet,Text,TextInput,View}from"react-native";import{night}from"@buoy-gg/shared-ui";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export function Composer({onSend:e,onStop:t,busy:o,disabled:s,placeholder:i}){const[l,r]=useState(""),n=useCallback(()=>{const t=l.trim();t&&(r(""),e(t))},[l,e]),a=l.trim().length>0&&!o&&!s;return _jsxs(View,{style:styles.wrap,children:[_jsx(View,{style:[styles.field,s&&styles.fieldDisabled],children:_jsx(TextInput,{testID:"buoy-ask-buoy-input",style:styles.input,value:l,onChangeText:r,placeholder:i??(s?"Ask Buoy isn't set up yet":"Ask, or tell it what to change…"),placeholderTextColor:night.color.placeholder,multiline:!0,editable:!s,keyboardType:"ascii-capable",autoCorrect:!0,autoCapitalize:"sentences",blurOnSubmit:!1,onSubmitEditing:n,returnKeyType:"send",maxLength:4e3})}),_jsx(Pressable,o?{testID:"buoy-ask-buoy-stop",accessibilityRole:"button",accessibilityLabel:"Stop",onPress:t,style:({pressed:e})=>[styles.button,styles.stop,e&&styles.pressed],children:_jsx(View,{style:styles.stopGlyph})}:{testID:"buoy-ask-buoy-send",accessibilityRole:"button",accessibilityLabel:"Send",disabled:!a,onPress:n,style:({pressed:e})=>[styles.button,a?styles.sendOn:styles.sendOff,e&&a&&styles.pressed],children:_jsx(Text,{style:[styles.sendGlyph,{color:a?night.color.onAccent:night.color.textTertiary}],children:"↑"})})]})}const styles=StyleSheet.create({wrap:{flexDirection:"row",alignItems:"flex-end",gap:8,paddingHorizontal:night.gutter,paddingTop:10,paddingBottom:6,borderTopWidth:StyleSheet.hairlineWidth,borderTopColor:night.color.border,backgroundColor:night.color.bg},field:{flex:1,minHeight:40,justifyContent:"center",borderRadius:20,borderWidth:StyleSheet.hairlineWidth,borderColor:night.color.border,backgroundColor:night.color.surfaceElevated},fieldDisabled:{opacity:.6},input:{maxHeight:120,paddingHorizontal:16,paddingTop:"ios"===Platform.OS?10:6,paddingBottom:"ios"===Platform.OS?10:6,color:night.color.text,fontSize:night.font.row,lineHeight:20},button:{width:40,height:40,borderRadius:20,alignItems:"center",justifyContent:"center"},sendGlyph:{fontSize:20,fontWeight:"700",lineHeight:22},sendOn:{backgroundColor:night.color.accent},sendOff:{backgroundColor:night.color.fill},stop:{backgroundColor:night.color.fillTertiary},stopGlyph:{width:12,height:12,borderRadius:2,backgroundColor:night.color.text},pressed:{opacity:.7}});
@@ -1,149 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * The first screen.
5
- *
6
- * Written for someone who has never used a devtool. The suggestions are not
7
- * decoration — they are the fastest way to teach a tester what kind of sentence
8
- * works here, and they are phrased as outcomes ("why is this screen empty?")
9
- * rather than as tool names, because the tools are the thing this feature
10
- * exists to hide.
11
- */
12
- import { Pressable, StyleSheet, Text, View } from "react-native";
13
- import { ChevronRight, night, NightSectionLabel } from "@buoy-gg/shared-ui";
14
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
- const isRelease = typeof __DEV__ !== "undefined" && !__DEV__;
16
- const SUGGESTIONS = ["Why is this screen empty?", "What did the last few network calls return?", "Show me what's saved for this user", "Make the next request to this screen fail with a 500"];
17
- export function EmptyState({
18
- configured,
19
- onPick
20
- }) {
21
- if (!configured) {
22
- return /*#__PURE__*/_jsxs(View, {
23
- style: styles.wrap,
24
- testID: "buoy-ask-buoy-unconfigured",
25
- children: [/*#__PURE__*/_jsx(Text, {
26
- style: styles.title,
27
- children: "Not set up yet"
28
- }), /*#__PURE__*/_jsxs(Text, {
29
- style: styles.body,
30
- children: ["Ask Buoy talks to your own company's AI endpoint \u2014 nothing goes to Buoy. A developer needs to add the ", /*#__PURE__*/_jsx(Text, {
31
- style: styles.code,
32
- children: "askBuoy"
33
- }), " prop to", " ", /*#__PURE__*/_jsx(Text, {
34
- style: styles.code,
35
- children: "<FloatingDevTools />"
36
- }), " with your team's endpoint and model."]
37
- })]
38
- });
39
- }
40
- return /*#__PURE__*/_jsxs(View, {
41
- style: styles.wrap,
42
- testID: "buoy-ask-buoy-empty",
43
- children: [/*#__PURE__*/_jsx(Text, {
44
- style: styles.title,
45
- children: "Ask about this app"
46
- }), /*#__PURE__*/_jsx(Text, {
47
- style: styles.body,
48
- children: "Ask what the app is doing right now, or tell it to change something. Anything it changes shows up in a bar at the top, and you can undo it."
49
- }), /*#__PURE__*/_jsx(Text, {
50
- style: styles.buildLine,
51
- testID: "buoy-ask-buoy-build-line",
52
- children: isRelease ? "Release build — reading, impersonation and navigation work; simulations (forcing server responses, driving the screen) need a dev build." : "Dev build — full simulation available."
53
- }), /*#__PURE__*/_jsxs(View, {
54
- style: styles.group,
55
- children: [/*#__PURE__*/_jsx(NightSectionLabel, {
56
- children: "Try asking"
57
- }), /*#__PURE__*/_jsx(View, {
58
- style: styles.card,
59
- children: SUGGESTIONS.map((s, i) => /*#__PURE__*/_jsx(Suggestion, {
60
- text: s,
61
- onPick: onPick,
62
- last: i === SUGGESTIONS.length - 1
63
- }, s))
64
- })]
65
- })]
66
- });
67
- }
68
- function Suggestion({
69
- text,
70
- onPick,
71
- last
72
- }) {
73
- return /*#__PURE__*/_jsxs(Pressable, {
74
- testID: `buoy-ask-buoy-suggestion-${text.slice(0, 12)}`,
75
- accessibilityRole: "button",
76
- onPress: () => onPick(text),
77
- style: ({
78
- pressed
79
- }) => [styles.row, !last && styles.rowDivider, pressed && styles.pressed],
80
- children: [/*#__PURE__*/_jsx(Text, {
81
- style: styles.rowText,
82
- children: text
83
- }), /*#__PURE__*/_jsx(ChevronRight, {
84
- size: 14,
85
- color: night.color.textTertiary
86
- })]
87
- });
88
- }
89
- const styles = StyleSheet.create({
90
- wrap: {
91
- flex: 1,
92
- justifyContent: "center",
93
- paddingHorizontal: night.gutter,
94
- paddingVertical: 24,
95
- gap: 8
96
- },
97
- title: {
98
- color: night.color.text,
99
- fontSize: 22,
100
- fontWeight: "700",
101
- letterSpacing: -0.3
102
- },
103
- body: {
104
- color: night.color.textSecondary,
105
- fontSize: night.font.body,
106
- lineHeight: 20
107
- },
108
- code: {
109
- color: night.color.text,
110
- fontFamily: "Menlo"
111
- },
112
- buildLine: {
113
- marginTop: 8,
114
- color: night.color.textTertiary,
115
- fontSize: night.font.micro,
116
- lineHeight: 15
117
- },
118
- group: {
119
- marginTop: night.groupGap - 8
120
- },
121
- card: {
122
- borderRadius: night.radius.card,
123
- borderWidth: StyleSheet.hairlineWidth,
124
- borderColor: night.color.border,
125
- backgroundColor: night.color.surface,
126
- overflow: "hidden"
127
- },
128
- row: {
129
- flexDirection: "row",
130
- alignItems: "center",
131
- gap: 10,
132
- paddingHorizontal: night.rowPadH,
133
- paddingVertical: 13
134
- },
135
- rowDivider: {
136
- borderBottomWidth: StyleSheet.hairlineWidth,
137
- borderBottomColor: night.color.separator
138
- },
139
- rowText: {
140
- flex: 1,
141
- color: night.color.text,
142
- fontSize: night.font.body,
143
- lineHeight: 19
144
- },
145
- pressed: {
146
- backgroundColor: night.color.fill
147
- }
148
- });
149
- //# sourceMappingURL=EmptyState.js.map
1
+ "use strict";import{Pressable,StyleSheet,Text,View}from"react-native";import{ChevronRight,night,NightSectionLabel}from"@buoy-gg/shared-ui";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const isRelease="undefined"!=typeof __DEV__&&!__DEV__,SUGGESTIONS=["Why is this screen empty?","What did the last few network calls return?","Show me what's saved for this user","Make the next request to this screen fail with a 500"];export function EmptyState({configured:e,onPick:t}){return _jsxs(View,e?{style:styles.wrap,testID:"buoy-ask-buoy-empty",children:[_jsx(Text,{style:styles.title,children:"Ask about this app"}),_jsx(Text,{style:styles.body,children:"Ask what the app is doing right now, or tell it to change something. Anything it changes shows up in a bar at the top, and you can undo it."}),_jsx(Text,{style:styles.buildLine,testID:"buoy-ask-buoy-build-line",children:isRelease?"Release build — reading, impersonation and navigation work; simulations (forcing server responses, driving the screen) need a dev build.":"Dev build — full simulation available."}),_jsxs(View,{style:styles.group,children:[_jsx(NightSectionLabel,{children:"Try asking"}),_jsx(View,{style:styles.card,children:SUGGESTIONS.map((e,o)=>_jsx(Suggestion,{text:e,onPick:t,last:o===SUGGESTIONS.length-1},e))})]})]}:{style:styles.wrap,testID:"buoy-ask-buoy-unconfigured",children:[_jsx(Text,{style:styles.title,children:"Not set up yet"}),_jsxs(Text,{style:styles.body,children:["Ask Buoy talks to your own company's AI endpoint — nothing goes to Buoy. A developer needs to add the ",_jsx(Text,{style:styles.code,children:"askBuoy"})," prop to"," ",_jsx(Text,{style:styles.code,children:"<FloatingDevTools />"})," with your team's endpoint and model."]})]})}function Suggestion({text:e,onPick:t,last:o}){return _jsxs(Pressable,{testID:`buoy-ask-buoy-suggestion-${e.slice(0,12)}`,accessibilityRole:"button",onPress:()=>t(e),style:({pressed:e})=>[styles.row,!o&&styles.rowDivider,e&&styles.pressed],children:[_jsx(Text,{style:styles.rowText,children:e}),_jsx(ChevronRight,{size:14,color:night.color.textTertiary})]})}const styles=StyleSheet.create({wrap:{flex:1,justifyContent:"center",paddingHorizontal:night.gutter,paddingVertical:24,gap:8},title:{color:night.color.text,fontSize:22,fontWeight:"700",letterSpacing:-.3},body:{color:night.color.textSecondary,fontSize:night.font.body,lineHeight:20},code:{color:night.color.text,fontFamily:"Menlo"},buildLine:{marginTop:8,color:night.color.textTertiary,fontSize:night.font.micro,lineHeight:15},group:{marginTop:night.groupGap-8},card:{borderRadius:night.radius.card,borderWidth:StyleSheet.hairlineWidth,borderColor:night.color.border,backgroundColor:night.color.surface,overflow:"hidden"},row:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:night.rowPadH,paddingVertical:13},rowDivider:{borderBottomWidth:StyleSheet.hairlineWidth,borderBottomColor:night.color.separator},rowText:{flex:1,color:night.color.text,fontSize:night.font.body,lineHeight:19},pressed:{backgroundColor:night.color.fill}});
@@ -1,246 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Just enough Markdown for a chat answer.
5
- *
6
- * Models write `**bold**`, bullet lists and `code` whether or not the prompt
7
- * asks for prose, and the asterisks rendered raw made every answer look like
8
- * a broken template. This handles the subset a chat actually receives —
9
- * paragraphs, `-`/`*`/`1.` lists, `#` headings (rendered bold, not huge),
10
- * bold, italics and inline code — with no dependency and no HTML. Anything it
11
- * does not understand falls through as plain text, never as a blank.
12
- */
13
- import { StyleSheet, Text, View } from "react-native";
14
- import { night } from "@buoy-gg/shared-ui";
15
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
- const isTableRow = l => /^\s*\|.*\|\s*$/.test(l);
17
- const isTableRule = l => /^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)*\|?\s*$/.test(l);
18
- const splitRow = l => l.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map(c => c.trim());
19
- function parseBlocks(source) {
20
- const blocks = [];
21
- let para = [];
22
- const flush = () => {
23
- if (para.length) blocks.push({
24
- kind: "p",
25
- text: para.join(" ")
26
- });
27
- para = [];
28
- };
29
- const lines = source.split("\n");
30
- for (let li = 0; li < lines.length; li++) {
31
- const raw = lines[li];
32
- const line = raw.replace(/\s+$/, "");
33
- if (!line.trim()) {
34
- flush();
35
- continue;
36
- }
37
- // A pipe table: header row, a rule row, then body rows.
38
- if (isTableRow(line) && lines[li + 1] && isTableRule(lines[li + 1])) {
39
- flush();
40
- const header = splitRow(line);
41
- const rows = [];
42
- let j = li + 2;
43
- while (j < lines.length && isTableRow(lines[j])) {
44
- rows.push(splitRow(lines[j]));
45
- j++;
46
- }
47
- blocks.push({
48
- kind: "table",
49
- header,
50
- rows
51
- });
52
- li = j - 1;
53
- continue;
54
- }
55
- const heading = /^#{1,6}\s+(.*)$/.exec(line);
56
- if (heading) {
57
- flush();
58
- blocks.push({
59
- kind: "h",
60
- text: heading[1]
61
- });
62
- continue;
63
- }
64
- const bullet = /^(\s*)([-*•]|\d+[.)])\s+(.*)$/.exec(line);
65
- if (bullet) {
66
- flush();
67
- const depth = Math.min(2, Math.floor(bullet[1].length / 2));
68
- const marker = /^\d/.test(bullet[2]) ? bullet[2].replace(")", ".") : "•";
69
- blocks.push({
70
- kind: "li",
71
- text: bullet[3],
72
- marker,
73
- depth
74
- });
75
- continue;
76
- }
77
- para.push(line.trim());
78
- }
79
- flush();
80
- return blocks;
81
- }
82
-
83
- /**
84
- * `**bold**`, `*italic*` / `_italic_`, `` `code` `` → styled spans. Links and
85
- * images collapse to their text: a phone chat has nowhere to open a URL, and
86
- * `![Snorlax](https://raw.githubusercontent.com/…/143.png)` printed raw is
87
- * three lines of noise for one word of meaning.
88
- */
89
- export function renderInline(source, base) {
90
- const text = source.replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1");
91
- const out = [];
92
- const re = /(\*\*[^*]+\*\*|`[^`]+`|\*[^*\s][^*]*\*|_[^_\s][^_]*_)/g;
93
- let last = 0;
94
- let m;
95
- let i = 0;
96
- while (m = re.exec(text)) {
97
- if (m.index > last) out.push(text.slice(last, m.index));
98
- const tok = m[0];
99
- if (tok.startsWith("**")) {
100
- out.push(/*#__PURE__*/_jsx(Text, {
101
- style: [base, styles.bold],
102
- children: tok.slice(2, -2)
103
- }, i++));
104
- } else if (tok.startsWith("`")) {
105
- out.push(/*#__PURE__*/_jsx(Text, {
106
- style: [base, styles.code],
107
- children: tok.slice(1, -1)
108
- }, i++));
109
- } else {
110
- out.push(/*#__PURE__*/_jsx(Text, {
111
- style: [base, styles.italic],
112
- children: tok.slice(1, -1)
113
- }, i++));
114
- }
115
- last = m.index + tok.length;
116
- }
117
- if (last < text.length) out.push(text.slice(last));
118
- return out;
119
- }
120
- export function Markdown({
121
- text,
122
- style
123
- }) {
124
- const blocks = parseBlocks(text);
125
- return /*#__PURE__*/_jsx(View, {
126
- style: styles.wrap,
127
- children: blocks.map((b, i) => {
128
- if (b.kind === "table") {
129
- const cols = b.header.slice(0, 4);
130
- return /*#__PURE__*/_jsxs(View, {
131
- style: styles.table,
132
- children: [/*#__PURE__*/_jsx(View, {
133
- style: styles.tableHead,
134
- children: cols.map((c, k) => /*#__PURE__*/_jsx(Text, {
135
- style: [styles.th, k === 0 && styles.firstCol],
136
- numberOfLines: 1,
137
- children: c.replace(/\*\*/g, "")
138
- }, k))
139
- }), b.rows.slice(0, 12).map((r, ri) => /*#__PURE__*/_jsx(View, {
140
- style: [styles.tr, ri > 0 && styles.trDivider],
141
- children: cols.map((_, k) => /*#__PURE__*/_jsx(Text, {
142
- style: [styles.td, k === 0 && styles.firstCol, k === 0 && styles.tdFirst],
143
- numberOfLines: 2,
144
- children: renderInline((r[k] ?? "").replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1"), styles.td)
145
- }, k))
146
- }, ri))]
147
- }, i);
148
- }
149
- if (b.kind === "li") {
150
- return /*#__PURE__*/_jsxs(View, {
151
- style: [styles.li, {
152
- paddingLeft: 4 + b.depth * 14
153
- }],
154
- children: [/*#__PURE__*/_jsx(Text, {
155
- style: [style, styles.marker],
156
- children: b.marker
157
- }), /*#__PURE__*/_jsx(Text, {
158
- style: [style, styles.liText],
159
- selectable: true,
160
- children: renderInline(b.text, style)
161
- })]
162
- }, i);
163
- }
164
- return /*#__PURE__*/_jsx(Text, {
165
- style: [style, b.kind === "h" && styles.bold],
166
- selectable: true,
167
- children: renderInline(b.text, style)
168
- }, i);
169
- })
170
- });
171
- }
172
- const styles = StyleSheet.create({
173
- wrap: {
174
- gap: 8
175
- },
176
- bold: {
177
- fontWeight: "600"
178
- },
179
- italic: {
180
- fontStyle: "italic"
181
- },
182
- code: {
183
- fontFamily: "Menlo",
184
- fontSize: 13,
185
- color: night.color.accent,
186
- backgroundColor: night.color.fill
187
- },
188
- li: {
189
- flexDirection: "row",
190
- gap: 8
191
- },
192
- table: {
193
- borderRadius: night.radius.row,
194
- borderWidth: StyleSheet.hairlineWidth,
195
- borderColor: night.color.border,
196
- backgroundColor: night.color.surface,
197
- overflow: "hidden"
198
- },
199
- tableHead: {
200
- flexDirection: "row",
201
- paddingHorizontal: 10,
202
- paddingVertical: 6,
203
- gap: 8,
204
- backgroundColor: night.color.fill
205
- },
206
- th: {
207
- flex: 1,
208
- color: night.color.textTertiary,
209
- fontSize: night.font.micro,
210
- fontWeight: "700",
211
- letterSpacing: 0.6,
212
- textTransform: "uppercase"
213
- },
214
- tr: {
215
- flexDirection: "row",
216
- paddingHorizontal: 10,
217
- paddingVertical: 7,
218
- gap: 8
219
- },
220
- trDivider: {
221
- borderTopWidth: StyleSheet.hairlineWidth,
222
- borderTopColor: night.color.separator
223
- },
224
- td: {
225
- flex: 1,
226
- color: night.color.textSecondary,
227
- fontSize: night.font.caption,
228
- lineHeight: 17
229
- },
230
- tdFirst: {
231
- color: night.color.text,
232
- fontWeight: "500"
233
- },
234
- firstCol: {
235
- flex: 1.3
236
- },
237
- marker: {
238
- color: night.color.textSecondary,
239
- minWidth: 14,
240
- textAlign: "right"
241
- },
242
- liText: {
243
- flex: 1
244
- }
245
- });
246
- //# sourceMappingURL=Markdown.js.map
1
+ "use strict";import{StyleSheet,Text,View}from"react-native";import{night}from"@buoy-gg/shared-ui";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const isTableRow=e=>/^\s*\|.*\|\s*$/.test(e),isTableRule=e=>/^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)*\|?\s*$/.test(e),splitRow=e=>e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(e=>e.trim());function parseBlocks(e){const t=[];let l=[];const s=()=>{l.length&&t.push({kind:"p",text:l.join(" ")}),l=[]},i=e.split("\n");for(let e=0;e<i.length;e++){const r=i[e].replace(/\s+$/,"");if(!r.trim()){s();continue}if(isTableRow(r)&&i[e+1]&&isTableRule(i[e+1])){s();const l=splitRow(r),o=[];let n=e+2;for(;n<i.length&&isTableRow(i[n]);)o.push(splitRow(i[n])),n++;t.push({kind:"table",header:l,rows:o}),e=n-1;continue}const o=/^#{1,6}\s+(.*)$/.exec(r);if(o){s(),t.push({kind:"h",text:o[1]});continue}const n=/^(\s*)([-*•]|\d+[.)])\s+(.*)$/.exec(r);if(n){s();const e=Math.min(2,Math.floor(n[1].length/2)),l=/^\d/.test(n[2])?n[2].replace(")","."):"•";t.push({kind:"li",text:n[3],marker:l,depth:e});continue}l.push(r.trim())}return s(),t}export function renderInline(e,t){const l=e.replace(/!?\[([^\]]*)\]\([^)]*\)/g,"$1"),s=[],i=/(\*\*[^*]+\*\*|`[^`]+`|\*[^*\s][^*]*\*|_[^_\s][^_]*_)/g;let r,o=0,n=0;for(;r=i.exec(l);){r.index>o&&s.push(l.slice(o,r.index));const e=r[0];e.startsWith("**")?s.push(_jsx(Text,{style:[t,styles.bold],children:e.slice(2,-2)},n++)):e.startsWith("`")?s.push(_jsx(Text,{style:[t,styles.code],children:e.slice(1,-1)},n++)):s.push(_jsx(Text,{style:[t,styles.italic],children:e.slice(1,-1)},n++)),o=r.index+e.length}return o<l.length&&s.push(l.slice(o)),s}export function Markdown({text:e,style:t}){const l=parseBlocks(e);return _jsx(View,{style:styles.wrap,children:l.map((e,l)=>{if("table"===e.kind){const t=e.header.slice(0,4);return _jsxs(View,{style:styles.table,children:[_jsx(View,{style:styles.tableHead,children:t.map((e,t)=>_jsx(Text,{style:[styles.th,0===t&&styles.firstCol],numberOfLines:1,children:e.replace(/\*\*/g,"")},t))}),e.rows.slice(0,12).map((e,l)=>_jsx(View,{style:[styles.tr,l>0&&styles.trDivider],children:t.map((t,l)=>_jsx(Text,{style:[styles.td,0===l&&styles.firstCol,0===l&&styles.tdFirst],numberOfLines:2,children:renderInline((e[l]??"").replace(/!?\[([^\]]*)\]\([^)]*\)/g,"$1"),styles.td)},l))},l))]},l)}return"li"===e.kind?_jsxs(View,{style:[styles.li,{paddingLeft:4+14*e.depth}],children:[_jsx(Text,{style:[t,styles.marker],children:e.marker}),_jsx(Text,{style:[t,styles.liText],selectable:!0,children:renderInline(e.text,t)})]},l):_jsx(Text,{style:[t,"h"===e.kind&&styles.bold],selectable:!0,children:renderInline(e.text,t)},l)})})}const styles=StyleSheet.create({wrap:{gap:8},bold:{fontWeight:"600"},italic:{fontStyle:"italic"},code:{fontFamily:"Menlo",fontSize:13,color:night.color.accent,backgroundColor:night.color.fill},li:{flexDirection:"row",gap:8},table:{borderRadius:night.radius.row,borderWidth:StyleSheet.hairlineWidth,borderColor:night.color.border,backgroundColor:night.color.surface,overflow:"hidden"},tableHead:{flexDirection:"row",paddingHorizontal:10,paddingVertical:6,gap:8,backgroundColor:night.color.fill},th:{flex:1,color:night.color.textTertiary,fontSize:night.font.micro,fontWeight:"700",letterSpacing:.6,textTransform:"uppercase"},tr:{flexDirection:"row",paddingHorizontal:10,paddingVertical:7,gap:8},trDivider:{borderTopWidth:StyleSheet.hairlineWidth,borderTopColor:night.color.separator},td:{flex:1,color:night.color.textSecondary,fontSize:night.font.caption,lineHeight:17},tdFirst:{color:night.color.text,fontWeight:"500"},firstCol:{flex:1.3},marker:{color:night.color.textSecondary,minWidth:14,textAlign:"right"},liText:{flex:1}});