@buoy-gg/agent-core 7.0.40 → 7.0.42

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 (202) hide show
  1. package/lib/commonjs/blocks/receipts.js +1 -761
  2. package/lib/commonjs/blocks/runId.js +1 -31
  3. package/lib/commonjs/blocks/types.js +1 -140
  4. package/lib/commonjs/blocks/uiTool.js +6 -1405
  5. package/lib/commonjs/catalog/catalog.g.js +5 -4207
  6. package/lib/commonjs/catalog/catalog.source.json +656 -12
  7. package/lib/commonjs/catalog/catalog.types.g.js +1 -44
  8. package/lib/commonjs/catalog/normalizeParams.js +2 -332
  9. package/lib/commonjs/catalog/signature.js +1 -68
  10. package/lib/commonjs/catalog/snapshotReads.js +1 -263
  11. package/lib/commonjs/catalog/toProviderTools.js +2 -145
  12. package/lib/commonjs/catalog/validateParams.js +1 -129
  13. package/lib/commonjs/context/buildContextPack.js +1 -489
  14. package/lib/commonjs/effects/digest.js +1 -34
  15. package/lib/commonjs/effects/ledger.js +1 -325
  16. package/lib/commonjs/engine/askGate.js +1 -287
  17. package/lib/commonjs/engine/effectFor.js +1 -176
  18. package/lib/commonjs/engine/evidence.js +3 -111
  19. package/lib/commonjs/engine/historyBudget.js +1 -363
  20. package/lib/commonjs/engine/retrieve.js +1 -214
  21. package/lib/commonjs/engine/runAgentTurn.js +8 -1803
  22. package/lib/commonjs/engine/systemPrompt.js +54 -163
  23. package/lib/commonjs/engine/textToolCalls.js +1 -276
  24. package/lib/commonjs/engine/tokenCalibration.js +1 -81
  25. package/lib/commonjs/engine/verify.js +4 -297
  26. package/lib/commonjs/index.js +1 -384
  27. package/lib/commonjs/policy/labels.js +1 -319
  28. package/lib/commonjs/policy/policy.js +1 -148
  29. package/lib/commonjs/policy/redact.js +1 -172
  30. package/lib/commonjs/providers/anthropic.js +3 -445
  31. package/lib/commonjs/providers/openai.js +4 -324
  32. package/lib/commonjs/providers/problem.js +1 -98
  33. package/lib/commonjs/providers/sse.js +1 -240
  34. package/lib/commonjs/providers/streamTimer.js +1 -123
  35. package/lib/commonjs/providers/transport.js +1 -123
  36. package/lib/commonjs/providers/types.js +1 -6
  37. package/lib/commonjs/providers/xhrStream.js +1 -212
  38. package/lib/commonjs/realNow.js +1 -0
  39. package/lib/commonjs/session.js +1 -393
  40. package/lib/commonjs/types.js +0 -1
  41. package/lib/module/blocks/receipts.js +1 -755
  42. package/lib/module/blocks/runId.js +1 -26
  43. package/lib/module/blocks/types.js +1 -134
  44. package/lib/module/blocks/uiTool.js +6 -1396
  45. package/lib/module/catalog/catalog.g.js +5 -4203
  46. package/lib/module/catalog/catalog.source.json +656 -12
  47. package/lib/module/catalog/catalog.types.g.js +1 -40
  48. package/lib/module/catalog/normalizeParams.js +2 -326
  49. package/lib/module/catalog/signature.js +1 -63
  50. package/lib/module/catalog/snapshotReads.js +1 -259
  51. package/lib/module/catalog/toProviderTools.js +2 -139
  52. package/lib/module/catalog/validateParams.js +1 -124
  53. package/lib/module/context/buildContextPack.js +1 -485
  54. package/lib/module/effects/digest.js +1 -29
  55. package/lib/module/effects/ledger.js +1 -319
  56. package/lib/module/engine/askGate.js +1 -280
  57. package/lib/module/engine/effectFor.js +1 -173
  58. package/lib/module/engine/evidence.js +3 -105
  59. package/lib/module/engine/historyBudget.js +1 -355
  60. package/lib/module/engine/retrieve.js +1 -210
  61. package/lib/module/engine/runAgentTurn.js +8 -1794
  62. package/lib/module/engine/systemPrompt.js +54 -157
  63. package/lib/module/engine/textToolCalls.js +1 -270
  64. package/lib/module/engine/tokenCalibration.js +1 -75
  65. package/lib/module/engine/verify.js +4 -289
  66. package/lib/module/index.js +1 -35
  67. package/lib/module/policy/labels.js +1 -312
  68. package/lib/module/policy/policy.js +1 -142
  69. package/lib/module/policy/redact.js +1 -165
  70. package/lib/module/providers/anthropic.js +3 -441
  71. package/lib/module/providers/openai.js +4 -320
  72. package/lib/module/providers/problem.js +1 -92
  73. package/lib/module/providers/sse.js +1 -231
  74. package/lib/module/providers/streamTimer.js +1 -118
  75. package/lib/module/providers/transport.js +1 -119
  76. package/lib/module/providers/types.js +1 -4
  77. package/lib/module/providers/xhrStream.js +1 -207
  78. package/lib/module/realNow.js +1 -0
  79. package/lib/module/session.js +1 -369
  80. package/lib/module/types.js +0 -1
  81. package/lib/typescript/catalog/catalog.g.d.ts +3 -3
  82. package/lib/typescript/catalog/catalog.types.g.d.ts +7 -4
  83. package/lib/typescript/effects/ledger.d.ts +16 -1
  84. package/lib/typescript/providers/problem.d.ts +0 -20
  85. package/lib/typescript/providers/streamTimer.d.ts +0 -24
  86. package/lib/typescript/realNow.d.ts +18 -0
  87. package/lib/web/index.mjs +152 -0
  88. package/package.json +24 -3
  89. package/lib/commonjs/blocks/receipts.js.map +0 -1
  90. package/lib/commonjs/blocks/runId.js.map +0 -1
  91. package/lib/commonjs/blocks/types.js.map +0 -1
  92. package/lib/commonjs/blocks/uiTool.js.map +0 -1
  93. package/lib/commonjs/catalog/catalog.g.js.map +0 -1
  94. package/lib/commonjs/catalog/catalog.types.g.js.map +0 -1
  95. package/lib/commonjs/catalog/normalizeParams.js.map +0 -1
  96. package/lib/commonjs/catalog/signature.js.map +0 -1
  97. package/lib/commonjs/catalog/snapshotReads.js.map +0 -1
  98. package/lib/commonjs/catalog/toProviderTools.js.map +0 -1
  99. package/lib/commonjs/catalog/validateParams.js.map +0 -1
  100. package/lib/commonjs/context/buildContextPack.js.map +0 -1
  101. package/lib/commonjs/effects/digest.js.map +0 -1
  102. package/lib/commonjs/effects/ledger.js.map +0 -1
  103. package/lib/commonjs/engine/askGate.js.map +0 -1
  104. package/lib/commonjs/engine/effectFor.js.map +0 -1
  105. package/lib/commonjs/engine/evidence.js.map +0 -1
  106. package/lib/commonjs/engine/historyBudget.js.map +0 -1
  107. package/lib/commonjs/engine/retrieve.js.map +0 -1
  108. package/lib/commonjs/engine/runAgentTurn.js.map +0 -1
  109. package/lib/commonjs/engine/systemPrompt.js.map +0 -1
  110. package/lib/commonjs/engine/textToolCalls.js.map +0 -1
  111. package/lib/commonjs/engine/tokenCalibration.js.map +0 -1
  112. package/lib/commonjs/engine/verify.js.map +0 -1
  113. package/lib/commonjs/index.js.map +0 -1
  114. package/lib/commonjs/policy/labels.js.map +0 -1
  115. package/lib/commonjs/policy/policy.js.map +0 -1
  116. package/lib/commonjs/policy/redact.js.map +0 -1
  117. package/lib/commonjs/providers/anthropic.js.map +0 -1
  118. package/lib/commonjs/providers/openai.js.map +0 -1
  119. package/lib/commonjs/providers/problem.js.map +0 -1
  120. package/lib/commonjs/providers/sse.js.map +0 -1
  121. package/lib/commonjs/providers/streamTimer.js.map +0 -1
  122. package/lib/commonjs/providers/transport.js.map +0 -1
  123. package/lib/commonjs/providers/types.js.map +0 -1
  124. package/lib/commonjs/providers/xhrStream.js.map +0 -1
  125. package/lib/commonjs/session.js.map +0 -1
  126. package/lib/commonjs/types.js.map +0 -1
  127. package/lib/module/blocks/receipts.js.map +0 -1
  128. package/lib/module/blocks/runId.js.map +0 -1
  129. package/lib/module/blocks/types.js.map +0 -1
  130. package/lib/module/blocks/uiTool.js.map +0 -1
  131. package/lib/module/catalog/catalog.g.js.map +0 -1
  132. package/lib/module/catalog/catalog.types.g.js.map +0 -1
  133. package/lib/module/catalog/normalizeParams.js.map +0 -1
  134. package/lib/module/catalog/signature.js.map +0 -1
  135. package/lib/module/catalog/snapshotReads.js.map +0 -1
  136. package/lib/module/catalog/toProviderTools.js.map +0 -1
  137. package/lib/module/catalog/validateParams.js.map +0 -1
  138. package/lib/module/context/buildContextPack.js.map +0 -1
  139. package/lib/module/effects/digest.js.map +0 -1
  140. package/lib/module/effects/ledger.js.map +0 -1
  141. package/lib/module/engine/askGate.js.map +0 -1
  142. package/lib/module/engine/effectFor.js.map +0 -1
  143. package/lib/module/engine/evidence.js.map +0 -1
  144. package/lib/module/engine/historyBudget.js.map +0 -1
  145. package/lib/module/engine/retrieve.js.map +0 -1
  146. package/lib/module/engine/runAgentTurn.js.map +0 -1
  147. package/lib/module/engine/systemPrompt.js.map +0 -1
  148. package/lib/module/engine/textToolCalls.js.map +0 -1
  149. package/lib/module/engine/tokenCalibration.js.map +0 -1
  150. package/lib/module/engine/verify.js.map +0 -1
  151. package/lib/module/index.js.map +0 -1
  152. package/lib/module/policy/labels.js.map +0 -1
  153. package/lib/module/policy/policy.js.map +0 -1
  154. package/lib/module/policy/redact.js.map +0 -1
  155. package/lib/module/providers/anthropic.js.map +0 -1
  156. package/lib/module/providers/openai.js.map +0 -1
  157. package/lib/module/providers/problem.js.map +0 -1
  158. package/lib/module/providers/sse.js.map +0 -1
  159. package/lib/module/providers/streamTimer.js.map +0 -1
  160. package/lib/module/providers/transport.js.map +0 -1
  161. package/lib/module/providers/types.js.map +0 -1
  162. package/lib/module/providers/xhrStream.js.map +0 -1
  163. package/lib/module/session.js.map +0 -1
  164. package/lib/module/types.js.map +0 -1
  165. package/lib/typescript/blocks/receipts.d.ts.map +0 -1
  166. package/lib/typescript/blocks/runId.d.ts.map +0 -1
  167. package/lib/typescript/blocks/types.d.ts.map +0 -1
  168. package/lib/typescript/blocks/uiTool.d.ts.map +0 -1
  169. package/lib/typescript/catalog/catalog.g.d.ts.map +0 -1
  170. package/lib/typescript/catalog/catalog.types.g.d.ts.map +0 -1
  171. package/lib/typescript/catalog/normalizeParams.d.ts.map +0 -1
  172. package/lib/typescript/catalog/signature.d.ts.map +0 -1
  173. package/lib/typescript/catalog/snapshotReads.d.ts.map +0 -1
  174. package/lib/typescript/catalog/toProviderTools.d.ts.map +0 -1
  175. package/lib/typescript/catalog/validateParams.d.ts.map +0 -1
  176. package/lib/typescript/context/buildContextPack.d.ts.map +0 -1
  177. package/lib/typescript/effects/digest.d.ts.map +0 -1
  178. package/lib/typescript/effects/ledger.d.ts.map +0 -1
  179. package/lib/typescript/engine/askGate.d.ts.map +0 -1
  180. package/lib/typescript/engine/effectFor.d.ts.map +0 -1
  181. package/lib/typescript/engine/evidence.d.ts.map +0 -1
  182. package/lib/typescript/engine/historyBudget.d.ts.map +0 -1
  183. package/lib/typescript/engine/retrieve.d.ts.map +0 -1
  184. package/lib/typescript/engine/runAgentTurn.d.ts.map +0 -1
  185. package/lib/typescript/engine/systemPrompt.d.ts.map +0 -1
  186. package/lib/typescript/engine/textToolCalls.d.ts.map +0 -1
  187. package/lib/typescript/engine/tokenCalibration.d.ts.map +0 -1
  188. package/lib/typescript/engine/verify.d.ts.map +0 -1
  189. package/lib/typescript/index.d.ts.map +0 -1
  190. package/lib/typescript/policy/labels.d.ts.map +0 -1
  191. package/lib/typescript/policy/policy.d.ts.map +0 -1
  192. package/lib/typescript/policy/redact.d.ts.map +0 -1
  193. package/lib/typescript/providers/anthropic.d.ts.map +0 -1
  194. package/lib/typescript/providers/openai.d.ts.map +0 -1
  195. package/lib/typescript/providers/problem.d.ts.map +0 -1
  196. package/lib/typescript/providers/sse.d.ts.map +0 -1
  197. package/lib/typescript/providers/streamTimer.d.ts.map +0 -1
  198. package/lib/typescript/providers/transport.d.ts.map +0 -1
  199. package/lib/typescript/providers/types.d.ts.map +0 -1
  200. package/lib/typescript/providers/xhrStream.d.ts.map +0 -1
  201. package/lib/typescript/session.d.ts.map +0 -1
  202. package/lib/typescript/types.d.ts.map +0 -1
