@artooi/ag-ui-web-component 0.10.0 → 0.12.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 (45) hide show
  1. package/CHANGELOG.md +78 -1
  2. package/README.md +144 -7
  3. package/dist/ag-ui-web-component.bundle.js +237 -40
  4. package/dist/ag-ui-web-component.bundle.js.map +4 -4
  5. package/dist/core/ag_ui_chat.d.ts +29 -0
  6. package/dist/core/ag_ui_chat.d.ts.map +1 -1
  7. package/dist/core/agui_client.d.ts +28 -1
  8. package/dist/core/agui_client.d.ts.map +1 -1
  9. package/dist/core/run_index.d.ts +50 -0
  10. package/dist/core/run_index.d.ts.map +1 -0
  11. package/dist/index.d.ts +5 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +942 -101
  14. package/dist/index.js.map +4 -4
  15. package/dist/ui/approval_card.d.ts +51 -0
  16. package/dist/ui/approval_card.d.ts.map +1 -0
  17. package/dist/ui/attachment_chips.d.ts.map +1 -1
  18. package/dist/ui/attachment_tray.d.ts.map +1 -1
  19. package/dist/ui/checkpoint_menu.d.ts +32 -0
  20. package/dist/ui/checkpoint_menu.d.ts.map +1 -0
  21. package/dist/ui/question_card.d.ts +52 -0
  22. package/dist/ui/question_card.d.ts.map +1 -0
  23. package/dist/ui/skills_menu.d.ts.map +1 -1
  24. package/dist/ui/styles.d.ts +1 -1
  25. package/dist/ui/styles.d.ts.map +1 -1
  26. package/dist/ui/thoughts_block.d.ts.map +1 -1
  27. package/dist/ui/thread_drawer.d.ts.map +1 -1
  28. package/dist/ui/ui_strings.d.ts +26 -0
  29. package/dist/ui/ui_strings.d.ts.map +1 -1
  30. package/package.json +4 -4
  31. package/src/core/ag_ui_chat.ts +263 -4
  32. package/src/core/agui_client.ts +86 -11
  33. package/src/core/run_index.ts +91 -0
  34. package/src/index.ts +16 -0
  35. package/src/ui/approval_card.ts +119 -0
  36. package/src/ui/attachment_chips.ts +5 -0
  37. package/src/ui/attachment_tray.ts +8 -0
  38. package/src/ui/checkpoint_menu.ts +153 -0
  39. package/src/ui/question_card.ts +216 -0
  40. package/src/ui/skills_menu.ts +6 -0
  41. package/src/ui/styles.ts +197 -0
  42. package/src/ui/thoughts_block.ts +1 -0
  43. package/src/ui/thread_drawer.ts +11 -0
  44. package/src/ui/ui_strings.ts +45 -0
  45. package/src/version.ts +1 -1
