@artooi/ag-ui-web-component 0.45.0 → 0.47.0

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 (91) hide show
  1. package/CHANGELOG.md +146 -1
  2. package/README.md +191 -25
  3. package/dist/ag-ui-web-component.bundle.js +399 -157
  4. package/dist/ag-ui-web-component.bundle.js.map +4 -4
  5. package/dist/constants.d.ts +14 -1
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/core/ag_ui_chat.d.ts +47 -4
  8. package/dist/core/ag_ui_chat.d.ts.map +1 -1
  9. package/dist/core/chat_registry.d.ts +23 -0
  10. package/dist/core/chat_registry.d.ts.map +1 -0
  11. package/dist/core/events/run_finished_detail.d.ts +6 -0
  12. package/dist/core/events/run_finished_detail.d.ts.map +1 -1
  13. package/dist/core/events/thread_detail.d.ts +27 -0
  14. package/dist/core/events/thread_detail.d.ts.map +1 -0
  15. package/dist/core/run_handlers.d.ts +6 -1
  16. package/dist/core/run_handlers.d.ts.map +1 -1
  17. package/dist/dom/animations.d.ts +21 -6
  18. package/dist/dom/animations.d.ts.map +1 -1
  19. package/dist/dom/highlight_overlay.d.ts +7 -1
  20. package/dist/dom/highlight_overlay.d.ts.map +1 -1
  21. package/dist/dom/ring_color.d.ts +14 -0
  22. package/dist/dom/ring_color.d.ts.map +1 -0
  23. package/dist/index.d.ts +3 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +857 -86
  26. package/dist/index.js.map +4 -4
  27. package/dist/tools/tool_catalog.d.ts +5 -0
  28. package/dist/tools/tool_catalog.d.ts.map +1 -1
  29. package/dist/tools/tool_dispatch.d.ts.map +1 -1
  30. package/dist/ui/history/conversation_history.d.ts +10 -1
  31. package/dist/ui/history/conversation_history.d.ts.map +1 -1
  32. package/dist/ui/interrupts/confirmation_styles.d.ts.map +1 -1
  33. package/dist/ui/placement/panel_placement.d.ts +6 -0
  34. package/dist/ui/placement/panel_placement.d.ts.map +1 -1
  35. package/dist/ui/placement/small_viewport_styles.d.ts.map +1 -1
  36. package/dist/ui/placement/surface_for.d.ts +12 -1
  37. package/dist/ui/placement/surface_for.d.ts.map +1 -1
  38. package/dist/ui/progress/thoughts_styles.d.ts.map +1 -1
  39. package/dist/ui/progress/tool_call_card.d.ts +8 -0
  40. package/dist/ui/progress/tool_call_card.d.ts.map +1 -1
  41. package/dist/ui/progress/tool_group_styles.d.ts +2 -0
  42. package/dist/ui/progress/tool_group_styles.d.ts.map +1 -0
  43. package/dist/ui/progress/tool_step_group.d.ts +47 -0
  44. package/dist/ui/progress/tool_step_group.d.ts.map +1 -0
  45. package/dist/ui/progress/tool_step_styles.d.ts.map +1 -1
  46. package/dist/ui/shell/token_styles.d.ts.map +1 -1
  47. package/dist/ui/styles.d.ts.map +1 -1
  48. package/dist/ui/themes/ledger_styles.d.ts.map +1 -1
  49. package/dist/ui/themes/soft_styles.d.ts.map +1 -1
  50. package/dist/ui/transcript/groups_tool_steps.d.ts +13 -0
  51. package/dist/ui/transcript/groups_tool_steps.d.ts.map +1 -0
  52. package/dist/ui/transcript/message_styles.d.ts.map +1 -1
  53. package/dist/ui/transcript/transcript.d.ts +16 -1
  54. package/dist/ui/transcript/transcript.d.ts.map +1 -1
  55. package/dist/ui/ui_strings.d.ts +18 -0
  56. package/dist/ui/ui_strings.d.ts.map +1 -1
  57. package/package.json +1 -1
  58. package/src/constants.ts +15 -1
  59. package/src/core/ag_ui_chat.ts +122 -11
  60. package/src/core/chat_registry.ts +53 -0
  61. package/src/core/events/run_finished_detail.ts +6 -0
  62. package/src/core/events/thread_detail.ts +26 -0
  63. package/src/core/run_handlers.ts +9 -4
  64. package/src/dom/animations.ts +30 -31
  65. package/src/dom/highlight_overlay.ts +9 -5
  66. package/src/dom/ring_color.ts +85 -0
  67. package/src/index.ts +3 -0
  68. package/src/tools/tool_catalog.ts +23 -10
  69. package/src/tools/tool_dispatch.ts +26 -11
  70. package/src/ui/history/conversation_history.ts +28 -4
  71. package/src/ui/interrupts/confirmation_styles.ts +0 -2
  72. package/src/ui/placement/embedded_styles.ts +2 -2
  73. package/src/ui/placement/panel_placement.ts +34 -9
  74. package/src/ui/placement/preset_styles.ts +1 -1
  75. package/src/ui/placement/sidebar_styles.ts +1 -1
  76. package/src/ui/placement/small_viewport_styles.ts +5 -0
  77. package/src/ui/placement/surface_for.ts +12 -1
  78. package/src/ui/progress/thoughts_styles.ts +0 -2
  79. package/src/ui/progress/tool_call_card.ts +29 -8
  80. package/src/ui/progress/tool_group_styles.ts +232 -0
  81. package/src/ui/progress/tool_step_group.ts +272 -0
  82. package/src/ui/progress/tool_step_styles.ts +0 -2
  83. package/src/ui/shell/token_styles.ts +4 -2
  84. package/src/ui/styles.ts +5 -0
  85. package/src/ui/themes/ledger_styles.ts +15 -0
  86. package/src/ui/themes/soft_styles.ts +20 -0
  87. package/src/ui/transcript/groups_tool_steps.ts +16 -0
  88. package/src/ui/transcript/message_styles.ts +0 -2
  89. package/src/ui/transcript/transcript.ts +109 -3
  90. package/src/ui/ui_strings.ts +31 -0
  91. package/src/version.ts +1 -1
