@buoy-gg/agent-core 7.0.33

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 (138) hide show
  1. package/LICENSE +58 -0
  2. package/README.md +42 -0
  3. package/lib/commonjs/blocks/receipts.js +702 -0
  4. package/lib/commonjs/blocks/receipts.js.map +1 -0
  5. package/lib/commonjs/blocks/types.js +119 -0
  6. package/lib/commonjs/blocks/types.js.map +1 -0
  7. package/lib/commonjs/blocks/uiTool.js +994 -0
  8. package/lib/commonjs/blocks/uiTool.js.map +1 -0
  9. package/lib/commonjs/catalog/catalog.g.js +4044 -0
  10. package/lib/commonjs/catalog/catalog.g.js.map +1 -0
  11. package/lib/commonjs/catalog/catalog.source.json +4956 -0
  12. package/lib/commonjs/catalog/snapshotReads.js +256 -0
  13. package/lib/commonjs/catalog/snapshotReads.js.map +1 -0
  14. package/lib/commonjs/catalog/toProviderTools.js +107 -0
  15. package/lib/commonjs/catalog/toProviderTools.js.map +1 -0
  16. package/lib/commonjs/catalog/validateParams.js +129 -0
  17. package/lib/commonjs/catalog/validateParams.js.map +1 -0
  18. package/lib/commonjs/context/buildContextPack.js +141 -0
  19. package/lib/commonjs/context/buildContextPack.js.map +1 -0
  20. package/lib/commonjs/effects/ledger.js +229 -0
  21. package/lib/commonjs/effects/ledger.js.map +1 -0
  22. package/lib/commonjs/engine/effectFor.js +95 -0
  23. package/lib/commonjs/engine/effectFor.js.map +1 -0
  24. package/lib/commonjs/engine/runAgentTurn.js +667 -0
  25. package/lib/commonjs/engine/runAgentTurn.js.map +1 -0
  26. package/lib/commonjs/engine/systemPrompt.js +86 -0
  27. package/lib/commonjs/engine/systemPrompt.js.map +1 -0
  28. package/lib/commonjs/index.js +288 -0
  29. package/lib/commonjs/index.js.map +1 -0
  30. package/lib/commonjs/package.json +1 -0
  31. package/lib/commonjs/policy/labels.js +303 -0
  32. package/lib/commonjs/policy/labels.js.map +1 -0
  33. package/lib/commonjs/policy/policy.js +143 -0
  34. package/lib/commonjs/policy/policy.js.map +1 -0
  35. package/lib/commonjs/policy/redact.js +135 -0
  36. package/lib/commonjs/policy/redact.js.map +1 -0
  37. package/lib/commonjs/providers/anthropic.js +272 -0
  38. package/lib/commonjs/providers/anthropic.js.map +1 -0
  39. package/lib/commonjs/providers/openai.js +193 -0
  40. package/lib/commonjs/providers/openai.js.map +1 -0
  41. package/lib/commonjs/providers/sse.js +104 -0
  42. package/lib/commonjs/providers/sse.js.map +1 -0
  43. package/lib/commonjs/providers/types.js +6 -0
  44. package/lib/commonjs/providers/types.js.map +1 -0
  45. package/lib/commonjs/session.js +173 -0
  46. package/lib/commonjs/session.js.map +1 -0
  47. package/lib/commonjs/types.js +2 -0
  48. package/lib/commonjs/types.js.map +1 -0
  49. package/lib/module/blocks/receipts.js +696 -0
  50. package/lib/module/blocks/receipts.js.map +1 -0
  51. package/lib/module/blocks/types.js +113 -0
  52. package/lib/module/blocks/types.js.map +1 -0
  53. package/lib/module/blocks/uiTool.js +987 -0
  54. package/lib/module/blocks/uiTool.js.map +1 -0
  55. package/lib/module/catalog/catalog.g.js +4040 -0
  56. package/lib/module/catalog/catalog.g.js.map +1 -0
  57. package/lib/module/catalog/catalog.source.json +4956 -0
  58. package/lib/module/catalog/snapshotReads.js +252 -0
  59. package/lib/module/catalog/snapshotReads.js.map +1 -0
  60. package/lib/module/catalog/toProviderTools.js +101 -0
  61. package/lib/module/catalog/toProviderTools.js.map +1 -0
  62. package/lib/module/catalog/validateParams.js +124 -0
  63. package/lib/module/catalog/validateParams.js.map +1 -0
  64. package/lib/module/context/buildContextPack.js +138 -0
  65. package/lib/module/context/buildContextPack.js.map +1 -0
  66. package/lib/module/effects/ledger.js +223 -0
  67. package/lib/module/effects/ledger.js.map +1 -0
  68. package/lib/module/engine/effectFor.js +91 -0
  69. package/lib/module/engine/effectFor.js.map +1 -0
  70. package/lib/module/engine/runAgentTurn.js +663 -0
  71. package/lib/module/engine/runAgentTurn.js.map +1 -0
  72. package/lib/module/engine/systemPrompt.js +82 -0
  73. package/lib/module/engine/systemPrompt.js.map +1 -0
  74. package/lib/module/index.js +30 -0
  75. package/lib/module/index.js.map +1 -0
  76. package/lib/module/policy/labels.js +296 -0
  77. package/lib/module/policy/labels.js.map +1 -0
  78. package/lib/module/policy/policy.js +137 -0
  79. package/lib/module/policy/policy.js.map +1 -0
  80. package/lib/module/policy/redact.js +128 -0
  81. package/lib/module/policy/redact.js.map +1 -0
  82. package/lib/module/providers/anthropic.js +268 -0
  83. package/lib/module/providers/anthropic.js.map +1 -0
  84. package/lib/module/providers/openai.js +189 -0
  85. package/lib/module/providers/openai.js.map +1 -0
  86. package/lib/module/providers/sse.js +99 -0
  87. package/lib/module/providers/sse.js.map +1 -0
  88. package/lib/module/providers/types.js +4 -0
  89. package/lib/module/providers/types.js.map +1 -0
  90. package/lib/module/session.js +168 -0
  91. package/lib/module/session.js.map +1 -0
  92. package/lib/module/types.js +2 -0
  93. package/lib/module/types.js.map +1 -0
  94. package/lib/typescript/blocks/receipts.d.ts +32 -0
  95. package/lib/typescript/blocks/receipts.d.ts.map +1 -0
  96. package/lib/typescript/blocks/types.d.ts +576 -0
  97. package/lib/typescript/blocks/types.d.ts.map +1 -0
  98. package/lib/typescript/blocks/uiTool.d.ts +15 -0
  99. package/lib/typescript/blocks/uiTool.d.ts.map +1 -0
  100. package/lib/typescript/catalog/catalog.g.d.ts +11 -0
  101. package/lib/typescript/catalog/catalog.g.d.ts.map +1 -0
  102. package/lib/typescript/catalog/snapshotReads.d.ts +37 -0
  103. package/lib/typescript/catalog/snapshotReads.d.ts.map +1 -0
  104. package/lib/typescript/catalog/toProviderTools.d.ts +52 -0
  105. package/lib/typescript/catalog/toProviderTools.d.ts.map +1 -0
  106. package/lib/typescript/catalog/validateParams.d.ts +33 -0
  107. package/lib/typescript/catalog/validateParams.d.ts.map +1 -0
  108. package/lib/typescript/context/buildContextPack.d.ts +32 -0
  109. package/lib/typescript/context/buildContextPack.d.ts.map +1 -0
  110. package/lib/typescript/effects/ledger.d.ts +119 -0
  111. package/lib/typescript/effects/ledger.d.ts.map +1 -0
  112. package/lib/typescript/engine/effectFor.d.ts +21 -0
  113. package/lib/typescript/engine/effectFor.d.ts.map +1 -0
  114. package/lib/typescript/engine/runAgentTurn.d.ts +140 -0
  115. package/lib/typescript/engine/runAgentTurn.d.ts.map +1 -0
  116. package/lib/typescript/engine/systemPrompt.d.ts +49 -0
  117. package/lib/typescript/engine/systemPrompt.d.ts.map +1 -0
  118. package/lib/typescript/index.d.ts +29 -0
  119. package/lib/typescript/index.d.ts.map +1 -0
  120. package/lib/typescript/policy/labels.d.ts +10 -0
  121. package/lib/typescript/policy/labels.d.ts.map +1 -0
  122. package/lib/typescript/policy/policy.d.ts +106 -0
  123. package/lib/typescript/policy/policy.d.ts.map +1 -0
  124. package/lib/typescript/policy/redact.d.ts +37 -0
  125. package/lib/typescript/policy/redact.d.ts.map +1 -0
  126. package/lib/typescript/providers/anthropic.d.ts +22 -0
  127. package/lib/typescript/providers/anthropic.d.ts.map +1 -0
  128. package/lib/typescript/providers/openai.d.ts +19 -0
  129. package/lib/typescript/providers/openai.d.ts.map +1 -0
  130. package/lib/typescript/providers/sse.d.ts +18 -0
  131. package/lib/typescript/providers/sse.d.ts.map +1 -0
  132. package/lib/typescript/providers/types.d.ts +129 -0
  133. package/lib/typescript/providers/types.d.ts.map +1 -0
  134. package/lib/typescript/session.d.ts +58 -0
  135. package/lib/typescript/session.d.ts.map +1 -0
  136. package/lib/typescript/types.d.ts +119 -0
  137. package/lib/typescript/types.d.ts.map +1 -0
  138. package/package.json +58 -0