package/src/ui/styles.ts CHANGED
@@ -1028,6 +1028,127 @@ export const STYLES = `
1028
1028
  color: #ffffff;
1029
1029
  }
1030
1030
 
1031
+ /* Approval card — the server-side-tool gate (approve/deny an interrupt). */
1032
+ .approval {
1033
+ align-self: stretch;
1034
+ box-sizing: border-box;
1035
+ display: flex;
1036
+ flex-direction: column;
1037
+ gap: 8px;
1038
+ padding: 12px;
1039
+ background: var(--ag-ui-bg);
1040
+ border: 1px solid var(--ag-ui-accent);
1041
+ border-radius: 10px;
1042
+ }
1043
+
1044
+ .approval[data-resolved] {
1045
+ opacity: 0.7;
1046
+ border-color: var(--ag-ui-border);
1047
+ }
1048
+
1049
+ .approval-body {
1050
+ font-weight: 600;
1051
+ }
1052
+
1053
+ .approval-actions {
1054
+ display: flex;
1055
+ gap: 8px;
1056
+ justify-content: flex-end;
1057
+ }
1058
+
1059
+ .approval-btn {
1060
+ border: 1px solid var(--ag-ui-border);
1061
+ border-radius: 8px;
1062
+ padding: 8px 14px;
1063
+ font: inherit;
1064
+ font-weight: 600;
1065
+ cursor: pointer;
1066
+ background: var(--ag-ui-bg);
1067
+ color: var(--ag-ui-fg);
1068
+ }
1069
+
1070
+ .approval-btn:disabled {
1071
+ cursor: default;
1072
+ opacity: 0.6;
1073
+ }
1074
+
1075
+ .approval-btn--approve {
1076
+ border-color: var(--ag-ui-accent);
1077
+ background: var(--ag-ui-accent);
1078
+ color: #ffffff;
1079
+ }
1080
+
1081
+ /* Question card — the built-in ask_user prompt (radios and/or free text). */
1082
+ .question {
1083
+ align-self: stretch;
1084
+ box-sizing: border-box;
1085
+ display: flex;
1086
+ flex-direction: column;
1087
+ gap: 8px;
1088
+ padding: 12px;
1089
+ background: var(--ag-ui-bg);
1090
+ border: 1px solid var(--ag-ui-accent);
1091
+ border-radius: 10px;
1092
+ }
1093
+
1094
+ .question[data-resolved] {
1095
+ opacity: 0.7;
1096
+ border-color: var(--ag-ui-border);
1097
+ }
1098
+
1099
+ .question-body {
1100
+ font-weight: 600;
1101
+ }
1102
+
1103
+ .question-options {
1104
+ display: flex;
1105
+ flex-direction: column;
1106
+ gap: 6px;
1107
+ }
1108
+
1109
+ .question-choice {
1110
+ display: flex;
1111
+ align-items: center;
1112
+ gap: 8px;
1113
+ cursor: pointer;
1114
+ }
1115
+
1116
+ .question-input {
1117
+ box-sizing: border-box;
1118
+ width: 100%;
1119
+ padding: 8px 10px;
1120
+ font: inherit;
1121
+ color: var(--ag-ui-fg);
1122
+ background: var(--ag-ui-bg);
1123
+ border: 1px solid var(--ag-ui-border);
1124
+ border-radius: 8px;
1125
+ }
1126
+
1127
+ .question-input:disabled {
1128
+ opacity: 0.6;
1129
+ }
1130
+
1131
+ .question-actions {
1132
+ display: flex;
1133
+ justify-content: flex-end;
1134
+ }
1135
+
1136
+ .question-btn {
1137
+ border: 1px solid var(--ag-ui-accent);
1138
+ border-radius: 8px;
1139
+ padding: 8px 14px;
1140
+ font: inherit;
1141
+ font-weight: 600;
1142
+ cursor: pointer;
1143
+ background: var(--ag-ui-accent);
1144
+ color: #ffffff;
1145
+ }
1146
+
1147
+ .question-btn:disabled {
1148
+ cursor: default;
1149
+ opacity: 0.6;
1150
+ }
1151
+
1031
1152
  /* Skills — chips row + the /-command palette, above the input. */
1032
1153
  .skill-chips {
1033
1154
  display: flex;
@@ -1108,6 +1229,82 @@ export const STYLES = `
1108
1229
  display: none;
1109
1230
  }
1110
1231
 