@@ -8,8 +8,14 @@ import { fillUiString } from "../fill_ui_string.js";
8
8
  import { prettifyToolName } from "../progress/prettify_tool_name.js";
9
9
  import { renderRunNotice } from "../progress/run_notice.js";
10
10
  import { ThoughtsBlock } from "../progress/thoughts_block.js";
11
- import { ToolCallCard, type ToolPayload } from "../progress/tool_call_card.js";
11
+ import {
12
+ ToolCallCard,
13
+ type ToolDisplayMode,
14
+ type ToolPayload,
15
+ } from "../progress/tool_call_card.js";
16
+ import { ToolStepGroup } from "../progress/tool_step_group.js";
12
17
  import type { UiStrings } from "../ui_strings.js";
18
+ import { groupsToolSteps } from "./groups_tool_steps.js";
13
19
  import { renderMarkdown } from "./render_markdown.js";
14
20
  import { renderOrWarn } from "./render_or_warn.js";
15
21
  import { wrapWords } from "./reveal_words.js";
@@ -35,6 +41,8 @@ export interface TranscriptHost {
35
41
  readonly serverSummary: (name: string) => string | undefined;
36
42
  /** The element's `formatToolPayload`, asked per region of a card. */
37
43
  readonly formatToolPayload: (payload: ToolPayload) => Node | string | null;
44
+ /** The element's `toolDisplay`, read per card: it decides whether calls fold into a step group. */
45
+ readonly toolDisplay: () => ToolDisplayMode;
38
46
  }
39
47
 
40
48
  /**
@@ -54,6 +62,12 @@ export class Transcript {
54
62
  readonly #toolCards = new Map<string, ToolCallCard>();
55
63
  /** Card elements by call id, so a rendering handler can find its own card. */
56
64
  readonly #cardElements = new Map<string, HTMLElement>();
