@buoy-gg/agent-core 7.0.41 → 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 (201) 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 -4556
  6. package/lib/commonjs/catalog/catalog.source.json +249 -0
  7. package/lib/commonjs/catalog/catalog.types.g.js +1 -46
  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 -345
  16. package/lib/commonjs/engine/askGate.js +1 -287
  17. package/lib/commonjs/engine/effectFor.js +1 -223
  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 -1836
  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 -4552
  46. package/lib/module/catalog/catalog.source.json +249 -0
  47. package/lib/module/catalog/catalog.types.g.js +1 -42
  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 -339
  56. package/lib/module/engine/askGate.js +1 -280
  57. package/lib/module/engine/effectFor.js +1 -220
  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 -1827
  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 +3 -2
  83. package/lib/typescript/providers/problem.d.ts +0 -20
  84. package/lib/typescript/providers/streamTimer.d.ts +0 -24
  85. package/lib/typescript/realNow.d.ts +18 -0
  86. package/lib/web/index.mjs +52 -53
  87. package/package.json +1 -1
  88. package/lib/commonjs/blocks/receipts.js.map +0 -1
  89. package/lib/commonjs/blocks/runId.js.map +0 -1
  90. package/lib/commonjs/blocks/types.js.map +0 -1
  91. package/lib/commonjs/blocks/uiTool.js.map +0 -1
  92. package/lib/commonjs/catalog/catalog.g.js.map +0 -1
  93. package/lib/commonjs/catalog/catalog.types.g.js.map +0 -1
  94. package/lib/commonjs/catalog/normalizeParams.js.map +0 -1
  95. package/lib/commonjs/catalog/signature.js.map +0 -1
  96. package/lib/commonjs/catalog/snapshotReads.js.map +0 -1
  97. package/lib/commonjs/catalog/toProviderTools.js.map +0 -1
  98. package/lib/commonjs/catalog/validateParams.js.map +0 -1
  99. package/lib/commonjs/context/buildContextPack.js.map +0 -1
  100. package/lib/commonjs/effects/digest.js.map +0 -1
  101. package/lib/commonjs/effects/ledger.js.map +0 -1
  102. package/lib/commonjs/engine/askGate.js.map +0 -1
  103. package/lib/commonjs/engine/effectFor.js.map +0 -1
  104. package/lib/commonjs/engine/evidence.js.map +0 -1
  105. package/lib/commonjs/engine/historyBudget.js.map +0 -1
  106. package/lib/commonjs/engine/retrieve.js.map +0 -1
  107. package/lib/commonjs/engine/runAgentTurn.js.map +0 -1
  108. package/lib/commonjs/engine/systemPrompt.js.map +0 -1
  109. package/lib/commonjs/engine/textToolCalls.js.map +0 -1
  110. package/lib/commonjs/engine/tokenCalibration.js.map +0 -1
  111. package/lib/commonjs/engine/verify.js.map +0 -1
  112. package/lib/commonjs/index.js.map +0 -1
  113. package/lib/commonjs/policy/labels.js.map +0 -1
  114. package/lib/commonjs/policy/policy.js.map +0 -1
  115. package/lib/commonjs/policy/redact.js.map +0 -1
  116. package/lib/commonjs/providers/anthropic.js.map +0 -1
  117. package/lib/commonjs/providers/openai.js.map +0 -1
  118. package/lib/commonjs/providers/problem.js.map +0 -1
  119. package/lib/commonjs/providers/sse.js.map +0 -1
  120. package/lib/commonjs/providers/streamTimer.js.map +0 -1
  121. package/lib/commonjs/providers/transport.js.map +0 -1
  122. package/lib/commonjs/providers/types.js.map +0 -1
  123. package/lib/commonjs/providers/xhrStream.js.map +0 -1
  124. package/lib/commonjs/session.js.map +0 -1
  125. package/lib/commonjs/types.js.map +0 -1
  126. package/lib/module/blocks/receipts.js.map +0 -1
  127. package/lib/module/blocks/runId.js.map +0 -1
  128. package/lib/module/blocks/types.js.map +0 -1
  129. package/lib/module/blocks/uiTool.js.map +0 -1
  130. package/lib/module/catalog/catalog.g.js.map +0 -1
  131. package/lib/module/catalog/catalog.types.g.js.map +0 -1
  132. package/lib/module/catalog/normalizeParams.js.map +0 -1
  133. package/lib/module/catalog/signature.js.map +0 -1
  134. package/lib/module/catalog/snapshotReads.js.map +0 -1
  135. package/lib/module/catalog/toProviderTools.js.map +0 -1
  136. package/lib/module/catalog/validateParams.js.map +0 -1
  137. package/lib/module/context/buildContextPack.js.map +0 -1
  138. package/lib/module/effects/digest.js.map +0 -1
  139. package/lib/module/effects/ledger.js.map +0 -1
  140. package/lib/module/engine/askGate.js.map +0 -1
  141. package/lib/module/engine/effectFor.js.map +0 -1
  142. package/lib/module/engine/evidence.js.map +0 -1
  143. package/lib/module/engine/historyBudget.js.map +0 -1
  144. package/lib/module/engine/retrieve.js.map +0 -1
  145. package/lib/module/engine/runAgentTurn.js.map +0 -1
  146. package/lib/module/engine/systemPrompt.js.map +0 -1
  147. package/lib/module/engine/textToolCalls.js.map +0 -1
  148. package/lib/module/engine/tokenCalibration.js.map +0 -1
  149. package/lib/module/engine/verify.js.map +0 -1
  150. package/lib/module/index.js.map +0 -1
  151. package/lib/module/policy/labels.js.map +0 -1
  152. package/lib/module/policy/policy.js.map +0 -1
  153. package/lib/module/policy/redact.js.map +0 -1
  154. package/lib/module/providers/anthropic.js.map +0 -1
  155. package/lib/module/providers/openai.js.map +0 -1
  156. package/lib/module/providers/problem.js.map +0 -1
  157. package/lib/module/providers/sse.js.map +0 -1
  158. package/lib/module/providers/streamTimer.js.map +0 -1
  159. package/lib/module/providers/transport.js.map +0 -1
  160. package/lib/module/providers/types.js.map +0 -1
  161. package/lib/module/providers/xhrStream.js.map +0 -1
  162. package/lib/module/session.js.map +0 -1
  163. package/lib/module/types.js.map +0 -1
  164. package/lib/typescript/blocks/receipts.d.ts.map +0 -1
  165. package/lib/typescript/blocks/runId.d.ts.map +0 -1
  166. package/lib/typescript/blocks/types.d.ts.map +0 -1
  167. package/lib/typescript/blocks/uiTool.d.ts.map +0 -1
  168. package/lib/typescript/catalog/catalog.g.d.ts.map +0 -1
  169. package/lib/typescript/catalog/catalog.types.g.d.ts.map +0 -1
  170. package/lib/typescript/catalog/normalizeParams.d.ts.map +0 -1
  171. package/lib/typescript/catalog/signature.d.ts.map +0 -1
  172. package/lib/typescript/catalog/snapshotReads.d.ts.map +0 -1
  173. package/lib/typescript/catalog/toProviderTools.d.ts.map +0 -1
  174. package/lib/typescript/catalog/validateParams.d.ts.map +0 -1
  175. package/lib/typescript/context/buildContextPack.d.ts.map +0 -1
  176. package/lib/typescript/effects/digest.d.ts.map +0 -1
  177. package/lib/typescript/effects/ledger.d.ts.map +0 -1
  178. package/lib/typescript/engine/askGate.d.ts.map +0 -1
  179. package/lib/typescript/engine/effectFor.d.ts.map +0 -1
  180. package/lib/typescript/engine/evidence.d.ts.map +0 -1
  181. package/lib/typescript/engine/historyBudget.d.ts.map +0 -1
  182. package/lib/typescript/engine/retrieve.d.ts.map +0 -1
  183. package/lib/typescript/engine/runAgentTurn.d.ts.map +0 -1
  184. package/lib/typescript/engine/systemPrompt.d.ts.map +0 -1
  185. package/lib/typescript/engine/textToolCalls.d.ts.map +0 -1
  186. package/lib/typescript/engine/tokenCalibration.d.ts.map +0 -1
  187. package/lib/typescript/engine/verify.d.ts.map +0 -1
  188. package/lib/typescript/index.d.ts.map +0 -1
  189. package/lib/typescript/policy/labels.d.ts.map +0 -1
  190. package/lib/typescript/policy/policy.d.ts.map +0 -1
  191. package/lib/typescript/policy/redact.d.ts.map +0 -1
  192. package/lib/typescript/providers/anthropic.d.ts.map +0 -1
  193. package/lib/typescript/providers/openai.d.ts.map +0 -1
  194. package/lib/typescript/providers/problem.d.ts.map +0 -1
  195. package/lib/typescript/providers/sse.d.ts.map +0 -1
  196. package/lib/typescript/providers/streamTimer.d.ts.map +0 -1
  197. package/lib/typescript/providers/transport.d.ts.map +0 -1
  198. package/lib/typescript/providers/types.d.ts.map +0 -1
  199. package/lib/typescript/providers/xhrStream.d.ts.map +0 -1
  200. package/lib/typescript/session.d.ts.map +0 -1
  201. package/lib/typescript/types.d.ts.map +0 -1