@@ -0,0 +1,987 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * `buoy_ui` — the one tool the model uses to SHOW or ASK instead of writing
5
+ * prose. One tool with `action` as the block kind, like every other Buoy
6
+ * tool, so tool selection stays good; the params are the block itself.
7
+ *
8
+ * Validation is the same `validateParams` every other action gets, and an
9
+ * invalid block goes back as a schema error for self-correction. A valid
10
+ * block is stamped with an id and yielded as a `block` event; an Ask block
11
+ * also ends the turn (see runAgentTurn).
12
+ */
13
+ import { validateParams } from "../catalog/validateParams";
14
+ import { CAPS, MODEL_KINDS } from "./types";
15
+ export const UI_TOOL_NAME = "buoy_ui";
16
+ const tone = {
17
+ type: "string",
18
+ enum: ["muted", "accent", "warning", "danger", "info"]
19
+ };
20
+ const action = {
21
+ type: "object",
22
+ properties: {
23
+ label: {
24
+ type: "string",
25
+ description: "Button text, 1–4 words."
26
+ },
27
+ primary: {
28
+ type: "boolean"
29
+ },
30
+ send: {
31
+ type: "string",
32
+ description: "Text sent as the user's next message when tapped."
33
+ },
34
+ dispatch: {
35
+ type: "object",
36
+ description: "A Buoy action to run when tapped — same policy and undo as if you called it.",
37
+ properties: {
38
+ toolId: {
39
+ type: "string"
40
+ },
41
+ action: {
42
+ type: "string"
43
+ },
44
+ params: {
45
+ type: "object"
46
+ }
47
+ },
48
+ required: ["toolId", "action"]
49
+ },
50
+ openTool: {
51
+ type: "object",
52
+ properties: {
53
+ toolId: {
54
+ type: "string"
55
+ },
56
+ select: {
57
+ type: "string"
58
+ }
59
+ },
60
+ required: ["toolId"]
61
+ },
62
+ minimize: {
63
+ type: "boolean",
64
+ description: "Collapse the chat so the user can look at the app."
65
+ }
66
+ },
67
+ required: ["label"],
68
+ additionalProperties: false
69
+ };
70
+ const cell = {
71
+ anyOf: [{
72
+ type: "string"
73
+ }, {
74
+ type: "object",
75
+ properties: {
76
+ text: {
77
+ type: "string"
78
+ },
79
+ tone
80
+ },
81
+ required: ["text"]
82
+ }]
83
+ };
84
+
85
+ /** Per-kind param schemas. Keys are block kinds; `kind` itself is the `action`. */
86
+ export const UI_PARAMS = {
87
+ choice: {
88
+ type: "object",
89
+ properties: {
90
+ question: {
91
+ type: "string",
92
+ description: "`title` is accepted as a synonym."
93
+ },
94
+ title: {
95
+ type: "string",
96
+ description: "Synonym for `question`."
97
+ },
98
+ options: {
99
+ type: "array",
100
+ maxItems: CAPS.choiceOptions,
101
+ items: {
102
+ type: "object",
103
+ properties: {
104
+ id: {
105
+ type: "string"
106
+ },
107
+ label: {
108
+ type: "string"
109
+ },
110
+ detail: {
111
+ type: "string"
112
+ }
113
+ },
114
+ required: ["id", "label"]
115
+ }
116
+ },
117
+ allowFreeText: {
118
+ type: "boolean"
119
+ }
120
+ },
121
+ // `question` is satisfied by `title` too — see normaliseChoice. Same
122
+ // lesson the confirm block cost us: a schema that rejects the obvious
123
+ // synonym sends a model into a retry loop and the user is never asked.
124
+ required: ["options"],
125
+ additionalProperties: false
126
+ },
127
+ confirm: {
128
+ type: "object",
129
+ properties: {
130
+ title: {
131
+ type: "string",
132
+ description: "Optional heading. Defaults to \"Confirm\"."
133
+ },
134
+ change: {
135
+ type: "string",
136
+ description: "What will change, in the user's words. `message` is accepted as a synonym."
137
+ },
138
+ message: {
139
+ type: "string",
140
+ description: "Synonym for `change`."
141
+ },
142
+ consequence: {
143
+ type: "string"
144
+ },
145
+ approveLabel: {
146
+ type: "string"
147
+ },
148
+ declineLabel: {
149
+ type: "string"
150
+ }
151
+ },
152
+ // ONLY `change` is required, and `message` satisfies it (see
153
+ // normaliseConfirm). Requiring both `title` AND `change` while rejecting
154
+ // `message` sent a live model into a four-attempt failure loop — it kept
155
+ // sending the universal {title, message} shape, and the validator
156
+ // answered "change: required" then "title: required", which reads as
157
+ // contradictory. It gave up and the user never got asked.
158
+ required: [],
159
+ additionalProperties: false
160
+ },
161
+ input: {
162
+ type: "object",
163
+ properties: {
164
+ label: {
165
+ type: "string"
166
+ },
167
+ type: {
168
+ type: "string",
169
+ enum: ["text", "number", "secret"]
170
+ },
171
+ placeholder: {
172
+ type: "string"
173
+ },
174
+ submitLabel: {
175
+ type: "string"
176
+ }
177
+ },
178
+ required: ["label"],
179
+ additionalProperties: false
180
+ },
181
+ table: {
182
+ type: "object",
183
+ properties: {
184
+ title: {
185
+ type: "string"
186
+ },
187
+ columns: {
188
+ type: "array",
189
+ maxItems: 4,
190
+ items: {
191
+ type: "string"
192
+ }
193
+ },
194
+ rows: {
195
+ type: "array",
196
+ items: {
197
+ type: "array",
198
+ items: cell
199
+ }
200
+ },
201
+ total: {
202
+ type: "number"
203
+ }
204
+ },
205
+ required: ["columns", "rows"],
206
+ additionalProperties: false
207
+ },
208
+ keyValue: {
209
+ type: "object",
210
+ properties: {
211
+ title: {
212
+ type: "string"
213
+ },
214
+ pairs: {
215
+ type: "array",
216
+ items: {
217
+ type: "object",
218
+ properties: {
219
+ key: {
220
+ type: "string"
221
+ },
222
+ value: {}
223
+ },
224
+ required: ["key"]
225
+ }
226
+ }
227
+ },
228
+ required: ["pairs"],
229
+ additionalProperties: false
230
+ },
231
+ list: {
232
+ type: "object",
233
+ properties: {
234
+ title: {
235
+ type: "string"
236
+ },
237
+ items: {
238
+ type: "array",
239
+ items: {
240
+ type: "object",
241
+ properties: {
242
+ id: {
243
+ type: "string"
244
+ },
245
+ title: {
246
+ type: "string"
247
+ },
248
+ subtitle: {
249
+ type: "string"
250
+ },
251
+ trailing: {
252
+ type: "string"
253
+ },
254
+ image: {
255
+ type: "string",
256
+ description: "Only a URL you read from the app this turn."
257
+ },
258
+ tone,
259
+ action
260
+ },
261
+ required: ["title"]
262
+ }
263
+ },
264
+ total: {
265
+ type: "number"
266
+ }
267
+ },
268
+ required: ["items"],
269
+ additionalProperties: false
270
+ },
271
+ imageGrid: {
272
+ type: "object",
273
+ properties: {
274
+ title: {
275
+ type: "string"
276
+ },
277
+ images: {
278
+ type: "array",
279
+ maxItems: CAPS.gridMax,
280
+ items: {
281
+ type: "object",
282
+ properties: {
283
+ url: {
284
+ type: "string",
285
+ description: "Only a URL you read from the app this turn."
286
+ },
287
+ alt: {
288
+ type: "string"
289
+ },
290
+ caption: {
291
+ type: "string"
292
+ }
293
+ },
294
+ required: ["url", "alt"]
295
+ }
296
+ },
297
+ total: {
298
+ type: "number"
299
+ }
300
+ },
301
+ required: ["images"],
302
+ additionalProperties: false
303
+ },
304
+ diff: {
305
+ type: "object",
306
+ properties: {
307
+ title: {
308
+ type: "string"
309
+ },
310
+ changes: {
311
+ type: "array",
312
+ items: {
313
+ type: "object",
314
+ properties: {
315
+ path: {
316
+ type: "string"
317
+ },
318
+ before: {},
319
+ after: {}
320
+ },
321
+ required: ["path"]
322
+ }
323
+ }
324
+ },
325
+ required: ["changes"],
326
+ additionalProperties: false
327
+ },
328
+ chart: {
329
+ type: "object",
330
+ properties: {
331
+ title: {
332
+ type: "string"
333
+ },
334
+ bars: {
335
+ type: "array",
336
+ maxItems: CAPS.chartBars,
337
+ items: {
338
+ type: "object",
339
+ properties: {
340
+ label: {
341
+ type: "string"
342
+ },
343
+ value: {
344
+ type: "number"
345
+ },
346
+ unit: {
347
+ type: "string"
348
+ },
349
+ tone
350
+ },
351
+ required: ["label", "value"]
352
+ }
353
+ },
354
+ max: {
355
+ type: "number"
356
+ }
357
+ },
358
+ required: ["bars"],
359
+ additionalProperties: false
360
+ },
361
+ steps: {
362
+ type: "object",
363
+ properties: {
364
+ title: {
365
+ type: "string"
366
+ },
367
+ steps: {
368
+ type: "array",
369
+ items: {
370
+ type: "object",
371
+ properties: {
372
+ text: {
373
+ type: "string"
374
+ },
375
+ state: {
376
+ type: "string",
377
+ enum: ["todo", "done", "failed"]
378
+ }
379
+ },
380
+ required: ["text"]
381
+ }
382
+ }
383
+ },
384
+ required: ["steps"],
385
+ additionalProperties: false
386
+ },
387
+ code: {
388
+ type: "object",
389
+ properties: {
390
+ title: {
391
+ type: "string"
392
+ },
393
+ language: {
394
+ type: "string",
395
+ enum: ["json", "text"]
396
+ },
397
+ text: {
398
+ type: "string"
399
+ }
400
+ },
401
+ required: ["text"],
402
+ additionalProperties: false
403
+ },
404
+ actions: {
405
+ type: "object",
406
+ properties: {
407
+ actions: {
408
+ type: "array",
409
+ maxItems: CAPS.actions,
410
+ items: action
411
+ }
412
+ },
413
+ required: ["actions"],
414
+ additionalProperties: false
415
+ },
416
+ suggestions: {
417
+ type: "object",
418
+ properties: {
419
+ chips: {
420
+ type: "array",
421
+ maxItems: 4,
422
+ items: {
423
+ type: "object",
424
+ properties: {
425
+ label: {
426
+ type: "string"
427
+ },
428
+ send: {
429
+ type: "string"
430
+ }
431
+ },
432
+ required: ["label"]
433
+ }
434
+ }
435
+ },
436
+ required: ["chips"],
437
+ additionalProperties: false
438
+ },
439
+ multiSelect: {
440
+ type: "object",
441
+ properties: {
442
+ question: {
443
+ type: "string"
444
+ },
445
+ options: {
446
+ type: "array",
447
+ maxItems: 12,
448
+ items: {
449
+ type: "object",
450
+ properties: {
451
+ id: {
452
+ type: "string"
453
+ },
454
+ label: {
455
+ type: "string"
456
+ },
457
+ detail: {
458
+ type: "string"
459
+ }
460
+ },
461
+ required: ["id", "label"]
462
+ }
463
+ },
464
+ min: {
465
+ type: "number"
466
+ },
467
+ max: {
468
+ type: "number"
469
+ },
470
+ submitLabel: {
471
+ type: "string"
472
+ }
473
+ },
474
+ required: ["question", "options"],
475
+ additionalProperties: false
476
+ },
477
+ select: {
478
+ type: "object",
479
+ properties: {
480
+ label: {
481
+ type: "string"
482
+ },
483
+ options: {
484
+ type: "array",
485
+ maxItems: 100,
486
+ items: {
487
+ type: "object",
488
+ properties: {
489
+ id: {
490
+ type: "string"
491
+ },
492
+ label: {
493
+ type: "string"
494
+ },
495
+ detail: {
496
+ type: "string"
497
+ }
498
+ },
499
+ required: ["id", "label"]
500
+ }
501
+ },
502
+ searchable: {
503
+ type: "boolean"
504
+ }
505
+ },
506
+ required: ["label", "options"],
507
+ additionalProperties: false
508
+ },
509
+ slider: {
510
+ type: "object",
511
+ properties: {
512
+ label: {
513
+ type: "string"
514
+ },
515
+ min: {
516
+ type: "number"
517
+ },
518
+ max: {
519
+ type: "number"
520
+ },
521
+ step: {
522
+ type: "number"
523
+ },
524
+ value: {
525
+ type: "number"
526
+ },
527
+ unit: {
528
+ type: "string"
529
+ }
530
+ },
531
+ required: ["label", "min", "max"],
532
+ additionalProperties: false
533
+ },
534
+ dateTime: {
535
+ type: "object",
536
+ properties: {
537
+ label: {
538
+ type: "string"
539
+ },
540
+ mode: {
541
+ type: "string",
542
+ enum: ["date", "time", "datetime"]
543
+ },
544
+ presets: {
545
+ type: "array",
546
+ items: {
547
+ type: "object",
548
+ properties: {
549
+ label: {
550
+ type: "string"
551
+ },
552
+ value: {
553
+ type: "string"
554
+ }
555
+ },
556
+ required: ["label", "value"]
557
+ }
558
+ }
559
+ },
560
+ required: ["label"],
561
+ additionalProperties: false
562
+ },
563
+ form: {
564
+ type: "object",
565
+ properties: {
566
+ title: {
567
+ type: "string"
568
+ },
569
+ fields: {
570
+ type: "array",
571
+ maxItems: 6,
572
+ items: {
573
+ type: "object"
574
+ }
575
+ },
576
+ submitLabel: {
577
+ type: "string"
578
+ }
579
+ },
580
+ required: ["fields"],
581
+ additionalProperties: false
582
+ },
583
+ proposal: {
584
+ type: "object",
585
+ properties: {
586
+ title: {
587
+ type: "string"
588
+ },
589
+ change: {
590
+ type: "string"
591
+ },
592
+ fields: {
593
+ type: "array",
594
+ maxItems: 6,
595
+ items: {
596
+ type: "object"
597
+ }
598
+ },
599
+ consequence: {
600
+ type: "string"
601
+ },
602
+ approveLabel: {
603
+ type: "string"
604
+ }
605
+ },
606
+ required: ["title", "change", "fields"],
607
+ additionalProperties: false
608
+ },
609
+ claim: {
610
+ type: "object",
611
+ properties: {
612
+ text: {
613
+ type: "string"
614
+ },
615
+ sources: {
616
+ type: "array",
617
+ maxItems: 4,
618
+ items: {
619
+ type: "object",
620
+ properties: {
621
+ label: {
622
+ type: "string"
623
+ },
624
+ detail: {
625
+ type: "string"
626
+ }
627
+ },
628
+ required: ["label"]
629
+ }
630
+ },
631
+ verify: action
632
+ },
633
+ required: ["text", "sources"],
634
+ additionalProperties: false
635
+ },
636
+ details: {
637
+ type: "object",
638
+ properties: {
639
+ summary: {
640
+ type: "string"
641
+ },
642
+ body: {
643
+ type: "string"
644
+ },
645
+ open: {
646
+ type: "boolean"
647
+ }
648
+ },
649
+ required: ["summary", "body"],
650
+ additionalProperties: false
651
+ },
652
+ compare: {
653
+ type: "object",
654
+ properties: {
655
+ title: {
656
+ type: "string"
657
+ },
658
+ left: {
659
+ type: "object",
660
+ properties: {
661
+ title: {
662
+ type: "string"
663
+ },
664
+ pairs: {
665
+ type: "array",
666
+ items: {
667
+ type: "object"
668
+ }
669
+ }
670
+ },
671
+ required: ["title", "pairs"]
672
+ },
673
+ right: {
674
+ type: "object",
675
+ properties: {
676
+ title: {
677
+ type: "string"
678
+ },
679
+ pairs: {
680
+ type: "array",
681
+ items: {
682
+ type: "object"
683
+ }
684
+ }
685
+ },
686
+ required: ["title", "pairs"]
687
+ }
688
+ },
689
+ required: ["left", "right"],
690
+ additionalProperties: false
691
+ },
692
+ card: {
693
+ type: "object",
694
+ properties: {
695
+ title: {
696
+ type: "string"
697
+ },
698
+ subtitle: {
699
+ type: "string"
700
+ },
701
+ image: {
702
+ type: "string"
703
+ },
704
+ facts: {
705
+ type: "array",
706
+ maxItems: 6,
707
+ items: {
708
+ type: "object",
709
+ properties: {
710
+ label: {
711
+ type: "string"
712
+ },
713
+ value: {
714
+ type: "string"
715
+ },
716
+ tone
717
+ },
718
+ required: ["label", "value"]
719
+ }
720
+ },
721
+ actions: {
722
+ type: "array",
723
+ maxItems: CAPS.actions,
724
+ items: action
725
+ }
726
+ },
727
+ required: ["title"],
728
+ additionalProperties: false
729
+ },
730
+ cardCarousel: {
731
+ type: "object",
732
+ properties: {
733
+ title: {
734
+ type: "string"
735
+ },
736
+ cards: {
737
+ type: "array",
738
+ maxItems: 8,
739
+ items: {
740
+ type: "object"
741
+ }
742
+ },
743
+ total: {
744
+ type: "number"
745
+ }
746
+ },
747
+ required: ["cards"],
748
+ additionalProperties: false
749
+ },
750
+ sparkline: {
751
+ type: "object",
752
+ properties: {
753
+ title: {
754
+ type: "string"
755
+ },
756
+ series: {
757
+ type: "array",
758
+ maxItems: 120,
759
+ items: {
760
+ type: "number"
761
+ }
762
+ },
763
+ unit: {
764
+ type: "string"
765
+ },
766
+ label: {
767
+ type: "string"
768
+ },
769
+ current: {
770
+ type: "number"
771
+ }
772
+ },
773
+ required: ["series"],
774
+ additionalProperties: false
775
+ },
776
+ plan: {
777
+ type: "object",
778
+ properties: {
779
+ title: {
780
+ type: "string"
781
+ },
782
+ steps: {
783
+ type: "array",
784
+ maxItems: 10,
785
+ items: {
786
+ type: "object",
787
+ properties: {
788
+ text: {
789
+ type: "string"
790
+ },
791
+ state: {
792
+ type: "string",
793
+ enum: ["todo", "running", "done", "failed"]
794
+ }
795
+ },
796
+ required: ["text"]
797
+ }
798
+ },
799
+ pending: {
800
+ type: "boolean"
801
+ },
802
+ actions: {
803
+ type: "array",
804
+ maxItems: CAPS.actions,
805
+ items: action
806
+ }
807
+ },
808
+ required: ["title", "steps"],
809
+ additionalProperties: false
810
+ },
811
+ finding: {
812
+ type: "object",
813
+ properties: {
814
+ title: {
815
+ type: "string"
816
+ },
817
+ evidence: {
818
+ type: "array",
819
+ items: {
820
+ type: "object",
821
+ properties: {
822
+ label: {
823
+ type: "string"
824
+ },
825
+ value: {
826
+ type: "string"
827
+ },
828
+ tone
829
+ },
830
+ required: ["label", "value"]
831
+ }
832
+ },
833
+ actions: {
834
+ type: "array",
835
+ maxItems: CAPS.actions,
836
+ items: action
837
+ }
838
+ },
839
+ required: ["title", "evidence"],
840
+ additionalProperties: false
841
+ }
842
+ };
843
+ const KIND_HELP = {
844
+ choice: "ASK the user to pick one of 2–5 options when a request could mean different things. Ends your turn; their pick comes back as their next message.",
845
+ confirm: "ASK before a change you are guessing at (a shape you haven't read, a user you invented, anything destructive). Ends your turn.",
846
+ input: "ASK for one value you need (an order id, a quantity). Ends your turn.",
847
+ table: "Show rows of comparable facts — prices before/after, requests, counts. ≤4 columns, ≤8 rows; put the rest in total.",
848
+ keyValue: "Show one record's fields — a profile, a store's state, a stored value.",
849
+ list: "Show several things with a title each — items, orders, users. Add image only from URLs you read. Each item may carry one action.",
850
+ imageGrid: "Show pictures — menu items, loaded images. Only URLs you read from the app this turn. ≤24; grid up to 6, carousel after.",
851
+ diff: "Show what changed: path, before, after. Use for compare questions and after any write.",
852
+ chart: "Show numbers side by side as bars — render counts, timings, sizes. ≤8 bars.",
853
+ steps: "Show a procedure or a plan as a checklist (to reproduce, to test).",
854
+ code: "Show a raw value only when the user asked for the raw thing.",
855
+ actions: "Offer up to two buttons for what to do next instead of writing 'say X and I'll…'. Use send for a chat reply, dispatch to run an action directly, minimize to let them look at the app.",
856
+ finding: "Report something worth filing: a title plus evidence rows (request → status, screen → what it showed). Add a button to reproduce or open the tool.",
857
+ suggestions: "Offer 2–4 follow-up questions the user might ask next. Put it last.",
858
+ multiSelect: "ASK the user to pick several (which stores, which keys). Ends your turn.",
859
+ select: "ASK the user to pick one from a long list (routes, stores) — searchable. Ends your turn.",
860
+ slider: "ASK for a number in a range (a delay, a quantity). Ends your turn.",
861
+ dateTime: "ASK for a date or time. Ends your turn.",
862
+ form: "ASK for several coupled values at once. Ends your turn.",
863
+ proposal: "ASK to approve a change whose values the user may edit first. Ends your turn.",
864
+ claim: "State one fact with the evidence chips it rests on and a Verify button that re-reads it.",
865
+ details: "A collapsed detail the user can open — long explanations, raw values.",
866
+ compare: "Two things side by side with differences highlighted.",
867
+ card: "One entity: title, image, facts, up to two actions.",
868
+ cardCarousel: "3–8 cards to scan and pick from (scenarios, snapshots, items).",
869
+ sparkline: "A series over time — FPS, memory, request timing.",
870
+ plan: "Before multi-step work: the steps you intend, with Go/Stop. Update states as you go."
871
+ };
872
+
873
+ /** The provider-facing tool definition. */
874
+ export function uiProviderTool() {
875
+ const kinds = MODEL_KINDS.join(" | ");
876
+ const help = MODEL_KINDS.map(k => `- ${k}: ${KIND_HELP[k]}`).join("\n");
877
+ return {
878
+ name: UI_TOOL_NAME,
879
+ description: `Show the user something richer than text, or ask them something. Blocks render inline in the chat, ABOVE your text — so your text should say what the block means, never repeat it. Kinds: ${kinds}.\n${help}\n\nRules: choice/confirm/input END your turn — send them last, alone, with no other tool calls, and the answer arrives as the user's next message. Never put URLs, ids or numbers in a block that you did not read from a tool result this turn. Prefer the smallest block that answers.`,
880
+ inputSchema: {
881
+ type: "object",
882
+ properties: {
883
+ action: {
884
+ type: "string",
885
+ enum: [...MODEL_KINDS],
886
+ description: "The block kind."
887
+ },
888
+ params: {
889
+ type: "object",
890
+ description: "The block's fields; see the kind's schema."
891
+ }
892
+ },
893
+ required: ["action", "params"],
894
+ additionalProperties: false
895
+ }
896
+ };
897
+ }
898
+ let seq = 0;
899
+
900
+ /** Validate a `buoy_ui` call and build the block. */
901
+ /**
902
+ * Accept the shape models actually send for a confirm. `message` is the
903
+ * near-universal field name, and `title` alone is a perfectly clear ask —
904
+ * so fold them into the block's own vocabulary rather than bouncing the
905
+ * call. Returns null only when there is genuinely nothing to agree to.
906
+ */
907
+ function normaliseConfirm(params) {
908
+ const str = v => typeof v === "string" && v.trim() ? v.trim() : undefined;
909
+ const {
910
+ message,
911
+ ...rest
912
+ } = params;
913
+ const change = str(rest.change) ?? str(message) ?? str(rest.title);
914
+ if (!change) return null;
915
+ // When both arrived, the one we didn't use as `change` still carries
916
+ // meaning — keep it as the consequence line rather than dropping it.
917
+ const spare = str(rest.change) ? str(message) : undefined;
918
+ return {
919
+ ...rest,
920
+ title: str(rest.title) ?? "Confirm",
921
+ change,
922
+ consequence: str(rest.consequence) ?? spare
923
+ };
924
+ }
925
+
926
+ /** Accept `title` where the schema says `question` — see normaliseConfirm. */
927
+ function normaliseChoice(params) {
928
+ const str = v => typeof v === "string" && v.trim() ? v.trim() : undefined;
929
+ const {
930
+ title,
931
+ ...rest
932
+ } = params;
933
+ const question = str(rest.question) ?? str(title);
934
+ if (!question) return null;
935
+ return {
936
+ ...rest,
937
+ question
938
+ };
939
+ }
940
+ export function buildUiBlock(input) {
941
+ const kind = input.action;
942
+ if (!kind || !MODEL_KINDS.includes(kind)) {
943
+ return {
944
+ ok: false,
945
+ errors: [`"action" must be one of: ${MODEL_KINDS.join(", ")}`]
946
+ };
947
+ }
948
+ const schema = UI_PARAMS[kind];
949
+ const check = validateParams(input.params, schema);
950
+ if (!check.ok) return {
951
+ ok: false,
952
+ errors: check.errors
953
+ };
954
+ let params = input.params ?? {};
955
+ if (kind === "choice") {
956
+ const fixed = normaliseChoice(params);
957
+ if (!fixed) {
958
+ return {
959
+ ok: false,
960
+ errors: ['choice needs the question being asked: pass `question` (or `title`), e.g. { "question": "Which checkout?", "options": [...] }']
961
+ };
962
+ }
963
+ params = fixed;
964
+ }
965
+ if (kind === "confirm") {
966
+ const fixed = normaliseConfirm(params);
967
+ if (!fixed) {
968
+ return {
969
+ ok: false,
970
+ errors: ['confirm needs what the user is agreeing to: pass `change` (or `message`), e.g. { "change": "Wipe all app storage", "consequence": "This cannot be undone." }']
971
+ };
972
+ }
973
+ params = fixed;
974
+ }
975
+ const block = {
976
+ ...params,
977
+ kind,
978
+ id: `ui${++seq}`,
979
+ source: "model"
980
+ };
981
+ return {
982
+ ok: true,
983
+ errors: [],
984
+ block
985
+ };
986
+ }
987
+ //# sourceMappingURL=uiTool.js.map