65
+ /**
66
+ * Cards whose call is being run, by call id. A card leaves the awaiting ones
67
+ * the moment its call is dispatched, and a handler that opens a prompt on its
68
+ * own card is still running long after, so it is found here.
69
+ */
70
+ readonly #running = new Map<string | undefined, ToolCallCard>();
57
71
  /**
58
72
  * Call ids whose card was already settled from a streamed server-side result
59
73
  * (`TOOL_CALL_RESULT`), so the post-run executeTool sweep doesn't overwrite
@@ -74,6 +88,24 @@ export class Transcript {
74
88
  // the answer group while a reasoning model thinks and collapsed once the
75
89
  // answer's first text token arrives. `null` outside a reasoning turn.
76
90
  #thoughts: ThoughtsBlock | null = null;
91
+ /** The step group behind each group element, so a new card can find its run. */
92
+ readonly #stepGroups = new WeakMap<Element, ToolStepGroup>();
93
+ /**
94
+ * An empty comment after each step group that has rendered output, which
95
+ * every later output is placed before, so a group's outputs come out in call
96
+ * order. Every card of a round joins its group before any handler runs, so
97
+ * placing each output straight after the group would put the newest first;
98
+ * and a marker rather than the last output, because an output may be a
99
+ * fragment, which leaves nothing behind to place the next one after.
100
+ */
101
+ readonly #groupEnds = new WeakMap<Element, Comment>();
102
+ /**
103
+ * The step group element each placed output belongs to. A tool's own output
104
+ * does not end its group: the next call joins the group above it. Without
105
+ * that, replay -- which draws each restored call's output before the next
106
+ * call's card -- would split a run the live stream drew as one group.
107
+ */
108
+ readonly #outputGroups = new WeakMap<Node, Element>();
77
109
 