@@ -1,369 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * A conversation, with everything wired up.
5
- *
6
- * This is the one-call surface the UI packages use. It owns the pieces that
7
- * have to agree with each other across a whole session — the provider, the
8
- * catalog filtered to what this device can actually do, the system prompt
9
- * (the stable part built once after grounding, the RIGHT NOW part re-read every
10
- * turn), the effect ledger, and the message history —
11
- * so a chat UI is a message list plus a text box rather than an orchestrator.
12
- */
13
- import { CATALOG } from "./catalog/catalog.g";
14
- import { buildContextDigest, buildLiveContext } from "./context/buildContextPack";
15
- import { runAgentTurn } from "./engine/runAgentTurn";
16
- import { buildLiveBlock, buildSystemPrompt, listableProcedures } from "./engine/systemPrompt";
17
- import { EffectLedger } from "./effects/ledger";
18
- import { EvidenceStore } from "./engine/evidence";
19
- import { TokenCalibration } from "./engine/tokenCalibration";
20
- import { compressConsumed, trimHistory, trimHistoryReport } from "./engine/historyBudget";
21
- import { createAnthropicProvider } from "./providers/anthropic";
22
- import { createOpenAIProvider } from "./providers/openai";
23
- import { resolveRequireApproval } from "./policy/policy";
24
- import { registerSelfEndpoint } from "./policy/redact";
25
- /**
26
- * A stored history, made safe to send as the start of a new request.
27
- *
28
- * Two things make a saved conversation unusable as-is.
29
- *
30
- * A history captured mid-turn ends with an assistant message whose `tool_use`
31
- * blocks were never answered, or with the `tool_result`s and no reply after
32
- * them. Every provider rejects both: the blocks must pair up. So this rewinds
33
- * to the last COMPLETE round — an assistant message that made no tool calls,
34
- * which is where a conversation is always safe to resume from.
35
- *
36
- * And thinking blocks are dropped. Anthropic needs them replayed only when the
37
- * very next thing sent is that turn's `tool_result`s; a restored conversation
38
- * always resumes with a fresh user message instead, so their signatures are
39
- * dead weight at best and a stale-signature 400 at worst.
40
- */
41
- // Re-exported: these were defined here before the engine needed them too, and
42
- // the tests and the package surface still reach them through this module.
43
- export { compressConsumed, trimHistory, trimHistoryReport };
44
- export function resumableHistory(history) {
45
- let end = history.length;
46
- while (end > 0) {
47
- const m = history[end - 1];
48
- if (m.role === "assistant" && !m.toolCalls?.length) break;
49
- end -= 1;
50
- }
51
- return history.slice(0, end).map(m => m.role === "assistant" && m.thinking ? {
52
- ...m,
53
- thinking: undefined
54
- } : m);
55
- }
56
- export function createAskBuoySession(config) {
57
- const catalog = config.catalog ?? CATALOG;
58
- const ledger = new EffectLedger();
59
- const policy = config.policy ?? {};
60
- let messages = [];
61
- /**
62
- * Image-URL provenance for the whole conversation, not one turn of it.
63
- *
64
- * "Show me the shop as pictures" and "no, actually render them" are two
65
- * turns; the second has no tool calls of its own, so a per-turn set held
66
- * nothing and every image was stripped out from under the model. It kept
67
- * describing artwork that was not on screen. The rule is unchanged — a URL
68
- * still has to have been READ — the window is just the conversation. Reset
69
- * with the conversation.
70
- */
71
- const seenUrls = new Set();
72
- /**
73
- * Every result's full text, for `ask-buoy.retrieve` — see engine/evidence.ts.
74
- * Conversation-scoped like `seenUrls`: "what were the stats in that response"
75
- * is a normal second message. Cleared with the conversation; never persisted.
76
- */
77
- const evidence = new EvidenceStore();
78
- /** Chars-per-token as measured on THIS session's provider — see engine/tokenCalibration.ts. */
79
- const calibration = new TokenCalibration();
80
- let system;
81
- let primed = false;
82
- /** See `setApprovalBypass`. Consulted per turn, never captured. */
83
- let bypassApproval = false;
84
- /** Actions the user waived the card for in this conversation — see RunTurnInput.trusted. */
85
- const trusted = new Set();
86
- /** See `setReadOnly`. */
87
- let deviceReadOnly = false;
88
- /**
89
- * Rounds dropped by `restore` — reported on the first send, because there is
90
- * no open turn to carry the event when the restore happens.
91
- */
92
- let trimmedOnRestore = 0;
93
- /**
94
- * Which conversation is live. Bumped by `reset`.
95
- *
96
- * A turn's history is committed when its generator drains, and a turn does
97
- * not stop the moment Stop is pressed — an in-flight dispatch has to settle
98
- * first, and nothing can pull a store write back out of an adapter. So the
99
- * sequence Stop -> "New conversation" -> the write finishes used to end with
100
- * the OLD turn assigning its whole history over the empty one: a chat the
101
- * user had just cleared came back, carrying a change they never saw made.
102
- * The turn still finishes and its effect still lands in the app; it simply
103
- * no longer owns a conversation that has moved on.
104
- */
105
- let generation = 0;
106
- /**
107
- * The grounding probe's result, held past `prime`.
108
- *
109
- * The system prompt is a pure function of this plus the policy, and the
110
- * approval paragraph changes when the device toggle does — holding the
111
- * digest lets the prompt be rebuilt without re-probing the app for state it
112
- * already read.
113
- */
114
- let digest = {};
115
- /**
116
- * `storage key -> the live store that owns it`, derived from the grounding.
117
- *
118
- * Kept because the prompt alone is advice, and a cheap model skips advice the
119
- * same way it skips an optional parameter. With this the ENGINE can tell,
120
- * at dispatch time, that a storage write landed on a store's saved copy and
121
- * therefore changed nothing the user can see.
122
- */
123
- let storeKeyOwners = {};
124
-
125
- // So the agent's own requests to the model endpoint never come back to it
126
- // out of the network tool — that would feed it its own auth headers.
127
- registerSelfEndpoint(config.endpoint);
128
- const provider = config.provider ?? (config.protocol === "openai" ? createOpenAIProvider(config) : createAnthropicProvider(config));
129
-
130
- // Mutable: the device's tool list fills in over the first frames and can
131
- // change while the sheet is open. See setAvailableActions.
132
- let availableActions = config.availableActions;
133
- let availableToolIds = Object.keys(availableActions);
134
-
135
- /**
136
- * THE policy object the engine reads, mutated in place.
137
- *
138
- * One object for the life of the session, not a fresh one per turn: the
139
- * engine reads `policy.readOnly` and the approval lists at each call, so a
140
- * toggle flipped mid-turn lands on the very next call of that turn. A new
141
- * object per turn would leave a running turn on the old rules until it
142
- * finished — "Read only" switched on while the agent was writing would let
143
- * the rest of the batch through.
144
- */
145
- const live = {
146
- ...policy
147
- };
148
- function refreshLive() {
149
- for (const k of Object.keys(live)) delete live[k];
150
- Object.assign(live, policy);
151
- if (bypassApproval) {
152
- live.requireApproval = [];
153
- live.requireApprovalFor = [];
154
- }
155
- // OR, never override: the device can narrow, the app's own read-only stands.
156
- if (deviceReadOnly) live.readOnly = true;
157
- }
158
- function activePolicy() {
159
- return live;
160
- }
161
- function composeSystem() {
162
- system = buildSystemPrompt({
163
- catalog,
164
- context: {
165
- ...config.context,
166
- digest: {
167
- ...digest,
168
- ...config.context?.digest
169
- }
170
- },
171
- isRelease: config.isRelease,
172
- readOnly: live.readOnly ?? false,
173
- readOnlySource: policy.readOnly ? "app" : deviceReadOnly ? "device" : undefined,
174
- requireApproval: resolveRequireApproval(live),
175
- approvalsBypassed: bypassApproval,
176
- appName: config.appName,
177
- platform: config.platform,
178
- availableToolIds
179
- });
180
- }
181
- async function prime() {
182
- if (primed) return;
183
- primed = true;
184
- digest = {};
185
- try {
186
- digest = await buildContextDigest({
187
- dispatch: config.dispatch,
188
- readSnapshot: config.readSnapshot,
189
- availableToolIds,
190
- availableActions
191
- });
192
- } catch {
193
- // Grounding is an optimisation. A chat with no digest still works; a
194
- // chat that refuses to open because a probe timed out does not.
195
- }
196
- storeKeyOwners = {};
197
- for (const raw of digest.zustandStores ?? []) {
198
- const store = raw;
199
- if (store?.persistsTo && store.name) storeKeyOwners[store.persistsTo] = store.name;
200
- }
201
- composeSystem();
202
- }
203
- return {
204
- ledger,
205
- evidence,
206
- calibration,
207
- trustedActions: () => [...trusted],
208
- untrust: key => {
209
- trusted.delete(key);
210
- },
211
- get messages() {
212
- return messages;
213
- },
214
- prime,
215
- setAvailableActions(actions) {
216
- availableActions = actions;
217
- availableToolIds = Object.keys(actions);
218
- },
219
- setApprovalBypass(enabled) {
220
- if (bypassApproval === enabled) return;
221
- bypassApproval = enabled;
222
- refreshLive();
223
- // The prompt tells the model whether a card will appear before its
224
- // change lands; leaving that paragraph stale would have it announce an
225
- // approval step that no longer exists. Rebuilt from the held digest, so
226
- // toggling mid-conversation costs nothing and re-reads nothing.
227
- if (system) composeSystem();
228
- },
229
- setReadOnly(enabled) {
230
- if (deviceReadOnly === enabled) return;
231
- deviceReadOnly = enabled;
232
- refreshLive();
233
- if (system) composeSystem();
234
- },
235
- restore(history) {
236
- // Only into a session that has not been talked to. Restoring over a live
237
- // conversation would drop whatever was said since the app started.
238
- if (messages.length > 0) return;
239
- const report = trimHistoryReport(resumableHistory(history), calibration.charsPerToken, ledger.liveCallIds());
240
- messages = report.messages;
241
- trimmedOnRestore = report.droppedRounds;
242
- },
243
- async *send(text, signal) {
244
- /**
245
- * Captured FIRST, before any await.
246
- *
247
- * Priming and the live-context probes are awaits like any other, and a
248
- * reset can land inside them. Reading the generation after them would
249
- * pick up the NEW conversation's value and let this turn commit into it —
250
- * the precise bug this guards against, reintroduced one line lower.
251
- */
252
- const myGeneration = generation;
253
- await prime();
254
- // The RIGHT NOW block: re-read on EVERY turn, not once at open. The
255
- // stable digest above was once the whole picture, and it was built
256
- // before the user had navigated anywhere — so the query that owned the
257
- // screen they were looking at was simply not in the prompt. This is the
258
- // uncached tail of the system prompt (see ProviderRequest.systemVolatile).
259
- let live;
260
- try {
261
- live = await buildLiveContext({
262
- dispatch: config.dispatch,
263
- readSnapshot: config.readSnapshot,
264
- availableToolIds,
265
- availableActions
266
- });
267
- } catch {
268
- live = undefined;
269
- }
270
- /**
271
- * The conversation was cleared while this turn was still getting ready.
272
- *
273
- * Priming and the live probes take real time, so "New conversation"
274
- * lands here often enough to matter. Abandoning now costs nothing: the
275
- * model has not been asked anything yet.
276
- */
277
- if (myGeneration !== generation) {
278
- yield {
279
- type: "done",
280
- stopReason: "superseded"
281
- };
282
- return;
283
- }
284
-
285
- /**
286
- * The turn works on its OWN array, and `messages` is assigned in exactly
287
- * one place — the commit at the bottom.
288
- *
289
- * `runAgentTurn` pushes each round into the array it is handed. Handing
290
- * it the session's own array made every push a live edit of session
291
- * state, so a turn racing a reset wrote its whole history into the new
292
- * conversation one push at a time and the commit guard had nothing left
293
- * to protect. Copying makes ownership checkable in one place instead of
294
- * spread across the loop.
295
- */
296
- const trimmed = trimHistoryReport([...messages, {
297
- role: "user",
298
- text
299
- }], calibration.charsPerToken, ledger.liveCallIds());
300
- const working = trimmed.messages;
301
- // Said once, before the answer it affects. The screen still shows the
302
- // rounds the model just lost; this is the only thing that tells the two
303
- // apart. See the `history-trimmed` event.
304
- const droppedRounds = trimmed.droppedRounds + trimmedOnRestore;
305
- trimmedOnRestore = 0;
306
- if (droppedRounds > 0) yield {
307
- type: "history-trimmed",
308
- droppedRounds,
309
- droppedPinned: trimmed.droppedPinned
310
- };
311
- const gen = runAgentTurn({
312
- provider,
313
- catalog,
314
- messages: working,
315
- system: system,
316
- systemVolatile: buildLiveBlock(live,
317
- // What this conversation has already done to the app. See
318
- // buildLiveBlock — without it the model answers "what have you
319
- // changed?" from memory of its own sentences, and reports a value it
320
- // overwrote itself as the app's own.
321
- ledger.list().map(e => ({
322
- label: `${e.toolId}.${e.action}${e.effect.label ? ` — ${e.effect.label}` : ""}`,
323
- undone: e.undoneAt !== undefined
324
- }))),
325
- model: config.model,
326
- maxTokens: config.maxTokens ?? 4096,
327
- dispatch: config.dispatch,
328
- readSnapshot: config.readSnapshot,
329
- storeKeyOwners,
330
- ledger,
331
- policy: activePolicy(),
332
- isRelease: config.isRelease,
333
- availableToolIds,
334
- availableActions,
335
- requestApproval: config.requestApproval,
336
- seenUrls,
337
- evidence,
338
- calibration,
339
- trusted,
340
- procedures: listableProcedures(config.context?.procedures, availableToolIds),
341
- signal
342
- });
343
- let next = await gen.next();
344
- while (!next.done) {
345
- yield next.value;
346
- next = await gen.next();
347
- }
348
- // The generator's return value is the full history including tool turns.
349
- // Committed only if this turn still owns the conversation — see
350
- // `generation`.
351
- if (myGeneration === generation) messages = next.value;
352
- },
353
- reset() {
354
- // Before anything else: a turn still draining must not commit over this.
355
- generation += 1;
356
- messages = [];
357
- trimmedOnRestore = 0;
358
- ledger.clear();
359
- seenUrls.clear();
360
- evidence.clear();
361
- trusted.clear();
362
- // The grounding digest is a snapshot of the app AT OPEN — stores and
363
- // routes registered since are invisible to it. A new conversation is
364
- // the natural moment to re-read the world.
365
- primed = false;
366
- }
367
- };
368
- }
369
- //# sourceMappingURL=session.js.map
1
+ "use strict";import{CATALOG as H}from"./catalog/catalog.g";import{buildContextDigest as g,buildLiveContext as G}from"./context/buildContextPack";import{runAgentTurn as N}from"./engine/runAgentTurn";import{buildLiveBlock as z,buildSystemPrompt as D,listableProcedures as F}from"./engine/systemPrompt";import{EffectLedger as K}from"./effects/ledger";import{EvidenceStore as U}from"./engine/evidence";import{TokenCalibration as V}from"./engine/tokenCalibration";import{compressConsumed as J,trimHistory as M,trimHistoryReport as T}from"./engine/historyBudget";import{createAnthropicProvider as Q}from"./providers/anthropic";import{createOpenAIProvider as W}from"./providers/openai";import{resolveRequireApproval as X}from"./policy/policy";import{registerSelfEndpoint as Y}from"./policy/redact";export{J as compressConsumed,M as trimHistory,T as trimHistoryReport};export function resumableHistory(e){let a=e.length;while(a>0){const r=e[a-1];if(r.role==="assistant"&&!r.toolCalls?.length)break;a-=1}return e.slice(0,a).map(r=>r.role==="assistant"&&r.thinking?{...r,thinking:void 0}:r)}export function createAskBuoySession(e){const a=e.catalog??H;const r=new K;const b=e.policy??{};let n=[];const P=new Set;const k=new U;const d=new V;let c;let w=false;let m=false;const u=new Set;let y=false;let v=0;let f=0;let h={};let O={};Y(e.endpoint);const B=e.provider??(e.protocol==="openai"?W(e):Q(e));let i=e.availableActions;let l=Object.keys(i);const s={...b};function C(){for(const t of Object.keys(s))delete s[t];Object.assign(s,b);if(m){s.requireApproval=[];s.requireApprovalFor=[]}if(y)s.readOnly=true}function $(){return s}function S(){c=D({catalog:a,context:{...e.context,digest:{...h,...e.context?.digest}},isRelease:e.isRelease,readOnly:s.readOnly??false,readOnlySource:b.readOnly?"app":y?"device":void 0,requireApproval:X(s),approvalsBypassed:m,appName:e.appName,platform:e.platform,availableToolIds:l})}async function q(){if(w)return;w=true;h={};try{h=await g({dispatch:e.dispatch,readSnapshot:e.readSnapshot,availableToolIds:l,availableActions:i})}catch{}O={};for(const t of h.zustandStores??[]){const o=t;if(o?.persistsTo&&o.name)O[o.persistsTo]=o.name}S()}return{ledger:r,evidence:k,calibration:d,trustedActions:()=>[...u],untrust:t=>{u.delete(t)},get messages(){return n},prime:q,setAvailableActions(t){i=t;l=Object.keys(t)},setApprovalBypass(t){if(m===t)return;m=t;C();if(c)S()},setReadOnly(t){if(y===t)return;y=t;C();if(c)S()},restore(t){if(n.length>0)return;const o=T(resumableHistory(t),d.charsPerToken,r.liveCallIds());n=o.messages;v=o.droppedRounds},async*send(t,o){const I=f;await q();let x;try{x=await G({dispatch:e.dispatch,readSnapshot:e.readSnapshot,availableToolIds:l,availableActions:i})}catch{x=void 0}if(I!==f){yield{type:"done",stopReason:"superseded"};return}const R=T([...n,{role:"user",text:t}],d.charsPerToken,r.liveCallIds());const E=R.messages;const L=R.droppedRounds+v;v=0;if(L>0)yield{type:"history-trimmed",droppedRounds:L,droppedPinned:R.droppedPinned};const j=N({provider:B,catalog:a,messages:E,system:c,systemVolatile:z(x,r.list().map(p=>({label:`${p.toolId}.${p.action}${p.effect.label?` \u2014 ${p.effect.label}`:""}`,undone:p.undoneAt!==void 0}))),model:e.model,maxTokens:e.maxTokens??4096,dispatch:e.dispatch,readSnapshot:e.readSnapshot,storeKeyOwners:O,ledger:r,policy:$(),isRelease:e.isRelease,availableToolIds:l,availableActions:i,requestApproval:e.requestApproval,seenUrls:P,evidence:k,calibration:d,trusted:u,procedures:F(e.context?.procedures,l),signal:o});let A=await j.next();while(!A.done){yield A.value;A=await j.next()}if(I===f)n=A.value},reset(){f+=1;n=[];v=0;r.clear();P.clear();k.clear();u.clear();w=false}}}
@@ -1,2 +1 @@
1
1
  "use strict";