1232
+ .checkpoints {
1233
+ position: absolute;
1234
+ inset-block-start: 3rem;
1235
+ inset-inline: 0.75rem;
1236
+ z-index: 6;
1237
+ display: flex;
1238
+ flex-direction: column;
1239
+ gap: 0.25rem;
1240
+ padding: 0.5rem;
1241
+ border: 1px solid var(--agui-border, #d7d7dc);
1242
+ border-radius: 0.5rem;
1243
+ background: var(--agui-surface, #fff);
1244
+ box-shadow: 0 6px 24px rgb(0 0 0 / 12%);
1245
+ max-height: 60%;
1246
+ overflow-y: auto;
1247
+ }
1248
+
1249
+ .checkpoints[hidden] {
1250
+ display: none;
1251
+ }
1252
+
1253
+ .checkpoints-title {
1254
+ font-size: 0.75rem;
1255
+ font-weight: 600;
1256
+ opacity: 0.7;
1257
+ }
1258
+
1259
+ .checkpoints-empty {
1260
+ padding: 0.5rem 0.25rem;
1261
+ font-size: 0.8125rem;
1262
+ opacity: 0.7;
1263
+ }
1264
+
1265
+ .checkpoint-row {
1266
+ display: flex;
1267
+ align-items: center;
1268
+ gap: 0.5rem;
1269
+ padding: 0.25rem;
1270
+ border-radius: 0.375rem;
1271
+ }
1272
+
1273
+ .checkpoint-row:hover {
1274
+ background: var(--agui-hover, #f3f3f5);
1275
+ }
1276
+
1277
+ .checkpoint-label {
1278
+ flex: 1;
1279
+ font-size: 0.8125rem;
1280
+ white-space: nowrap;
1281
+ overflow: hidden;
1282
+ text-overflow: ellipsis;
1283
+ }
1284
+
1285
+ .checkpoint-branch {
1286
+ font-size: 0.6875rem;
1287
+ padding: 0 0.375rem;
1288
+ border-radius: 999px;
1289
+ background: var(--agui-hover, #f3f3f5);
1290
+ opacity: 0.8;
1291
+ }
1292
+
1293
+ .checkpoint-action {
1294
+ font: inherit;
1295
+ font-size: 0.75rem;
1296
+ cursor: pointer;
1297
+ padding: 0.125rem 0.5rem;
1298
+ border: 1px solid var(--agui-border, #d7d7dc);
1299
+ border-radius: 0.375rem;
1300
+ background: transparent;
1301
+ color: inherit;
1302
+ }
1303
+
1304
+ .checkpoint-action:hover {
1305
+ background: var(--agui-hover, #f3f3f5);
1306
+ }
1307
+
1111
1308
  .drawer-backdrop {
1112
1309
  position: absolute;
1113
1310
  inset: 0;
@@ -42,6 +42,7 @@ export class ThoughtsBlock {
42
42
 
43
43
  this.#label = document.createElement("span");
44
44
  this.#label.className = "thoughts-label";
45
+ this.#label.setAttribute("part", "thoughts-label");
45
46
  this.#label.textContent = strings.thinking;
46
47
  this.#toggle.append(this.#label);
47
48
 
@@ -196,12 +196,15 @@ export class ThreadDrawer {
196
196
  select.setAttribute("part", "drawer-row-select");
197
197
  const title = document.createElement("span");
198
198
  title.className = "drawer-row-title";
199
+ title.setAttribute("part", "drawer-row-title");
199
200
  title.textContent = meta.title;
200
201
  const time = document.createElement("span");
201
202
  time.className = "drawer-row-time";
203
+ time.setAttribute("part", "drawer-row-time");
202
204
  time.textContent = relativeTime(meta.updatedAt, undefined, this.#strings);
203
205
  const preview = document.createElement("span");
204
206
  preview.className = "drawer-row-preview";
207
+ preview.setAttribute("part", "drawer-row-preview");
205
208
  preview.textContent = meta.preview;
206
209
  select.append(title, time, preview);
207
210
  select.addEventListener("click", () => {
@@ -212,6 +215,7 @@ export class ThreadDrawer {
212
215
  const rename = document.createElement("button");
213
216
  rename.type = "button";
214
217
  rename.className = "drawer-row-rename";
218
+ rename.setAttribute("part", "drawer-row-rename");
215
219
  rename.title = this.#strings.rename;
216
220
  rename.setAttribute("aria-label", this.#strings.renameConversation);
217
221
  rename.textContent = "✎";
@@ -220,6 +224,7 @@ export class ThreadDrawer {
220
224
  const remove = document.createElement("button");
221
225
  remove.type = "button";
222
226
  remove.className = "drawer-row-delete";
227
+ remove.setAttribute("part", "drawer-row-delete");
223
228
  remove.title = this.#strings.delete;
224
229
  remove.setAttribute("aria-label", this.#strings.deleteConversation);
225
230
  remove.textContent = "🗑";
@@ -227,6 +232,7 @@ export class ThreadDrawer {
227
232
 
228
233
  const actions = document.createElement("div");
229
234
  actions.className = "drawer-row-actions";
235
+ actions.setAttribute("part", "drawer-row-actions");
230
236
  actions.append(rename, remove);
231
237
 
232
238
  row.append(select, actions);
@@ -238,6 +244,7 @@ export class ThreadDrawer {
238
244
  const input = document.createElement("input");
239
245
  input.type = "text";
240
246
  input.className = "drawer-rename-input";
247
+ input.setAttribute("part", "drawer-rename-input");
241
248
  input.value = meta.title;
242
249
  // One-shot: Enter, Escape, and blur can all fire for a single edit (Enter
243
250
  // commits and re-renders, which blurs the detached input); the flag makes
@@ -283,17 +290,21 @@ export class ThreadDrawer {
283
290
  #confirmDelete(row: HTMLDivElement, meta: ThreadMeta): void {
284
291
  const confirm = document.createElement("div");
285
292
  confirm.className = "drawer-confirm";
293
+ confirm.setAttribute("part", "drawer-confirm");
286
294
  const label = document.createElement("span");
287
295
  label.className = "drawer-confirm-label";
296
+ label.setAttribute("part", "drawer-confirm-label");
288
297
  label.textContent = this.#strings.deletePrompt;
289
298
  const yes = document.createElement("button");
290
299
  yes.type = "button";
291
300
  yes.className = "drawer-confirm-yes";
301
+ yes.setAttribute("part", "drawer-confirm-yes");
292
302
  yes.textContent = this.#strings.delete;
293
303
  yes.addEventListener("click", () => this.#callbacks.onDelete(meta.threadId));
294
304
  const no = document.createElement("button");
295
305
  no.type = "button";
296
306
  no.className = "drawer-confirm-no";
307
+ no.setAttribute("part", "drawer-confirm-no");
297
308
  no.textContent = this.#strings.cancel;
298
309
  no.addEventListener("click", () => this.#renderList());
299
310
  confirm.append(label, yes, no);
@@ -98,6 +98,26 @@ export interface UiStrings {
98
98
  /** Cancel button (confirmation + delete confirm). */
99
99
  cancel: string;
100
100
 
101
+ // ── Approval card (server-side tool gate) ───────────────────────────────────
102
+ /** `aria-label` of the inline server-side-tool approval card. */
103
+ approveAction: string;
104
+ /** Fallback approval prompt when the interrupt carries no message. */
105
+ approvalPrompt: string;
106
+ /** Approve button (runs the gated server-side tool). */
107
+ approve: string;
108
+ /** Deny button (declines the gated server-side tool). */
109
+ deny: string;
110
+
111
+ // ── Question card (the `ask_user` frontend tool) ────────────────────────────
112
+ /** `aria-label` of the inline question card. */
113
+ askUserAction: string;
114
+ /** Radio label for the free-text "other" choice (when custom answers are allowed). */
115
+ otherOption: string;
116
+ /** Placeholder for the free-text answer field. */
117
+ answerPlaceholder: string;
118
+ /** Submit button for the question card. */
119
+ submit: string;
120
+
101
121
  // ── Chat-history drawer ─────────────────────────────────────────────────────
102
122
  /** Drawer heading. */
103
123
  chats: string;
@@ -137,6 +157,16 @@ export interface UiStrings {
137
157
  minutesAgo: string;
138
158
  /** Hours ago. Token: `{n}`. */
139
159
  hoursAgo: string;
160
+ /** Title of the checkpoint panel. */
161
+ checkpoints: string;
162
+ /** Empty state when no run can be continued. */
163
+ noCheckpoints: string;
164
+ /** Action: continue a run from its last checkpoint. */
165
+ resumeRun: string;
166
+ /** Action: branch a run without touching the original. */
167
+ forkRun: string;
168
+ /** Badge on a run that branched from another. */
169
+ forkedRun: string;
140
170
  /** Days ago. Token: `{n}`. */
141
171
  daysAgo: string;
142
172
  /** Weeks ago. Token: `{n}`. */
@@ -151,6 +181,11 @@ export const DEFAULT_UI_STRINGS: UiStrings = {
151
181
  collapse: "Collapse",
152
182
  expand: "Expand",
153
183
  toggleTheme: "Toggle theme",
184
+ checkpoints: "Continue a run",
185
+ noCheckpoints: "Nothing to continue yet.",
186
+ resumeRun: "Resume",
187
+ forkRun: "Fork",
188
+ forkedRun: "branched",
154
189
 
155
190
  conversation: "Conversation",
156
191
  thinking: "Assistant is thinking…",
@@ -186,6 +221,16 @@ export const DEFAULT_UI_STRINGS: UiStrings = {
186
221
  confirm: "Confirm",
187
222
  cancel: "Cancel",
188
223
 
224
+ approveAction: "Approve action",
225
+ approvalPrompt: "Approve this action?",
226
+ approve: "Approve",
227
+ deny: "Deny",
228
+
229
+ askUserAction: "Question",
230
+ otherOption: "Other…",
231
+ answerPlaceholder: "Type your answer…",
232
+ submit: "Submit",
233
+
189
234
  chats: "Chats",
190
235
  noConversations: "No conversations yet.",
191
236
  rename: "Rename",
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION: string = "0.10.0";
1
+ export const VERSION: string = "0.12.0";