78
110
  constructor(host: TranscriptHost) {
79
111
  this.#host = host;
@@ -185,6 +217,20 @@ export class Transcript {
185
217
  forgetCards(): void {
186
218
  this.#serverSettled.clear();
187
219
  this.#cardElements.clear();
220
+ this.#running.clear();
221
+ }
222
+
223
+ /** Remember the card of a call being run, for {@link setAsking}. */
224
+ holdRunning(callId: string, card: ToolCallCard): void {
225
+ this.#running.set(callId, card);
226
+ }
227
+
228
+ /**
229
+ * Say whether a prompt is open on the card of a running call. A call id of
230
+ * none, or one no card was held for, has no card to say it on.
231
+ */
232
+ setAsking(callId: string | undefined, asking: boolean): void {
233
+ this.#running.get(callId)?.setAsking(asking);
188
234
  }
189
235
 
190
236
  /** Empty the list back to its empty-state region. The last half of wiping it. */
@@ -383,7 +429,26 @@ export class Transcript {
383
429
  // `after` rather than an insert-or-append branch: both callers set the card
384
430
  // element immediately before calling, and a parentless anchor makes `after`
385
431
  // a no-op, so the alternative would be a branch nothing can reach.
386
- this.#cardElements.get(call.id)?.after(node);
432
+ //
433
+ // A card folded into a step group has its output placed after the group
434
+ // rather than inside it, so a chart is never hidden one click down.
435
+ const anchor = this.#cardElements.get(call.id);
436
+ const group = anchor?.closest(".tool-group");
437
+ if (group === null || group === undefined) {
438
+ anchor?.after(node);
439
+ } else {
440
+ let end = this.#groupEnds.get(group);
441
+ if (end === undefined) {
442
+ end = document.createComment("");
443
+ group.after(end);
444
+ this.#groupEnds.set(group, end);
445
+ }
446
+ const placed = node instanceof DocumentFragment ? [...node.children] : [node];
447
+ end.before(node);
448
+ for (const output of placed) {
449
+ this.#outputGroups.set(output, group);
450
+ }
451
+ }
387
452
  this.afterGrew();
388
453
  }
389
454
 
@@ -421,9 +486,50 @@ export class Transcript {
421
486
  formatPayload: (payload) => this.#host.formatToolPayload(payload),
422
487
  });
423
488
  this.#toolCards.set(call.id, card);
424
- this.ensureGroup().appendChild(card.element);
489
+ if (groupsToolSteps(this.#host.toolDisplay())) {
490
+ this.#stepGroup().add(card.element, summary);
491
+ } else {
492
+ this.ensureGroup().appendChild(card.element);
493
+ }
425
494
  this.updateEmptyState();
426
495
  this.follow();
427
496
  return card;
428
497
  }
498
+
499
+ /**
500
+ * Open the step group ``card`` sits in, at once, ahead of a prompt about to be
501
+ * drawn inside it. A no-op for a card drawn in a card display mode, which has
502
+ * no group.
503
+ */
504
+ revealStep(card: ToolCallCard): void {
505
+ const group = card.element.closest(".tool-group");
506
+ (group === null ? undefined : this.#stepGroups.get(group))?.reveal();
507
+ }
508
+
509
+ /**
510
+ * The step group a new card joins. Consecutive cards share one, and so do
511
+ * cards separated only by the group's own rendered output; anything else in
512
+ * between (text, a confirmation, a question) starts the next.
513
+ *
514
+ * The pending dots are not skipped over: a tool call takes them down before
515
+ * its card is drawn, so they are never what a card finds at the foot of the
516
+ * turn.
517
+ */
518
+ #stepGroup(): ToolStepGroup {
519
+ const answer = this.ensureGroup();
520
+ const last = answer.lastElementChild;
521
+ const existing =
522
+ last === null ? undefined : this.#stepGroups.get(this.#outputGroups.get(last) ?? last);
523
+ if (existing !== undefined) {
524
+ return existing;
525
+ }
526
+ const group = new ToolStepGroup(this.#host.strings());
527
+ this.#stepGroups.set(group.element, group);
528
+ if (last === null) {
529
+ answer.prepend(group.element);
530
+ } else {
531
+ last.after(group.element);
532
+ }
533
+ return group;
534
+ }
429
535
  }
@@ -184,6 +184,29 @@ export interface UiStrings {
184
184
  /** Label on the toggle that expands a tool card's body. */
185
185
  details: string;
186
186
 
187
+ // ── Tool-step group ─────────────────────────────────────────────────────────
188
+ // The row a run's consecutive calls fold into under the default
189
+ // data-tool-display. A group of one shows that call's own label instead, so
190
+ // the three labels are filled with 2 or more; the notes count from 1.
191
+ /** The group's label while a step waits on the user. Token: `{count}` (steps). */
192
+ toolGroupSteps: string;
193
+ /** The group's label while a step runs. Token: `{count}` (steps). */
194
+ toolGroupWorking: string;
195
+ /** The group's label once every step has settled. Token: `{count}` (steps). */
196
+ toolGroupWorked: string;
197
+ /** Note on the group's row: steps waiting on the user. Token: `{count}`. */
198
+ toolGroupWaiting: string;
199
+ /** Note on the group's row: steps that failed. Token: `{count}`. */
200
+ toolGroupFailed: string;
201
+ /** Note on the group's row: steps that were declined. Token: `{count}`. */
202
+ toolGroupDeclined: string;
203
+ /**
204
+ * Set after a step's label when an earlier step in its group has the same
205
+ * one, so two "Fill field" steps read "Fill field" and "Fill field (2)".
206
+ * Grouped mode only. Token: `{n}` (which occurrence, from 2).
207
+ */
208
+ toolStepRepeat: string;
209
+
187
210
  // ── Delegated sub-agent ─────────────────────────────────────────────────────
188
211
  /**
189
212
  * The delegation row's text before the server's own status line lands.
@@ -423,6 +446,14 @@ export const DEFAULT_UI_STRINGS: UiStrings = {
423
446
  interruptedLabel: "Not finished",
424
447
  details: "Details",
425
448
 
449
+ toolGroupSteps: "{count} steps",
450
+ toolGroupWorking: "Working through {count} steps",
451
+ toolGroupWorked: "Worked through {count} steps",
452
+ toolGroupWaiting: "{count} waiting for you",
453
+ toolGroupFailed: "{count} failed",
454
+ toolGroupDeclined: "{count} declined",
455
+ toolStepRepeat: "({n})",
456
+
426
457
  subAgentWorking: "Working…",
427
458
  subAgentDelegatedTo: "Delegated to {agent}",
428
459
  subAgentFinished: "{agent} finished",
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION: string = "0.45.0";
1
+ export const VERSION: string = "0.47.0";