2
- //# sourceMappingURL=types.js.map
@@ -2,10 +2,10 @@
2
2
  * GENERATED by scripts/gen-agent-catalog.mjs — do not edit.
3
3
  * Source: packages/agent-core/src/catalog/catalog.source.json
4
4
  *
5
- * 26 Buoy tools, 218 actions.
5
+ * 27 Buoy tools, 229 actions.
6
6
  */
7
7
  import type { ToolDescriptor } from "../types";
8
8
  export declare const CATALOG: ToolDescriptor[];
9
- export declare const CATALOG_TOOL_COUNT = 26;
10
- export declare const CATALOG_ACTION_COUNT = 218;
9
+ export declare const CATALOG_TOOL_COUNT = 27;
10
+ export declare const CATALOG_ACTION_COUNT = 229;
11
11
  //# sourceMappingURL=catalog.g.d.ts.map
@@ -5,9 +5,9 @@
5
5
  * The catalog's tool ids and action names as types, so a wrong name fails
6
6
  * at compile time. `catalog.g.ts` carries the data.
7
7
  *
8
- * 26 Buoy tools, 218 actions.
8
+ * 27 Buoy tools, 229 actions.
9
9
  */
10
- export type CatalogToolId = "env" | "console" | "sentry" | "jotai" | "route-events" | "debug-borders" | "zustand" | "redux" | "impersonate" | "query" | "events" | "network" | "js-top" | "app" | "time-machine" | "storage" | "highlight-updates" | "scenarios" | "perf-monitor" | "assets" | "tv-remote" | "focus-inspector" | "images" | "ask-buoy" | "push-notifications" | "image-overlay";
10
+ export type CatalogToolId = "env" | "console" | "sentry" | "jotai" | "route-events" | "debug-borders" | "zustand" | "redux" | "impersonate" | "query" | "events" | "network" | "js-top" | "app" | "time-machine" | "clock" | "storage" | "highlight-updates" | "scenarios" | "perf-monitor" | "assets" | "tv-remote" | "focus-inspector" | "images" | "ask-buoy" | "push-notifications" | "image-overlay";
11
11
  export interface CatalogActionMap {
12
12
  "env": "getSnapshot";
13
13
  "console": "getSnapshot" | "clearEntries";
@@ -24,6 +24,7 @@ export interface CatalogActionMap {
24
24
  "js-top": "sample" | "getOriginDetail" | "setEnabled" | "pause" | "resume" | "clear";
25
25
  "app": "ping" | "reloadApp";
26
26
  "time-machine": "list" | "capture" | "captureBaseline" | "wipeAll" | "restore" | "preview" | "inspect" | "delete" | "rename" | "duplicate" | "setExclusions" | "setScope" | "setRestoreRoute";
27
+ "clock": "getState" | "setTime" | "shift" | "freeze" | "resume" | "setRate" | "reset" | "updateSettings" | "jumpToTokenExpiry" | "failNextRequest" | "stopTokenCheck";
27
28
  "storage": "getRequiredKeys" | "async.getAllKeys" | "async.multiGet" | "async.getItem" | "async.setItem" | "async.removeItem" | "async.multiRemove" | "async.multiSet" | "async.clear" | "clearAppStorage" | "getEventDetail" | "clearEvents" | "timeTravel.undo" | "timeTravel.jump" | "mmkv.snapshot" | "mmkv.get" | "mmkv.set" | "mmkv.remove" | "secure.keys" | "secure.snapshot" | "secure.get" | "secure.set" | "secure.delete";
28
29
  "highlight-updates": "describeScreen" | "tapElement" | "waitFor" | "beginMeasurement" | "endMeasurement" | "locateComponent" | "getRenderDetail" | "setEnabled" | "toggle" | "setSilentTracking" | "toggleFreeze" | "setSpotlight" | "clearRenderCounts" | "startTouchCapture" | "stopTouchCapture" | "clearTouchCapture" | "readTouchCapture";
29
30
  "scenarios": "listScenarios" | "getScenario" | "save" | "acceptDraft" | "discardDraft" | "preview" | "run" | "deactivate" | "delete" | "setFolder" | "listFolders" | "getActive" | "export";
@@ -1,23 +1,3 @@
1
- /**
2
- * What kind of failure a provider reported — decided once, from the status,
3
- * the error type and the message, so the engine can act on the KIND rather
4
- * than grep a string.
5
- *
6
- * Only two kinds are acted on, and both only when nothing has been generated:
7
- *
8
- * - `throttled` — 429 / 529 / 503, a `rate_limit_error` or `overloaded_error`
9
- * frame, or a body that says so. Waiting and asking again is the right move;
10
- * the request never reached a model.
11
- * - `overflow` — the provider refused the request as too big. Trimming older
12
- * history and asking once more is the right move; the proactive budget is
13
- * an estimate (chars ÷ 4) and JSON tokenizes worse than prose.
14
- *
15
- * Everything else — auth, a bad schema, an unknown model, a mid-answer
16
- * `api_error` — is reported and NOT retried. The phrase lists are the union
17
- * observed across provider responses by the Strands SDK (harness-sdk
18
- * `381ab48`, `models/anthropic.ts` + `models/openai/errors.ts`, Apache-2.0),
19
- * matched case-insensitively on the lowered message.
20
- */
21
1
  export type ProblemKind = "throttled" | "overflow" | "auth" | "other";
22
2
  export interface StreamProblem {
23
3
  kind: ProblemKind;
@@ -1,27 +1,3 @@
1
- /**
2
- * The clock on a model request.
3
- *
4
- * There was none. A gateway that accepted the socket and then said nothing —
5
- * an overloaded proxy, a dropped VPN, a laptop that slept mid-answer — left
6
- * the turn running with the thinking strip animating until a person pressed
7
- * Stop. The 180s turn deadline did not help: it is read at the TOP of a step
8
- * (`runAgentTurn`), and a step parked inside `await fetch(...)` never reaches
9
- * the next one.
10
- *
11
- * Two clocks, because the two silences mean different things:
12
- *
13
- * - CONNECT covers "no headers yet". Nothing has been generated, so nothing is
14
- * lost by giving up; 30s is already long for a gateway to acknowledge a POST.
15
- * - IDLE covers "headers arrived, then nothing". This one has to be generous.
16
- * Anthropic sends `ping` frames, but an OpenAI-protocol reasoning model can
17
- * legitimately emit nothing for a long stretch while it thinks, and cutting
18
- * that off would look like a broken product. Any frame at all — a keepalive
19
- * comment included — resets it, so only total silence trips it.
20
- *
21
- * A timeout is NOT a retry. Nothing is re-sent: the request may have reached
22
- * the model, and a duplicate turn is a duplicate bill and possibly duplicate
23
- * writes. The turn ends with an honest notice and a Continue button.
24
- */
25
1
  export declare const DEFAULT_CONNECT_TIMEOUT_MS = 30000;
26
2
  export declare const DEFAULT_IDLE_TIMEOUT_MS = 90000;
27
3
  export interface StreamTimerOptions {
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The device's real clock.
3
+ *
4
+ * @buoy-gg/clock can override the APP's clock (Date.now, new Date). Buoy's
5
+ * own bookkeeping must keep real time regardless: license expiry, sync
6
+ * throttles and request deadlines would otherwise lock tools or stall when
7
+ * someone travels a month ahead. The clock package publishes the real clock
8
+ * on `globalThis.__buoyRealNow`; without it, Date.now is already real.
9
+ */
10
+ export declare function realNow(): number;
11
+ /**
12
+ * setTimeout that a clock jump never fires early. @buoy-gg/clock tracks the
13
+ * app's timers so a jump ahead can run the ones that come due; Buoy's own
14
+ * deadlines and heartbeats must not be among them.
15
+ */
16
+ export declare function realSetTimeout(callback: () => void, ms: number): ReturnType<typeof setTimeout>;
17
+ export declare function realClearTimeout(handle: unknown): void;
18
+ //# sourceMappingURL=realNow.d.ts.map