@@ -1,312 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Human titles for tool calls.
5
- *
6
- * The catalog's `summary` field is written FOR THE MODEL — "Navigate the
7
- * device to a concrete path (pushes by default; replace:true swaps the
8
- * current screen)". Shown to a QA person in a 300pt-wide chat row it was
9
- * truncated to "Navigate the device to a concrete path (pushes by default;
10
- * replace:tru…", which is the worst of both worlds: too long to fit and too
11
- * technical to help. The transcript, the changes bar and the approval card
12
- * all render THIS layer instead: a short present-tense sentence with the one
13
- * or two parameters a person would recognise ("Open /bag", "Update the cart
14
- * store"), and the catalog sentence is kept alongside as the expandable
15
- * "what this does" detail.
16
- *
17
- * Phrases are keyed `toolId.action`. `{a|b.c}` interpolates the first defined
18
- * string/number among those parameter paths; a placeholder that resolves to
19
- * nothing disappears with its surrounding space. Anything not phrased here
20
- * falls back to the humanised action name plus the tool title, which is
21
- * still short and still honest — never the model-facing paragraph.
22
- */
23
- import { CATALOG } from "../catalog/catalog.g";
24
- const PHRASES = {
25
- // Routes
26
- "route-events.getSnapshot": "Check which screen is open",
27
- "route-events.getCurrentRoute": "Check the current screen",
28
- "route-events.navigate": "Open {path}",
29
- "route-events.stackGoBack": "Go back one screen",
30
- "route-events.stackNavigateToIndex": "Jump to screen {index} in the stack",
31
- "route-events.stackPopToIndex": "Go back to screen {index}",
32
- "route-events.stackPopToTop": "Go back to the first screen",
33
- // State stores
34
- "zustand.listStores": "List the app's stores",
35
- "zustand.getStoreState": "Read the {storeName} store",
36
- "zustand.getChangeDetail": "Inspect a store change",
37
- "zustand.setState": "Update the {storeName} store",
38
- "zustand.rehydrate": "Reload the {storeName} store from disk",
39
- "redux.getState": "Read the Redux state",
40
- "redux.getActionDetail": "Inspect a Redux action",
41
- "redux.dispatch": "Dispatch {action.type}",
42
- "jotai.listAtoms": "List the app's atoms",
43
- "jotai.getAtomValue": "Read atom {label}",
44
- "jotai.getChangeDetail": "Inspect an atom change",
45
- "jotai.setAtom": "Set atom {label}",
46
- // React Query
47
- "query.listQueries": "List cached queries",
48
- "query.getQueryData": "Read cached data for {queryHash}",
49
- "query.refetch": "Refetch {queryHash}",
50
- "query.invalidate": "Refresh {queryHash}",
51
- "query.reset": "Reset {queryHash}",
52
- "query.remove": "Drop {queryHash} from the cache",
53
- "query.setQueryData": "Replace cached data for {queryHash|queryKey}",
54
- "query.triggerError": "Force {queryHash} into an error",
55
- "query.restoreError": "Clear the forced error on {queryHash}",
56
- "query.triggerLoading": "Force {queryHash} to keep loading",
57
- "query.restoreLoading": "Clear the forced loading on {queryHash}",
58
- "query.clearQueryCache": "Clear the query cache",
59
- "query.clearMutationCache": "Clear the mutation cache",
60
- // Network
61
- "network.getSnapshot": "Read recent network requests",
62
- "network.getCaptureStatus": "Check network capture",
63
- "network.getEventBody": "Read a request's body",
64
- "network.setPinned": "Pin a request",
65
- "network.setSaved": "Save a request",
66
- "network.removeSavedRecord": "Remove saved request {key}",
67
- "network.clearSavedRequests": "Clear saved requests",
68
- "network.clearPinnedRequests": "Clear pinned requests",
69
- "network.listOverrideRules": "List network overrides",
70
- "network.getOverrideRuleBody": "Read a network override",
71
- "network.debugOverrides": "Check overrides for {url}",
72
- "network.upsertOverrideRule": "Add a network override",
73
- "network.deleteOverrideRule": "Delete a network override",
74
- "network.clearOverrideRules": "Clear all network overrides",
75
- // Storage
76
- "storage.async.getAllKeys": "List saved storage keys",
77
- "storage.async.multiGet": "Read saved values",
78
- "storage.async.getItem": "Read saved value {key}",
79
- "storage.async.setItem": "Save {key}",
80
- "storage.async.removeItem": "Delete saved value {key}",
81
- "storage.async.multiRemove": "Delete saved values",
82
- "storage.async.multiSet": "Save several values",
83
- // These two MUST read differently. They were both "Clear all saved app data",
84
- // and the difference is the whole point: `async.clear` also wipes Buoy's own
85
- // devtool settings, `clearAppStorage` preserves them. A user approving the
86
- // shared wording had no way to tell which one they were about to get.
87
- "storage.async.clear": "Clear ALL saved data — including Buoy's own settings",
88
- "storage.clearAppStorage": "Clear the app's saved data (keeps Buoy's settings)",
89
- "storage.getEventDetail": "Inspect a storage change",
90
- "storage.timeTravel.undo": "Undo a storage change",
91
- "storage.timeTravel.jump": "Rewind storage to an earlier point",
92
- "storage.mmkv.snapshot": "Read MMKV storage",
93
- "storage.mmkv.get": "Read {key} from MMKV",
94
- "storage.mmkv.set": "Save {key} to MMKV",
95
- "storage.mmkv.remove": "Delete {key} from MMKV",
96
- "storage.secure.keys": "List secure storage keys",
97
- "storage.secure.snapshot": "Read secure storage",
98
- "storage.secure.get": "Read secure value {key}",
99
- "storage.secure.set": "Save secure value {key}",
100
- "storage.secure.delete": "Delete secure value {key}",
101
- // Console / env / events
102
- "console.getSnapshot": "Read recent console logs",
103
- "console.clearEntries": "Clear the console",
104
- "env.getSnapshot": "Read environment variables",
105
- "events.exportEvents": "Export recent events",
106
- "events.setEnabledSources": "Change which events are recorded",
107
- "sentry.getSnapshot": "Read what's been sent to Sentry",
108
- "sentry.clearEnvelopes": "Clear captured Sentry traffic",
109
- // Ask Buoy's own session
110
- "ask-buoy.listChanges": "List Ask Buoy's changes",
111
- "ask-buoy.undoAll": "Undo everything Ask Buoy changed",
112
- // Screen
113
- "highlight-updates.describeScreen": "Look at what's on screen",
114
- "highlight-updates.tapElement": "Tap {query|testID|text}",
115
- "highlight-updates.waitFor": "Wait for {query|testID}",
116
- "highlight-updates.locateComponent": "Find {query} on screen",
117
- "highlight-updates.getRenderDetail": "Inspect a component's renders",
118
- "highlight-updates.beginMeasurement": "Start counting renders",
119
- "highlight-updates.endMeasurement": "Stop counting renders",
120
- "highlight-updates.clearRenderCounts": "Clear render counts",
121
- "debug-borders.cycleMode": "Cycle debug borders",
122
- "debug-borders.setMode": "Set debug borders to {mode}",
123
- // Impersonate
124
- "impersonate.searchUsers": "Search users for {query}",
125
- "impersonate.startImpersonation": "Impersonate {user.name|user.email|user.id}",
126
- "impersonate.stopImpersonation": "Stop impersonating",
127
- "impersonate.pauseImpersonation": "Pause impersonation",
128
- "impersonate.resumeImpersonation": "Resume impersonation",
129
- "impersonate.clearHistory": "Clear impersonation history",
130
- // App / time machine / scenarios / perf
131
- "app.ping": "Check the app is responding",
132
- "app.reloadApp": "Reload the app",
133
- "time-machine.list": "List saved snapshots",
134
- "time-machine.capture": "Save a snapshot {name}",
135
- "time-machine.captureBaseline": "Save a baseline snapshot",
136
- "time-machine.restore": "Restore snapshot {id}",
137
- "time-machine.preview": "Preview snapshot {id}",
138
- "time-machine.inspect": "Inspect snapshot {id}",
139
- "time-machine.delete": "Delete snapshot {id}",
140
- "time-machine.rename": "Rename a snapshot to {name}",
141
- "time-machine.duplicate": "Duplicate snapshot {id}",
142
- // NOT "delete every snapshot" — that is `time-machine.delete`, and this card
143
- // said so for months. `wipeAll` clears EVERY registered state source to
144
- // fresh-install and reloads the app (timeMachineStore.ts:639); no snapshot is
145
- // involved and there is no undo. The approval card is the last thing standing
146
- // between a user and that, so it has to name the real blast radius.
147
- "time-machine.wipeAll": "Wipe ALL app state to fresh install and reload",
148
- "scenarios.listScenarios": "List scenarios",
149
- "scenarios.getScenario": "Read scenario {id}",
150
- "scenarios.run": "Run scenario {id}",
151
- "scenarios.preview": "Preview scenario {id}",
152
- "scenarios.deactivate": "Stop the active scenario",
153
- "scenarios.delete": "Delete scenario {id}",
154
- "perf-monitor.startRecording": "Start recording performance",
155
- "perf-monitor.stopRecording": "Stop recording performance",
156
- "perf-monitor.mark": "Mark {label} on the timeline",
157
- "perf-monitor.loadReport": "Load a performance report",
158
- "perf-monitor.clearAll": "Clear all performance reports",
159
- "js-top.sample": "Sample the JS thread",
160
- "js-top.getOriginDetail": "Inspect {key} on the JS thread",
161
- // Assets / images
162
- "assets.list": "List bundled assets",
163
- "assets.getDetail": "Inspect an asset",
164
- "assets.rescan": "Rescan bundled assets",
165
- "assets.measureSizes": "Measure asset sizes",
166
- "images.list": "List loaded images",
167
- "images.getDetail": "Inspect an image",
168
- "images.getCaptureStatus": "Check image capture",
169
- "images.retry": "Retry loading an image",
170
- "images.flash": "Flash an image on screen",
171
- "images.setNetworkMode": "Set image network mode to {mode}",
172
- "images.clearExpoCaches": "Clear the image caches",
173
- // TV
174
- "tv-remote.arm": "Start capturing remote presses",
175
- "tv-remote.disarm": "Stop capturing remote presses",
176
- "focus-inspector.rescan": "Rescan focusable elements",
177
- "focus-inspector.focusElement": "Move focus to an element"
178
- };
179
-
180
- /** Boolean-switch actions read better as two sentences than one template. */
181
- const SWITCHES = {
182
- "query.setOnline": {
183
- param: "online",
184
- on: "Put the app back online",
185
- off: "Take the app offline"
186
- },
187
- "network.setOverridesEnabled": {
188
- param: "enabled",
189
- on: "Turn network overrides on",
190
- off: "Turn network overrides off"
191
- },
192
- "network.setOverrideRuleEnabled": {
193
- param: "enabled",
194
- on: "Enable a network override",
195
- off: "Disable a network override"
196
- },
197
- "highlight-updates.setEnabled": {
198
- param: "enabled",
199
- on: "Turn render highlighting on",
200
- off: "Turn render highlighting off"
201
- },
202
- "perf-monitor.setEnabled": {
203
- param: "enabled",
204
- on: "Turn the perf monitor on",
205
- off: "Turn the perf monitor off"
206
- },
207
- "js-top.setEnabled": {
208
- param: "enabled",
209
- on: "Turn JS Top on",
210
- off: "Turn JS Top off"
211
- },
212
- "images.setBlankImages": {
213
- param: "enabled",
214
- on: "Blank out every image",
215
- off: "Show images again"
216
- },
217
- "focus-inspector.setTracking": {
218
- param: "enabled",
219
- on: "Start tracking focus",
220
- off: "Stop tracking focus"
221
- },
222
- "highlight-updates.setSilentTracking": {
223
- param: "enabled",
224
- on: "Track renders silently",
225
- off: "Stop silent render tracking"
226
- }
227
- };
228
- const TOOL_TITLES = Object.fromEntries(CATALOG.map(t => [t.toolId, cleanTitle(t.title)]));
229
-
230
- /** "JS TOP (JS-thread task manager)" → "JS Top"; everything else as-is. */
231
- function cleanTitle(title) {
232
- const base = title.replace(/\s*\(.*\)\s*$/, "").trim();
233
- if (base !== base.toUpperCase() || base.length <= 3) return base;
234
- return base.split(" ").map(w => w.length <= 2 ? w : w.charAt(0) + w.slice(1).toLowerCase()).join(" ");
235
- }
236
-
237
- /** The display name of a tool: "Routes", "Zustand", "React Query". */
238
- export function toolTitle(toolId) {
239
- return TOOL_TITLES[toolId] ?? humanise(toolId);
240
- }
241
- const MAX_VALUE = 48;
242
- function readPath(params, path) {
243
- let cur = params;
244
- for (const seg of path.split(".")) {
245
- if (!cur || typeof cur !== "object") return undefined;
246
- cur = cur[seg];
247
- }
248
- if (typeof cur === "string" && cur.trim()) return truncate(cur.trim());
249
- if (typeof cur === "number") return String(cur);
250
- // A query key is an array — `["pokemon","pikachu","fetch"]` — and the ledger
251
- // row for the product's headline write read "Replace cached data for" with
252
- // nothing after it. Primitive arrays render as a path; anything else stays
253
- // out of a label.
254
- if (Array.isArray(cur) && cur.length > 0 && cur.every(v => typeof v === "string" || typeof v === "number")) {
255
- return truncate(cur.map(String).join(" / "));
256
- }
257
- return undefined;
258
- }
259
- function truncate(value) {
260
- return value.length > MAX_VALUE ? `${value.slice(0, MAX_VALUE - 1)}…` : value;
261
- }
262
- function fill(template, params) {
263
- return template.replace(/\{([^}]+)\}/g, (_, spec) => {
264
- for (const path of spec.split("|")) {
265
- const v = readPath(params, path.trim());
266
- if (v !== undefined) return v;
267
- }
268
- return "";
269
- }).replace(/\s{2,}/g, " ").trim();
270
- }
271
-
272
- /** `getStoreState` → "Get store state"; `async.getItem` → "Get item". */
273
- export function humanise(action) {
274
- const last = action.split(".").pop() ?? action;
275
- const words = last.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").toLowerCase();
276
- return words.charAt(0).toUpperCase() + words.slice(1);
277
- }
278
-
279
- /** The one or two parameters a person would recognise in a fallback title. */
280
- function notableParams(params) {
281
- const parts = [];
282
- for (const key of ["key", "id", "url", "name", "route", "path", "userId", "storeId", "type"]) {
283
- const v = readPath(params, key);
284
- if (v !== undefined) parts.push(v);
285
- if (parts.length >= 2) break;
286
- }
287
- return parts.join(", ");
288
- }
289
-
290
- /**
291
- * A short, present-tense title for a call — the thing a transcript row, a
292
- * ledger row and an approval card all show first.
293
- */
294
- export function titleCall(toolId, action, params) {
295
- const key = `${toolId}.${action}`;
296
- const sw = SWITCHES[key];
297
- if (sw) return params[sw.param] === false ? sw.off : sw.on;
298
- const phrase = PHRASES[key];
299
- if (phrase) {
300
- const out = fill(phrase, params);
301
- if (out) return out;
302
- }
303
-
304
- // Generic verbs the whole suite shares.
305
- const leaf = action.split(".").pop() ?? action;
306
- if (leaf === "clearEvents") return `Clear the ${toolTitle(toolId)} timeline`;
307
- if (leaf === "getSnapshot") return `Read ${toolTitle(toolId)}`;
308
- const detail = notableParams(params);
309
- const base = `${humanise(action)} in ${toolTitle(toolId)}`;
310
- return detail ? `${base} (${detail})` : base;
311
- }
312
- //# sourceMappingURL=labels.js.map
1
+ "use strict";import{CATALOG as g}from"../catalog/catalog.g";const h={"route-events.getSnapshot":"Check which screen is open","route-events.getCurrentRoute":"Check the current screen","route-events.navigate":"Open {path}","route-events.stackGoBack":"Go back one screen","route-events.stackNavigateToIndex":"Jump to screen {index} in the stack","route-events.stackPopToIndex":"Go back to screen {index}","route-events.stackPopToTop":"Go back to the first screen","zustand.listStores":"List the app's stores","zustand.getStoreState":"Read the {storeName} store","zustand.getChangeDetail":"Inspect a store change","zustand.setState":"Update the {storeName} store","zustand.rehydrate":"Reload the {storeName} store from disk","redux.getState":"Read the Redux state","redux.getActionDetail":"Inspect a Redux action","redux.dispatch":"Dispatch {action.type}","jotai.listAtoms":"List the app's atoms","jotai.getAtomValue":"Read atom {label}","jotai.getChangeDetail":"Inspect an atom change","jotai.setAtom":"Set atom {label}","query.listQueries":"List cached queries","query.getQueryData":"Read cached data for {queryHash}","query.refetch":"Refetch {queryHash}","query.invalidate":"Refresh {queryHash}","query.reset":"Reset {queryHash}","query.remove":"Drop {queryHash} from the cache","query.setQueryData":"Replace cached data for {queryHash|queryKey}","query.triggerError":"Force {queryHash} into an error","query.restoreError":"Clear the forced error on {queryHash}","query.triggerLoading":"Force {queryHash} to keep loading","query.restoreLoading":"Clear the forced loading on {queryHash}","query.clearQueryCache":"Clear the query cache","query.clearMutationCache":"Clear the mutation cache","network.getSnapshot":"Read recent network requests","network.getCaptureStatus":"Check network capture","network.getEventBody":"Read a request's body","network.setPinned":"Pin a request","network.setSaved":"Save a request","network.removeSavedRecord":"Remove saved request {key}","network.clearSavedRequests":"Clear saved requests","network.clearPinnedRequests":"Clear pinned requests","network.listOverrideRules":"List network overrides","network.getOverrideRuleBody":"Read a network override","network.debugOverrides":"Check overrides for {url}","network.upsertOverrideRule":"Add a network override","network.deleteOverrideRule":"Delete a network override","network.clearOverrideRules":"Clear all network overrides","storage.async.getAllKeys":"List saved storage keys","storage.async.multiGet":"Read saved values","storage.async.getItem":"Read saved value {key}","storage.async.setItem":"Save {key}","storage.async.removeItem":"Delete saved value {key}","storage.async.multiRemove":"Delete saved values","storage.async.multiSet":"Save several values","storage.async.clear":"Clear ALL saved data \u2014 including Buoy's own settings","storage.clearAppStorage":"Clear the app's saved data (keeps Buoy's settings)","storage.getEventDetail":"Inspect a storage change","storage.timeTravel.undo":"Undo a storage change","storage.timeTravel.jump":"Rewind storage to an earlier point","storage.mmkv.snapshot":"Read MMKV storage","storage.mmkv.get":"Read {key} from MMKV","storage.mmkv.set":"Save {key} to MMKV","storage.mmkv.remove":"Delete {key} from MMKV","storage.secure.keys":"List secure storage keys","storage.secure.snapshot":"Read secure storage","storage.secure.get":"Read secure value {key}","storage.secure.set":"Save secure value {key}","storage.secure.delete":"Delete secure value {key}","console.getSnapshot":"Read recent console logs","console.clearEntries":"Clear the console","env.getSnapshot":"Read environment variables","events.exportEvents":"Export recent events","events.setEnabledSources":"Change which events are recorded","sentry.getSnapshot":"Read what's been sent to Sentry","sentry.clearEnvelopes":"Clear captured Sentry traffic","ask-buoy.listChanges":"List Ask Buoy's changes","ask-buoy.undoAll":"Undo everything Ask Buoy changed","highlight-updates.describeScreen":"Look at what's on screen","highlight-updates.tapElement":"Tap {query|testID|text}","highlight-updates.waitFor":"Wait for {query|testID}","highlight-updates.locateComponent":"Find {query} on screen","highlight-updates.getRenderDetail":"Inspect a component's renders","highlight-updates.beginMeasurement":"Start counting renders","highlight-updates.endMeasurement":"Stop counting renders","highlight-updates.clearRenderCounts":"Clear render counts","debug-borders.cycleMode":"Cycle debug borders","debug-borders.setMode":"Set debug borders to {mode}","impersonate.searchUsers":"Search users for {query}","impersonate.startImpersonation":"Impersonate {user.name|user.email|user.id}","impersonate.stopImpersonation":"Stop impersonating","impersonate.pauseImpersonation":"Pause impersonation","impersonate.resumeImpersonation":"Resume impersonation","impersonate.clearHistory":"Clear impersonation history","app.ping":"Check the app is responding","app.reloadApp":"Reload the app","time-machine.list":"List saved snapshots","time-machine.capture":"Save a snapshot {name}","time-machine.captureBaseline":"Save a baseline snapshot","time-machine.restore":"Restore snapshot {id}","time-machine.preview":"Preview snapshot {id}","time-machine.inspect":"Inspect snapshot {id}","time-machine.delete":"Delete snapshot {id}","time-machine.rename":"Rename a snapshot to {name}","time-machine.duplicate":"Duplicate snapshot {id}","time-machine.wipeAll":"Wipe ALL app state to fresh install and reload","scenarios.listScenarios":"List scenarios","scenarios.getScenario":"Read scenario {id}","scenarios.run":"Run scenario {id}","scenarios.preview":"Preview scenario {id}","scenarios.deactivate":"Stop the active scenario","scenarios.delete":"Delete scenario {id}","perf-monitor.startRecording":"Start recording performance","perf-monitor.stopRecording":"Stop recording performance","perf-monitor.mark":"Mark {label} on the timeline","perf-monitor.loadReport":"Load a performance report","perf-monitor.clearAll":"Clear all performance reports","js-top.sample":"Sample the JS thread","js-top.getOriginDetail":"Inspect {key} on the JS thread","assets.list":"List bundled assets","assets.getDetail":"Inspect an asset","assets.rescan":"Rescan bundled assets","assets.measureSizes":"Measure asset sizes","images.list":"List loaded images","images.getDetail":"Inspect an image","images.getCaptureStatus":"Check image capture","images.retry":"Retry loading an image","images.flash":"Flash an image on screen","images.setNetworkMode":"Set image network mode to {mode}","images.clearExpoCaches":"Clear the image caches","tv-remote.arm":"Start capturing remote presses","tv-remote.disarm":"Stop capturing remote presses","focus-inspector.rescan":"Rescan focusable elements","focus-inspector.focusElement":"Move focus to an element"};const m={"query.setOnline":{param:"online",on:"Put the app back online",off:"Take the app offline"},"network.setOverridesEnabled":{param:"enabled",on:"Turn network overrides on",off:"Turn network overrides off"},"network.setOverrideRuleEnabled":{param:"enabled",on:"Enable a network override",off:"Disable a network override"},"highlight-updates.setEnabled":{param:"enabled",on:"Turn render highlighting on",off:"Turn render highlighting off"},"perf-monitor.setEnabled":{param:"enabled",on:"Turn the perf monitor on",off:"Turn the perf monitor off"},"js-top.setEnabled":{param:"enabled",on:"Turn JS Top on",off:"Turn JS Top off"},"images.setBlankImages":{param:"enabled",on:"Blank out every image",off:"Show images again"},"focus-inspector.setTracking":{param:"enabled",on:"Start tracking focus",off:"Stop tracking focus"},"highlight-updates.setSilentTracking":{param:"enabled",on:"Track renders silently",off:"Stop silent render tracking"}};const f=Object.fromEntries(g.map(t=>[t.toolId,y(t.title)]));function y(t){const r=t.replace(/\s*\(.*\)\s*$/,"").trim();if(r!==r.toUpperCase()||r.length<=3)return r;return r.split(" ").map(e=>e.length<=2?e:e.charAt(0)+e.slice(1).toLowerCase()).join(" ")}export function toolTitle(t){return f[t]??humanise(t)}const l=48;function d(t,r){let e=t;for(const a of r.split(".")){if(!e||typeof e!=="object")return void 0;e=e[a]}if(typeof e==="string"&&e.trim())return p(e.trim());if(typeof e==="number")return String(e);if(Array.isArray(e)&&e.length>0&&e.every(a=>typeof a==="string"||typeof a==="number")){return p(e.map(String).join(" / "))}return void 0}function p(t){return t.length>l?`${t.slice(0,l-1)}\u2026`:t}function v(t,r){return t.replace(/\{([^}]+)\}/g,(e,a)=>{for(const s of a.split("|")){const n=d(r,s.trim());if(n!==void 0)return n}return""}).replace(/\s{2,}/g," ").trim()}export function humanise(t){const r=t.split(".").pop()??t;const e=r.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[-_]+/g," ").toLowerCase();return e.charAt(0).toUpperCase()+e.slice(1)}function k(t){const r=[];for(const e of["key","id","url","name","route","path","userId","storeId","type"]){const a=d(t,e);if(a!==void 0)r.push(a);if(r.length>=2)break}return r.join(", ")}export function titleCall(t,r,e){const a=`${t}.${r}`;const s=m[a];if(s)return e[s.param]===false?s.off:s.on;const n=h[a];if(n){const u=v(n,e);if(u)return u}const o=r.split(".").pop()??r;if(o==="clearEvents")return`Clear the ${toolTitle(t)} timeline`;if(o==="getSnapshot")return`Read ${toolTitle(t)}`;const i=k(e);const c=`${humanise(r)} in ${toolTitle(t)}`;return i?`${c} (${i})`:c}
@@ -1,142 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * What the agent is allowed to do, decided before dispatch.
5
- *
6
- * The default: reads and writes auto-run — the banner plus the effect ledger
7
- * keep the user in control — but DESTRUCTIVE actions need a human tap unless
8
- * the app explicitly passes `requireApproval: []`. Auto-running wipes proved
9
- * too sharp in live evals (five destructive calls in one confused turn), and
10
- * the approval gate is also the blast-radius control if injected text in a
11
- * tool result ever steers the model.
12
- *
13
- * The one thing the policy layer will not do is let the agent report success
14
- * for an action that cannot work in this build. Several Buoy actions return
15
- * `{ok:true}` and do nothing once `__DEV__` is false — `upsertOverrideRule`
16
- * persists a rule the engine never consults — and a QA tester who files a bug
17
- * against data that was never applied is a worse outcome than no agent at all.
18
- * So `release !== "works"` is refused BEFORE dispatch, with the reason handed
19
- * back to the model as the tool result, and `unknown` fails closed.
20
- */
21
-
22
- import { titleCall } from "./labels";
23
-
24
- /**
25
- * One allow rule. A call is permitted when it matches ANY rule; every field a
26
- * rule specifies must match. So a support seat that may impersonate and look
27
- * at anything, and nothing else, is two rules:
28
- *
29
- * allow: [{ effect: "read" }, { toolId: "impersonate" }]
30
- */
31
-
32
- /** The one place the approval default lives; `decide` and the system prompt both resolve through it. */
33
- export const DEFAULT_REQUIRE_APPROVAL = ["destructive"];
34
- export function resolveRequireApproval(policy) {
35
- return policy.requireApproval ?? DEFAULT_REQUIRE_APPROVAL;
36
- }
37
- /** SecureStore VALUE reads — gated behind `policy.secureReads`. Names stay open. */
38
- const SECURE_VALUE_READS = new Set(["secure.get", "secure.snapshot"]);
39
- export function decide({
40
- descriptor,
41
- toolId,
42
- policy,
43
- isRelease
44
- }) {
45
- for (const rule of policy.deny ?? []) {
46
- if (rule.toolId === toolId && (!rule.action || rule.action === descriptor.action)) {
47
- return {
48
- verdict: "refuse",
49
- reason: "This action is disabled in this app."
50
- };
51
- }
52
- }
53
- if (isRelease && descriptor.release !== "works") {
54
- return {
55
- verdict: "refuse",
56
- reason: releaseRefusal(descriptor)
57
- };
58
- }
59
- if (policy.allow) {
60
- const permitted = policy.allow.some(rule => (rule.toolId === undefined || rule.toolId === toolId) && (rule.action === undefined || rule.action === descriptor.action) && (rule.effect === undefined || rule.effect === descriptor.effect));
61
- if (!permitted) {
62
- return {
63
- verdict: "refuse",
64
- reason: "This action isn't on Ask Buoy's allow list in this app."
65
- };
66
- }
67
- }
68
- if (toolId === "storage" && SECURE_VALUE_READS.has(descriptor.action) && policy.secureReads !== true) {
69
- return {
70
- verdict: "refuse",
71
- reason: "Reading SecureStore values is off by default — they are credentials, and they would be sent to the configured model endpoint. Key names are still readable via secure.keys; the app can opt in with policy.secureReads: true."
72
- };
73
- }
74
- if (descriptor.effect !== "read" && policy.readOnly) {
75
- return {
76
- verdict: "refuse",
77
- reason: "Ask Buoy is in read-only mode in this app, so it can look at state but not change it."
78
- };
79
- }
80
- for (const rule of policy.requireApprovalFor ?? []) {
81
- if (rule.toolId === toolId && (!rule.action || rule.action === descriptor.action)) {
82
- return {
83
- verdict: "needs-approval",
84
- reason: "This app asks for a tap before this particular action runs."
85
- };
86
- }
87
- }
88
- if (descriptor.effect === "read") return {
89
- verdict: "allow"
90
- };
91
- if (resolveRequireApproval(policy).includes(descriptor.effect)) {
92
- return {
93
- verdict: "needs-approval",
94
- reason: descriptor.effect === "destructive"
95
- // Not "this will wipe or reset something": most destructive actions
96
- // in the catalog are ordinary edits that simply cannot be put back
97
- // (a store write, a cache reset), and telling someone their quantity
98
- // change is a wipe teaches them to stop reading the card.
99
- ? "Buoy can't undo this one — that's why it's asking." : "This will change the app's state."
100
- };
101
- }
102
- return {
103
- verdict: "allow"
104
- };
105
- }
106
-
107
- /**
108
- * The message the model gets back instead of a result. Written to be relayed
109
- * to a non-developer, because it usually will be.
110
- */
111
- function releaseRefusal(d) {
112
- const base = `\`${d.action}\` does not work in this build (a release build).`;
113
- switch (d.release) {
114
- case "noop":
115
- return `${base} It would report success and change nothing, so Buoy refused to run it rather than let you be told it worked. ${d.releaseNote ?? ""}`.trim();
116
- case "empty":
117
- return `${base} It relies on React's developer hook, which React Native only installs in development builds, so it can only ever return empty results here. ${d.releaseNote ?? ""}`.trim();
118
- case "throws":
119
- return `${base} It is explicitly disabled outside development. ${d.releaseNote ?? ""}`.trim();
120
- default:
121
- return `${base} Buoy could not confirm it behaves correctly outside development, so it refused rather than guess.`;
122
- }
123
- }
124
-
125
- /**
126
- * A short, domain-flavoured title for what a call will do — the first line of
127
- * a transcript row, a ledger row and an approval card.
128
- *
129
- * The raw tool payload is deliberately NOT what gets shown. A QA person cannot
130
- * evaluate `redux_dispatch({type:'SET_ENTITLEMENTS', payload:{...}})`, and an
131
- * approval prompt nobody can read is a rubber stamp, which is worse than no
132
- * prompt because it looks like oversight.
133
- *
134
- * Nor is the catalog `summary`: that sentence is written for the model and
135
- * ran to three lines in a phone-width row before it was cut off. The phrasing
136
- * lives in ./labels.ts; the catalog sentence travels separately on the event
137
- * as `description`, for a row the user chooses to expand.
138
- */
139
- export function describeCall(toolId, descriptor, params) {
140
- return titleCall(toolId, descriptor.action, params);
141
- }
142
- //# sourceMappingURL=policy.js.map
1
+ "use strict";import{titleCall as s}from"./labels";export const DEFAULT_REQUIRE_APPROVAL=["destructive"];export function resolveRequireApproval(e){return e.requireApproval??DEFAULT_REQUIRE_APPROVAL}const i=new Set(["secure.get","secure.snapshot"]);export function decide({descriptor:e,toolId:t,policy:n,isRelease:o}){for(const r of n.deny??[]){if(r.toolId===t&&(!r.action||r.action===e.action)){return{verdict:"refuse",reason:"This action is disabled in this app."}}}if(o&&e.release!=="works"){return{verdict:"refuse",reason:u(e)}}if(n.allow){const r=n.allow.some(a=>(a.toolId===void 0||a.toolId===t)&&(a.action===void 0||a.action===e.action)&&(a.effect===void 0||a.effect===e.effect));if(!r){return{verdict:"refuse",reason:"This action isn't on Ask Buoy's allow list in this app."}}}if(t==="storage"&&i.has(e.action)&&n.secureReads!==true){return{verdict:"refuse",reason:"Reading SecureStore values is off by default \u2014 they are credentials, and they would be sent to the configured model endpoint. Key names are still readable via secure.keys; the app can opt in with policy.secureReads: true."}}if(e.effect!=="read"&&n.readOnly){return{verdict:"refuse",reason:"Ask Buoy is in read-only mode in this app, so it can look at state but not change it."}}for(const r of n.requireApprovalFor??[]){if(r.toolId===t&&(!r.action||r.action===e.action)){return{verdict:"needs-approval",reason:"This app asks for a tap before this particular action runs."}}}if(e.effect==="read")return{verdict:"allow"};if(resolveRequireApproval(n).includes(e.effect)){return{verdict:"needs-approval",reason:e.effect==="destructive"?"Buoy can't undo this one \u2014 that's why it's asking.":"This will change the app's state."}}return{verdict:"allow"}}function u(e){const t=`\`${e.action}\` does not work in this build (a release build).`;switch(e.release){case"noop":return`${t} It would report success and change nothing, so Buoy refused to run it rather than let you be told it worked. ${e.releaseNote??""}`.trim();case"empty":return`${t} It relies on React's developer hook, which React Native only installs in development builds, so it can only ever return empty results here. ${e.releaseNote??""}`.trim();case"throws":return`${t} It is explicitly disabled outside development. ${e.releaseNote??""}`.trim();default:return`${t} Buoy could not confirm it behaves correctly outside development, so it refused rather than guess.`}}export function describeCall(e,t,n){return s(e,t.action,n)}
@@ -1,165 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Scrub tool results before they leave the device.
5
- *
6
- * Two separate reasons, and the second is the one people forget:
7
- *
8
- * 1. EGRESS. Tool results go to the customer's own model endpoint. That is
9
- * their data boundary, not ours — but a response body carrying an
10
- * `Authorization` header or a Buoy `licenseKey` is a credential, and
11
- * credentials do not belong in a chat transcript that may be retained for
12
- * 30 days for abuse monitoring.
13
- * 2. SELF-INJECTION. Buoy's own network interceptor captures the agent's
14
- * requests to the model endpoint. Without exclusion, the model reads back
15
- * its own request headers — including whatever the host app's `headers()`
16
- * returned — out of `network.getRequests`. That is a credential leak and a
17
- * prompt-injection channel in one call.
18
- */
19
-
20
- /**
21
- * Key names that mean "credential", compared with separators stripped —
22
- * `X_API_KEY`, `x-api-key` and `xApiKey` are the same word. A list of hyphen
23
- * spellings let `EXPO_PUBLIC_X_API_KEY=…` through to the model whole on a real
24
- * app, alongside `EXPO_PUBLIC_BUOY_KEY`, which is the Pro licence that gates
25
- * this very tool. Both went out in plaintext while `…_PASSWORD` was caught.
26
- */
27
- const SECRET_KEYS = ["authorization", "cookie", "setcookie", "apikey", "proxyauthorization", "authtoken", "accesstoken", "refreshtoken", "idtoken", "sessiontoken", "bearertoken", "licensekey", "licencekey", "buoykey", "privatekey", "secret", "password", "passwd", "credential"];
28
- const REDACTED = "[redacted by Buoy]";
29
-
30
- /**
31
- * Credential SHAPES, for values whose key name gives nothing away — a JWT
32
- * stored under `session`, a Bearer header quoted inside a response body. The
33
- * key-name check alone let those through whole. Same shapes the broker wire
34
- * scrubber uses; duplicated here because agent-core cannot depend on ask-buoy.
35
- */
36
- const SECRET_VALUE_PATTERNS = [{
37
- re: /\bBearer\s+[A-Za-z0-9._~+/-]{12,}=*/gi,
38
- label: "[bearer token removed]"
39
- }, {
40
- re: /\beyJ[A-Za-z0-9._-]{20,}/g,
41
- label: "[jwt removed]"
42
- }, {
43
- re: /\bsk-[A-Za-z0-9_-]{16,}/g,
44
- label: "[api key removed]"
45
- }, {
46
- re: /\bBUOY-[A-Z0-9-]{8,}/g,
47
- label: "[license key removed]"
48
- },
49
- // Keygen-issued Buoy Pro keys: five hex sextets and a version suffix.
50
- {
51
- re: /\b[A-F0-9]{6}(?:-[A-F0-9]{6}){4}-V\d\b/g,
52
- label: "[license key removed]"
53
- }, {
54
- // Key-name spellings inside free text: `X_API_KEY=…`, `apiKey: "…"`,
55
- // `EXPO_PUBLIC_BUOY_KEY=…`. Word-prefixed forms (EXPO_PUBLIC_, REACT_APP_)
56
- // are covered because the name only has to END in the credential word.
57
- re: /("|')?[A-Za-z0-9_-]*(authorization|api[_-]?key|password|passwd|secret|access[_-]?token|refresh[_-]?token|auth[_-]?token|session[_-]?token|license[_-]?key|licence[_-]?key|buoy[_-]?key|private[_-]?key)\1?\s*[:=]\s*("|')?[^\s"',}]{6,}/gi,
58
- label: "[credential removed]"
59
- }];
60
- function scrubString(s) {
61
- let out = s;
62
- for (const {
63
- re,
64
- label
65
- } of SECRET_VALUE_PATTERNS) {
66
- out = out.replace(re, label);
67
- }
68
- return out;
69
- }
70
- function isSecretKey(key) {
71
- const k = key.toLowerCase().replace(/[-_.\s]/g, "");
72
- return SECRET_KEYS.some(s => k.includes(s));
73
- }
74
-
75
- /**
76
- * Deep-redact by key name AND by value shape. Depth-limited because tool
77
- * results can be deeply nested state trees and a runaway walk on a megabyte
78
- * payload is a frame drop on the JS thread the app is also using.
79
- */
80
- export function redact(value, depth = 0) {
81
- if (typeof value === "string") return scrubString(value);
82
- if (depth > 12 || value === null || typeof value !== "object") return value;
83
- if (Array.isArray(value)) {
84
- return value.map(v => redact(v, depth + 1));
85
- }
86
- const out = {};
87
- for (const [key, v] of Object.entries(value)) {
88
- out[key] = isSecretKey(key) ? REDACTED : redact(v, depth + 1);
89
- }
90
- return out;
91
- }
92
-
93
- /**
94
- * Hosts that must never appear in a tool result, because they are the agent's
95
- * own traffic. Registered by the runtime from the configured endpoint.
96
- */
97
- const selfHosts = new Set();
98
-
99
- /**
100
- * Where the network tool looks for hosts it must not touch.
101
- *
102
- * A GLOBAL, not an import, because the dependency cannot go either way:
103
- * `agent-core` ships with no dependencies at all, and `@buoy-gg/network` is
104
- * optional — most apps that install Ask Buoy do not have it, and the ones that
105
- * do may load it after. A well-known key is the only seam that works in both
106
- * directions without either package requiring the other.
107
- *
108
- * Registering a host here means the interceptor passes its requests straight
109
- * through: not captured, not overridable, and — the reason this exists — not
110
- * held open while the interceptor reads the body. See `networkListener.ts`.
111
- */
112
- const INTERNAL_HOSTS_KEY = "__BUOY_INTERNAL_HOSTS__";
113
- export function registerSelfEndpoint(endpoint) {
114
- try {
115
- // No URL polyfill assumptions — a plain parse is enough for a host match.
116
- const match = /^[a-z]+:\/\/([^/?#]+)/i.exec(endpoint);
117
- if (!match?.[1]) return;
118
- const host = match[1].toLowerCase();
119
- selfHosts.add(host);
120
- const g = globalThis;
121
- const existing = g[INTERNAL_HOSTS_KEY];
122
- const hosts = existing instanceof Set ? existing : new Set();
123
- hosts.add(host);
124
- g[INTERNAL_HOSTS_KEY] = hosts;
125
- } catch {
126
- /* an unparseable endpoint just means no exclusion */
127
- }
128
- }
129
- export function isSelfTraffic(url) {
130
- if (typeof url !== "string") return false;
131
- const lower = url.toLowerCase();
132
- for (const host of selfHosts) {
133
- if (lower.includes(host)) return true;
134
- }
135
- return false;
136
- }
137
- function hasSelfUrl(item) {
138
- if (!item || typeof item !== "object") return false;
139
- const rec = item;
140
- return isSelfTraffic(rec.url ?? rec.uri ?? rec.href);
141
- }
142
-
143
- /**
144
- * Drop the agent's own requests out of a network-shaped result before the
145
- * model sees them.
146
- *
147
- * WALKS INTO OBJECTS, not just top-level arrays. A network reader returns
148
- * `{ totalCaptured, requests: [...] }`, not a bare array, and a version of
149
- * this that only handled the bare array quietly did nothing — the agent's own
150
- * POST to the model endpoint, headers and all, came straight back to it out
151
- * of the network read. Depth-limited for the same reason `redact` is: this
152
- * runs on the JS thread the app is drawing on.
153
- */
154
- export function stripSelfTraffic(value, depth = 0) {
155
- if (depth > 6 || value === null || typeof value !== "object") return value;
156
- if (Array.isArray(value)) {
157
- return value.filter(item => !hasSelfUrl(item)).map(item => stripSelfTraffic(item, depth + 1));
158
- }
159
- const out = {};
160
- for (const [key, v] of Object.entries(value)) {
161
- out[key] = stripSelfTraffic(v, depth + 1);
162
- }
163
- return out;
164
- }
165
- //# sourceMappingURL=redact.js.map
1
+ "use strict";const a=["authorization","cookie","setcookie","apikey","proxyauthorization","authtoken","accesstoken","refreshtoken","idtoken","sessiontoken","bearertoken","licensekey","licencekey","buoykey","privatekey","secret","password","passwd","credential"];const f="[redacted by Buoy]";const l=[{re:/\bBearer\s+[A-Za-z0-9._~+/-]{12,}=*/gi,label:"[bearer token removed]"},{re:/\beyJ[A-Za-z0-9._-]{20,}/g,label:"[jwt removed]"},{re:/\bsk-[A-Za-z0-9_-]{16,}/g,label:"[api key removed]"},{re:/\bBUOY-[A-Z0-9-]{8,}/g,label:"[license key removed]"},{re:/\b[A-F0-9]{6}(?:-[A-F0-9]{6}){4}-V\d\b/g,label:"[license key removed]"},{re:/("|')?[A-Za-z0-9_-]*(authorization|api[_-]?key|password|passwd|secret|access[_-]?token|refresh[_-]?token|auth[_-]?token|session[_-]?token|license[_-]?key|licence[_-]?key|buoy[_-]?key|private[_-]?key)\1?\s*[:=]\s*("|')?[^\s"',}]{6,}/gi,label:"[credential removed]"}];function y(e){let t=e;for(const{re:o,label:r}of l){t=t.replace(o,r)}return t}function k(e){const t=e.toLowerCase().replace(/[-_.\s]/g,"");return a.some(o=>t.includes(o))}export function redact(e,t=0){if(typeof e==="string")return y(e);if(t>12||e===null||typeof e!=="object")return e;if(Array.isArray(e)){return e.map(r=>redact(r,t+1))}const o={};for(const[r,n]of Object.entries(e)){o[r]=k(r)?f:redact(n,t+1)}return o}const c=new Set;const i="__BUOY_INTERNAL_HOSTS__";export function registerSelfEndpoint(e){try{const t=/^[a-z]+:\/\/([^/?#]+)/i.exec(e);if(!t?.[1])return;const o=t[1].toLowerCase();c.add(o);const r=globalThis;const n=r[i];const s=n instanceof Set?n:new Set;s.add(o);r[i]=s}catch{}}export function isSelfTraffic(e){if(typeof e!=="string")return false;const t=e.toLowerCase();for(const o of c){if(t.includes(o))return true}return false}function u(e){if(!e||typeof e!=="object")return false;const t=e;return isSelfTraffic(t.url??t.uri??t.href)}export function stripSelfTraffic(e,t=0){if(t>6||e===null||typeof e!=="object")return e;if(Array.isArray(e)){return e.filter(r=>!u(r)).map(r=>stripSelfTraffic(r,t+1))}const o={};for(const[r,n]of Object.entries(e)){o[r]=stripSelfTraffic(n,t+1)}return o}