@adecore/agents-react 0.37.2 → 0.38.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 (115) hide show
  1. package/dist/chat/chat-client.d.ts +1 -0
  2. package/dist/chat/chat-client.js +2 -1
  3. package/dist/chat/chat-references.d.ts +16 -1
  4. package/dist/chat/chat-references.js +29 -3
  5. package/dist/chat/drafts.d.ts +2 -0
  6. package/dist/chat/drafts.js +21 -5
  7. package/dist/chat/index.d.ts +1 -1
  8. package/dist/chat/logic/visual-height.d.ts +1 -0
  9. package/dist/chat/logic/visual-height.js +1 -1
  10. package/dist/chat/mentions.d.ts +31 -14
  11. package/dist/chat/mentions.js +186 -41
  12. package/dist/chat/stash.d.ts +1 -0
  13. package/dist/chat/stash.js +4 -2
  14. package/dist/chat/ui/Composer.js +438 -429
  15. package/dist/chat/ui/ComposerInput.d.ts +1 -0
  16. package/dist/chat/ui/ComposerInput.js +2 -0
  17. package/dist/chat/ui/HostMenuItems.d.ts +4 -0
  18. package/dist/chat/ui/HostMenuItems.js +15 -0
  19. package/dist/chat/ui/Markdown.d.ts +3 -1
  20. package/dist/chat/ui/Markdown.js +194 -120
  21. package/dist/chat/ui/MessageActions.js +70 -66
  22. package/dist/chat/ui/ReferenceChip.d.ts +15 -0
  23. package/dist/chat/ui/ReferenceChip.js +255 -0
  24. package/dist/chat/ui/Timeline.js +52 -29
  25. package/dist/chat/ui/TimelineMenu.js +84 -78
  26. package/dist/chat/ui/VisualFrame.d.ts +8 -0
  27. package/dist/chat/ui/VisualFrame.js +217 -115
  28. package/dist/chat/ui/chip-clipboard.d.ts +9 -0
  29. package/dist/chat/ui/chip-clipboard.js +105 -0
  30. package/dist/chat/ui/chips.d.ts +5 -0
  31. package/dist/chat/ui/chips.js +15 -1
  32. package/dist/chat/ui/composer/ComposerMenu.js +140 -79
  33. package/dist/chat/ui/composer/DraftParts.d.ts +0 -4
  34. package/dist/chat/ui/composer/DraftParts.js +0 -41
  35. package/dist/chat/ui/composer/chip-paste.d.ts +15 -0
  36. package/dist/chat/ui/composer/chip-paste.js +104 -0
  37. package/dist/chat/ui/composer/chips.d.ts +5 -0
  38. package/dist/chat/ui/composer/chips.js +59 -9
  39. package/dist/chat/ui/composer/key-handler.js +9 -0
  40. package/dist/chat/ui/composer/use-composer-draft.d.ts +0 -1
  41. package/dist/chat/ui/composer/use-composer-draft.js +2 -10
  42. package/dist/chat/ui/composer/use-composer-menus.d.ts +12 -2
  43. package/dist/chat/ui/composer/use-composer-menus.js +192 -149
  44. package/dist/chat/ui/composer/use-composer-submit.js +17 -12
  45. package/dist/chat/ui/composer/use-draft-files.d.ts +7 -1
  46. package/dist/chat/ui/composer/use-draft-files.js +90 -58
  47. package/dist/chat/ui/composer/use-take-back.js +2 -1
  48. package/dist/chat/ui/index.d.ts +1 -1
  49. package/dist/chat/ui/index.js +1 -1
  50. package/dist/chat/ui/reference-icons.d.ts +3 -0
  51. package/dist/chat/ui/reference-icons.js +15 -0
  52. package/dist/chat/ui/reference-lookup.d.ts +7 -0
  53. package/dist/chat/ui/reference-lookup.js +6 -0
  54. package/dist/chat/ui/rehype-chips.d.ts +8 -1
  55. package/dist/chat/ui/rehype-chips.js +35 -11
  56. package/dist/chat/ui/rows/GeneratedImageRow.js +8 -4
  57. package/dist/chat/ui/rows/MessageRows.js +218 -158
  58. package/dist/chat/ui/rows/VisualRow.js +184 -142
  59. package/dist/chat/ui/rows/row-rhythm.js +6 -4
  60. package/dist/chat/ui/thread-references.d.ts +4 -0
  61. package/dist/chat/ui/thread-references.js +78 -0
  62. package/dist/host-hooks.d.ts +2 -0
  63. package/dist/host-hooks.js +7 -0
  64. package/dist/host.d.ts +14 -1
  65. package/dist/index.d.ts +1 -1
  66. package/dist/locales/en/agent-chat.d.ts +20 -3
  67. package/dist/locales/en/agent-chat.js +24 -7
  68. package/dist/locales/nl/agent-chat.d.ts +20 -3
  69. package/dist/locales/nl/agent-chat.js +24 -7
  70. package/package.json +8 -8
  71. package/src/chat/chat-client.ts +4 -1
  72. package/src/chat/chat-references.ts +44 -3
  73. package/src/chat/drafts.ts +24 -6
  74. package/src/chat/index.ts +1 -1
  75. package/src/chat/logic/visual-height.ts +1 -1
  76. package/src/chat/mentions.ts +202 -36
  77. package/src/chat/stash.ts +6 -2
  78. package/src/chat/ui/Composer.tsx +14 -4
  79. package/src/chat/ui/ComposerInput.tsx +4 -0
  80. package/src/chat/ui/HostMenuItems.tsx +11 -0
  81. package/src/chat/ui/Markdown.tsx +57 -25
  82. package/src/chat/ui/MessageActions.tsx +5 -2
  83. package/src/chat/ui/ReferenceChip.tsx +74 -0
  84. package/src/chat/ui/Timeline.tsx +24 -2
  85. package/src/chat/ui/TimelineMenu.tsx +7 -3
  86. package/src/chat/ui/VisualFrame.tsx +68 -21
  87. package/src/chat/ui/chip-clipboard.ts +115 -0
  88. package/src/chat/ui/chips.ts +20 -1
  89. package/src/chat/ui/composer/ComposerMenu.tsx +53 -37
  90. package/src/chat/ui/composer/DraftParts.tsx +0 -12
  91. package/src/chat/ui/composer/chip-paste.ts +122 -0
  92. package/src/chat/ui/composer/chips.ts +60 -10
  93. package/src/chat/ui/composer/key-handler.ts +9 -0
  94. package/src/chat/ui/composer/use-composer-draft.ts +1 -7
  95. package/src/chat/ui/composer/use-composer-menus.ts +68 -29
  96. package/src/chat/ui/composer/use-composer-submit.ts +13 -6
  97. package/src/chat/ui/composer/use-draft-files.ts +39 -5
  98. package/src/chat/ui/composer/use-take-back.ts +2 -1
  99. package/src/chat/ui/index.ts +1 -1
  100. package/src/chat/ui/reference-icons.ts +17 -0
  101. package/src/chat/ui/reference-lookup.ts +13 -0
  102. package/src/chat/ui/rehype-chips.ts +38 -13
  103. package/src/chat/ui/rows/GeneratedImageRow.tsx +9 -4
  104. package/src/chat/ui/rows/MessageRows.tsx +88 -64
  105. package/src/chat/ui/rows/VisualRow.tsx +5 -1
  106. package/src/chat/ui/rows/row-rhythm.ts +6 -4
  107. package/src/chat/ui/thread-references.ts +47 -0
  108. package/src/host-hooks.ts +9 -0
  109. package/src/host.ts +24 -1
  110. package/src/index.ts +1 -0
  111. package/src/locales/en/agent-chat.ts +24 -7
  112. package/src/locales/nl/agent-chat.ts +24 -7
  113. package/dist/chat/ui/ChatReferenceChip.d.ts +0 -4
  114. package/dist/chat/ui/ChatReferenceChip.js +0 -110
  115. package/src/chat/ui/ChatReferenceChip.tsx +0 -26
@@ -5,6 +5,7 @@ import { ButtonGroup, ErrorBoundary, Icon, IconButton, Menu, Surface } from '@ad
5
5
  import { useChatHost } from '../../../host.js';
6
6
  import { useChatScope } from '../../../scope.js';
7
7
  import { useVisualDialog } from '../../visuals.js';
8
+ import { HostMenuItems } from '../HostMenuItems.js';
8
9
  import { VisualFrame } from '../VisualFrame.js';
9
10
  /*
10
11
  * A page an agent published, borderless on the thread's ground, with its width set by the row. Its few
@@ -14,7 +15,7 @@ import { VisualFrame } from '../VisualFrame.js';
14
15
  */
15
16
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
17
  export function VisualRow(t0) {
17
- const $ = _c(50);
18
+ const $ = _c(63);
18
19
  const {
19
20
  chatId,
20
21
  visual
@@ -24,223 +25,264 @@ export function VisualRow(t0) {
24
25
  t
25
26
  } = useTranslation("agent-chat");
26
27
  const {
28
+ id: scopeId,
27
29
  keyOf
28
30
  } = useChatScope();
29
31
  if (host.visuals === null) {
30
32
  return null;
31
33
  }
32
34
  let t1;
33
- if ($[0] !== chatId || $[1] !== keyOf || $[2] !== visual.id) {
34
- t1 = kind => useVisualDialog.getState().open(keyOf(chatId), visual.id, kind);
35
+ if ($[0] !== chatId || $[1] !== host.visuals || $[2] !== scopeId || $[3] !== visual) {
36
+ t1 = host.visuals.actions?.(scopeId, chatId, visual) ?? [];
35
37
  $[0] = chatId;
36
- $[1] = keyOf;
37
- $[2] = visual.id;
38
- $[3] = t1;
38
+ $[1] = host.visuals;
39
+ $[2] = scopeId;
40
+ $[3] = visual;
41
+ $[4] = t1;
39
42
  } else {
40
- t1 = $[3];
43
+ t1 = $[4];
41
44
  }
42
- const open = t1;
45
+ const extra = t1;
43
46
  let t2;
44
- if ($[4] !== t) {
45
- t2 = t("visuals.renderFailed");
46
- $[4] = t;
47
- $[5] = t2;
47
+ if ($[5] !== chatId || $[6] !== keyOf || $[7] !== visual.id) {
48
+ t2 = kind => useVisualDialog.getState().open(keyOf(chatId), visual.id, kind);
49
+ $[5] = chatId;
50
+ $[6] = keyOf;
51
+ $[7] = visual.id;
52
+ $[8] = t2;
48
53
  } else {
49
- t2 = $[5];
54
+ t2 = $[8];
50
55
  }
56
+ const open = t2;
51
57
  let t3;
52
- if ($[6] !== visual) {
53
- t3 = [visual];
54
- $[6] = visual;
55
- $[7] = t3;
58
+ if ($[9] !== t) {
59
+ t3 = t("visuals.renderFailed");
60
+ $[9] = t;
61
+ $[10] = t3;
56
62
  } else {
57
- t3 = $[7];
63
+ t3 = $[10];
58
64
  }
59
65
  let t4;
60
- if ($[8] !== chatId || $[9] !== visual) {
61
- t4 = /*#__PURE__*/_jsx(VisualFrame, {
62
- chatId: chatId,
63
- visual: visual
64
- });
65
- $[8] = chatId;
66
- $[9] = visual;
67
- $[10] = t4;
66
+ if ($[11] !== visual) {
67
+ t4 = [visual];
68
+ $[11] = visual;
69
+ $[12] = t4;
68
70
  } else {
69
- t4 = $[10];
71
+ t4 = $[12];
70
72
  }
71
73
  let t5;
72
- if ($[11] !== t || $[12] !== visual.title) {
73
- t5 = t("visuals.actions", {
74
- title: visual.title
74
+ if ($[13] !== chatId || $[14] !== visual) {
75
+ t5 = /*#__PURE__*/_jsx(VisualFrame, {
76
+ chatId: chatId,
77
+ visual: visual
75
78
  });
76
- $[11] = t;
77
- $[12] = visual.title;
78
- $[13] = t5;
79
+ $[13] = chatId;
80
+ $[14] = visual;
81
+ $[15] = t5;
79
82
  } else {
80
- t5 = $[13];
83
+ t5 = $[15];
81
84
  }
82
85
  let t6;
83
- if ($[14] !== t) {
84
- t6 = t("visuals.expand");
85
- $[14] = t;
86
- $[15] = t6;
86
+ if ($[16] !== t || $[17] !== visual.title) {
87
+ t6 = t("visuals.actions", {
88
+ title: visual.title
89
+ });
90
+ $[16] = t;
91
+ $[17] = visual.title;
92
+ $[18] = t6;
87
93
  } else {
88
- t6 = $[15];
94
+ t6 = $[18];
89
95
  }
90
96
  let t7;
91
- if ($[16] !== open) {
92
- t7 = () => open("expand");
93
- $[16] = open;
94
- $[17] = t7;
97
+ if ($[19] !== t) {
98
+ t7 = t("visuals.expand");
99
+ $[19] = t;
100
+ $[20] = t7;
95
101
  } else {
96
- t7 = $[17];
102
+ t7 = $[20];
97
103
  }
98
104
  let t8;
99
- if ($[18] !== t6 || $[19] !== t7) {
100
- t8 = /*#__PURE__*/_jsx(IconButton, {
101
- icon: Maximize2,
102
- size: "sm",
103
- label: t6,
104
- onClick: t7
105
- });
106
- $[18] = t6;
107
- $[19] = t7;
108
- $[20] = t8;
105
+ if ($[21] !== open) {
106
+ t8 = () => open("expand");
107
+ $[21] = open;
108
+ $[22] = t8;
109
109
  } else {
110
- t8 = $[20];
110
+ t8 = $[22];
111
111
  }
112
112
  let t9;
113
- if ($[21] !== t) {
114
- t9 = t("visuals.more");
115
- $[21] = t;
116
- $[22] = t9;
113
+ if ($[23] !== t7 || $[24] !== t8) {
114
+ t9 = /*#__PURE__*/_jsx(IconButton, {
115
+ icon: Maximize2,
116
+ size: "sm",
117
+ label: t7,
118
+ onClick: t8
119
+ });
120
+ $[23] = t7;
121
+ $[24] = t8;
122
+ $[25] = t9;
117
123
  } else {
118
- t9 = $[22];
124
+ t9 = $[25];
119
125
  }
120
126
  let t10;
121
- if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
122
- t10 = /*#__PURE__*/_jsx(Menu.Trigger, {});
123
- $[23] = t10;
127
+ if ($[26] !== t) {
128
+ t10 = t("visuals.more");
129
+ $[26] = t;
130
+ $[27] = t10;
124
131
  } else {
125
- t10 = $[23];
132
+ t10 = $[27];
126
133
  }
127
134
  let t11;
128
- if ($[24] !== t9) {
129
- t11 = /*#__PURE__*/_jsx(IconButton, {
130
- icon: Ellipsis,
131
- size: "sm",
132
- label: t9,
133
- render: t10
134
- });
135
- $[24] = t9;
136
- $[25] = t11;
135
+ if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
136
+ t11 = /*#__PURE__*/_jsx(Menu.Trigger, {});
137
+ $[28] = t11;
137
138
  } else {
138
- t11 = $[25];
139
+ t11 = $[28];
139
140
  }
140
141
  let t12;
141
- if ($[26] !== open) {
142
- t12 = () => open("remove");
143
- $[26] = open;
144
- $[27] = t12;
142
+ if ($[29] !== t10) {
143
+ t12 = /*#__PURE__*/_jsx(IconButton, {
144
+ icon: Ellipsis,
145
+ size: "sm",
146
+ label: t10,
147
+ render: t11
148
+ });
149
+ $[29] = t10;
150
+ $[30] = t12;
145
151
  } else {
146
- t12 = $[27];
152
+ t12 = $[30];
147
153
  }
148
154
  let t13;
149
- if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
150
- t13 = /*#__PURE__*/_jsx(Icon, {
151
- icon: Trash2,
152
- size: 14
155
+ if ($[31] !== extra) {
156
+ t13 = /*#__PURE__*/_jsx(HostMenuItems, {
157
+ actions: extra
153
158
  });
154
- $[28] = t13;
159
+ $[31] = extra;
160
+ $[32] = t13;
155
161
  } else {
156
- t13 = $[28];
162
+ t13 = $[32];
157
163
  }
158
164
  let t14;
159
- if ($[29] !== t) {
160
- t14 = t("visuals.remove");
161
- $[29] = t;
162
- $[30] = t14;
165
+ if ($[33] !== extra.length) {
166
+ t14 = extra.length > 0 && /*#__PURE__*/_jsx(Menu.Separator, {});
167
+ $[33] = extra.length;
168
+ $[34] = t14;
163
169
  } else {
164
- t14 = $[30];
170
+ t14 = $[34];
165
171
  }
166
172
  let t15;
167
- if ($[31] !== t12 || $[32] !== t14) {
168
- t15 = /*#__PURE__*/_jsx(Menu.Popup, {
169
- align: "end",
170
- children: /*#__PURE__*/_jsxs(Menu.Item, {
171
- onClick: t12,
172
- children: [t13, " ", t14]
173
- })
174
- });
175
- $[31] = t12;
176
- $[32] = t14;
177
- $[33] = t15;
173
+ if ($[35] !== open) {
174
+ t15 = () => open("remove");
175
+ $[35] = open;
176
+ $[36] = t15;
178
177
  } else {
179
- t15 = $[33];
178
+ t15 = $[36];
180
179
  }
181
180
  let t16;
182
- if ($[34] !== t11 || $[35] !== t15) {
183
- t16 = /*#__PURE__*/_jsxs(Menu.Root, {
184
- children: [t11, t15]
181
+ if ($[37] === Symbol.for("react.memo_cache_sentinel")) {
182
+ t16 = /*#__PURE__*/_jsx(Icon, {
183
+ icon: Trash2,
184
+ size: 14
185
185
  });
186
- $[34] = t11;
187
- $[35] = t15;
188
- $[36] = t16;
186
+ $[37] = t16;
189
187
  } else {
190
- t16 = $[36];
188
+ t16 = $[37];
191
189
  }
192
190
  let t17;
193
- if ($[37] !== t16 || $[38] !== t8) {
194
- t17 = /*#__PURE__*/_jsxs(ButtonGroup, {
195
- children: [t8, t16]
196
- });
197
- $[37] = t16;
198
- $[38] = t8;
191
+ if ($[38] !== t) {
192
+ t17 = t("visuals.remove");
193
+ $[38] = t;
199
194
  $[39] = t17;
200
195
  } else {
201
196
  t17 = $[39];
202
197
  }
203
198
  let t18;
204
- if ($[40] !== t17 || $[41] !== t5) {
205
- t18 = /*#__PURE__*/_jsx(Surface, {
206
- role: "toolbar",
207
- "aria-label": t5,
208
- className: "absolute top-2 right-2 rounded-lg p-0.5 opacity-0 transition-opacity group-focus-within/visual:opacity-100 group-hover/visual:opacity-100 has-[[data-popup-open]]:opacity-100 pointer-coarse:opacity-100",
209
- children: t17
199
+ if ($[40] !== t15 || $[41] !== t17) {
200
+ t18 = /*#__PURE__*/_jsxs(Menu.Item, {
201
+ onClick: t15,
202
+ children: [t16, " ", t17]
210
203
  });
211
- $[40] = t17;
212
- $[41] = t5;
204
+ $[40] = t15;
205
+ $[41] = t17;
213
206
  $[42] = t18;
214
207
  } else {
215
208
  t18 = $[42];
216
209
  }
217
210
  let t19;
218
- if ($[43] !== t18 || $[44] !== t4) {
219
- t19 = /*#__PURE__*/_jsxs("div", {
220
- className: "group/visual relative",
221
- children: [t4, t18]
211
+ if ($[43] !== t13 || $[44] !== t14 || $[45] !== t18) {
212
+ t19 = /*#__PURE__*/_jsxs(Menu.Popup, {
213
+ align: "end",
214
+ children: [t13, t14, t18]
222
215
  });
223
- $[43] = t18;
224
- $[44] = t4;
225
- $[45] = t19;
216
+ $[43] = t13;
217
+ $[44] = t14;
218
+ $[45] = t18;
219
+ $[46] = t19;
226
220
  } else {
227
- t19 = $[45];
221
+ t19 = $[46];
228
222
  }
229
223
  let t20;
230
- if ($[46] !== t19 || $[47] !== t2 || $[48] !== t3) {
231
- t20 = /*#__PURE__*/_jsx(ErrorBoundary, {
232
- label: t2,
233
- resetKeys: t3,
234
- compact: true,
235
- className: "relative rounded-lg",
236
- children: t19
224
+ if ($[47] !== t12 || $[48] !== t19) {
225
+ t20 = /*#__PURE__*/_jsxs(Menu.Root, {
226
+ children: [t12, t19]
237
227
  });
238
- $[46] = t19;
239
- $[47] = t2;
240
- $[48] = t3;
228
+ $[47] = t12;
229
+ $[48] = t19;
241
230
  $[49] = t20;
242
231
  } else {
243
232
  t20 = $[49];
244
233
  }
245
- return t20;
234
+ let t21;
235
+ if ($[50] !== t20 || $[51] !== t9) {
236
+ t21 = /*#__PURE__*/_jsxs(ButtonGroup, {
237
+ children: [t9, t20]
238
+ });
239
+ $[50] = t20;
240
+ $[51] = t9;
241
+ $[52] = t21;
242
+ } else {
243
+ t21 = $[52];
244
+ }
245
+ let t22;
246
+ if ($[53] !== t21 || $[54] !== t6) {
247
+ t22 = /*#__PURE__*/_jsx(Surface, {
248
+ role: "toolbar",
249
+ "aria-label": t6,
250
+ className: "absolute top-2 right-2 rounded-lg p-0.5 opacity-0 transition-opacity group-focus-within/visual:opacity-100 group-hover/visual:opacity-100 has-[[data-popup-open]]:opacity-100 pointer-coarse:opacity-100",
251
+ children: t21
252
+ });
253
+ $[53] = t21;
254
+ $[54] = t6;
255
+ $[55] = t22;
256
+ } else {
257
+ t22 = $[55];
258
+ }
259
+ let t23;
260
+ if ($[56] !== t22 || $[57] !== t5) {
261
+ t23 = /*#__PURE__*/_jsxs("div", {
262
+ className: "group/visual relative",
263
+ children: [t5, t22]
264
+ });
265
+ $[56] = t22;
266
+ $[57] = t5;
267
+ $[58] = t23;
268
+ } else {
269
+ t23 = $[58];
270
+ }
271
+ let t24;
272
+ if ($[59] !== t23 || $[60] !== t3 || $[61] !== t4) {
273
+ t24 = /*#__PURE__*/_jsx(ErrorBoundary, {
274
+ label: t3,
275
+ resetKeys: t4,
276
+ compact: true,
277
+ className: "relative rounded-lg",
278
+ children: t23
279
+ });
280
+ $[59] = t23;
281
+ $[60] = t3;
282
+ $[61] = t4;
283
+ $[62] = t24;
284
+ } else {
285
+ t24 = $[62];
286
+ }
287
+ return t24;
246
288
  }
@@ -4,13 +4,15 @@ import { isBlock } from '../../logic/timeline.js';
4
4
  export const FOLLOW_THRESHOLD_PX = 40;
5
5
  /*
6
6
  * The gaps a row wears for where it sits: a question is followed by its answer gap, and a seam where
7
- * the list rhythm of tool lines meets the block rhythm of prose gets the block gap. A visual has no
8
- * margin of its own like prose does, so the row under one takes the block gap too. A question
9
- * already carries the gap before it, and the row after one is the answer, so neither takes a seam.
7
+ * the list rhythm of tool lines meets the block rhythm of prose gets the block gap. A visual and an
8
+ * app's card have no margin of their own like prose does, so the row under one takes the block gap
9
+ * too. A question already carries the gap before it, and the row after one is the answer, so neither
10
+ * takes a seam.
10
11
  */
11
12
  export function rowRhythm(row, previous) {
12
13
  const question = row.kind === 'user';
13
- const seam = !question && previous !== null && previous.kind !== 'user' && (isBlock(row) !== isBlock(previous) || previous.kind === 'visual');
14
+ const bare = previous?.kind === 'visual' || previous?.kind === 'app-card';
15
+ const seam = !question && previous !== null && previous.kind !== 'user' && (isBlock(row) !== isBlock(previous) || bare);
14
16
  return clsx(question && 'pb-(--chat-answer-gap)', seam && 'pt-(--chat-block-gap)');
15
17
  }
16
18
  /*
@@ -0,0 +1,4 @@
1
+ import type { ChatItem } from '@adecore/agent-contracts';
2
+ import type { ReferenceLookup } from './reference-lookup.js';
3
+ export declare function threadReferencedKey(structure: Record<string, ChatItem> | undefined): string;
4
+ export declare function useReferenceLookup(chatId: string): ReferenceLookup;
@@ -0,0 +1,78 @@
1
+ import { c as _c } from "react/compiler-runtime";
2
+ import { useChatHost } from '../../host.js';
3
+ import { useHostReferables } from '../../host-hooks.js';
4
+ import { useChatScope } from '../../scope.js';
5
+ import { useChatRow } from '../../state/chats.js';
6
+ const referencedOf = new WeakMap();
7
+ /*
8
+ * The ids a person pointed at with `#` in a thread, one per line. A string, so the selector that reads
9
+ * it answers the same value until a message with another one comes; the structure a streamed word
10
+ * leaves alone is what it is cached on.
11
+ */
12
+ export function threadReferencedKey(structure) {
13
+ if (structure === undefined) {
14
+ return '';
15
+ }
16
+ const cached = referencedOf.get(structure);
17
+ if (cached !== undefined) {
18
+ return cached;
19
+ }
20
+ const ids = new Set();
21
+ for (const item of Object.values(structure)) {
22
+ if (item.kind === 'user') {
23
+ for (const id of [...(item.chats ?? []), ...(item.references ?? [])]) {
24
+ ids.add(id);
25
+ }
26
+ }
27
+ }
28
+ const key = [...ids].join('\n');
29
+ referencedOf.set(structure, key);
30
+ return key;
31
+ }
32
+ /* What the views, nodes and chats of a thread stand for now, and how one opens, for the rows that draw chips. */
33
+ export function useReferenceLookup(chatId) {
34
+ const $ = _c(9);
35
+ const {
36
+ id: scopeId
37
+ } = useChatScope();
38
+ const {
39
+ openReference
40
+ } = useChatHost();
41
+ const referables = useHostReferables(scopeId, chatId);
42
+ const key = useChatRow(chatId, _temp);
43
+ let t0;
44
+ if ($[0] !== openReference || $[1] !== scopeId) {
45
+ t0 = openReference ? id => openReference(scopeId, id) : null;
46
+ $[0] = openReference;
47
+ $[1] = scopeId;
48
+ $[2] = t0;
49
+ } else {
50
+ t0 = $[2];
51
+ }
52
+ let t1;
53
+ if ($[3] !== key) {
54
+ t1 = key === "" ? [] : key.split("\n");
55
+ $[3] = key;
56
+ $[4] = t1;
57
+ } else {
58
+ t1 = $[4];
59
+ }
60
+ let t2;
61
+ if ($[5] !== referables.items || $[6] !== t0 || $[7] !== t1) {
62
+ t2 = {
63
+ items: referables.items,
64
+ open: t0,
65
+ referenced: t1
66
+ };
67
+ $[5] = referables.items;
68
+ $[6] = t0;
69
+ $[7] = t1;
70
+ $[8] = t2;
71
+ } else {
72
+ t2 = $[8];
73
+ }
74
+ return t2;
75
+ }
76
+ function _temp(chat) {
77
+ return threadReferencedKey(chat?.structure);
78
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ProviderPlatform } from '@adecore/agent-contracts';
2
+ import { type Referables } from './chat/chat-references.js';
2
3
  import { type ChatHost, type CommandLook } from './host.js';
3
4
  export declare function useHostCodeMode(): 'light' | 'dark';
4
5
  export declare function useHostCodeThemes(): {
@@ -13,6 +14,7 @@ export declare function useHostStreaming(): ReturnType<ChatHost['useStreaming']>
13
14
  export declare function useHostSendDelivery(): ReturnType<ChatHost['useSendDelivery']>;
14
15
  export declare function useHostTimelineFind(...args: Parameters<ChatHost['useTimelineFind']>): ReturnType<ChatHost['useTimelineFind']>;
15
16
  export declare function useHostReferableChats(): ReturnType<ChatHost['useReferableChats']>;
17
+ export declare function useHostReferables(scopeId: string, chatId: string): Referables;
16
18
  export declare function useHostLoginBlocked(...args: Parameters<ChatHost['useLoginBlocked']>): ReturnType<ChatHost['useLoginBlocked']>;
17
19
  export declare function useHostMachinePlatform(scopeId: string): ProviderPlatform | null;
18
20
  export declare function useHostProjectLook(...args: Parameters<ChatHost['useProjectLook']>): ReturnType<ChatHost['useProjectLook']>;
@@ -1,5 +1,6 @@
1
1
  'use no memo';
2
2
 
3
+ import { referablesOfChats } from './chat/chat-references.js';
3
4
  import { useChatHost } from './host.js';
4
5
  export function useHostCodeMode() {
5
6
  return useChatHost().code.useMode();
@@ -31,6 +32,12 @@ export function useHostTimelineFind(...args) {
31
32
  export function useHostReferableChats() {
32
33
  return useChatHost().useReferableChats();
33
34
  }
35
+ const useReferablesFromChats = (_scopeId, _chatId) => referablesOfChats(useHostReferableChats());
36
+ /* A host without views of its own offers its chats. */
37
+ export function useHostReferables(scopeId, chatId) {
38
+ const useReferables = useChatHost().useReferables ?? useReferablesFromChats;
39
+ return useReferables(scopeId, chatId);
40
+ }
34
41
  export function useHostLoginBlocked(...args) {
35
42
  return useChatHost().useLoginBlocked(...args);
36
43
  }
package/dist/host.d.ts CHANGED
@@ -2,8 +2,10 @@ import { type ComponentProps, type ComponentType, type ReactNode, type RefObject
2
2
  import type { Extension } from '@codemirror/state';
3
3
  import type { EditorView } from '@codemirror/view';
4
4
  import type { Highlighter, ThemeRegistration } from 'shiki';
5
+ import type { LucideIcon } from 'lucide-react';
5
6
  import type { EditorEngine } from '@adecore/editor';
6
- import type { AgentKind, ChatCheckpointDiff, ChatConfigurePayload, ChatGoalAction, ChatItem, ChatSubagentItem, ChatUiChoicePayload, ChatUiQueryPayload, ChatUiQueryReading, ChatUiLinkPayload, ChatUiLinkReading, ProviderPlatform } from '@adecore/agent-contracts';
7
+ import type { AgentKind, ChatAttachment, ChatCheckpointDiff, ChatConfigurePayload, ChatGoalAction, ChatItem, ChatSubagentItem, ChatUiChoicePayload, ChatUiQueryPayload, ChatUiQueryReading, ChatUiLinkPayload, ChatUiLinkReading, ChatVisual, ProviderPlatform } from '@adecore/agent-contracts';
8
+ import type { Referables } from './chat/chat-references.js';
7
9
  import type { TimelineRow } from './chat/logic/timeline.js';
8
10
  import type { FindReveal } from './chat/ui/find-reveal.js';
9
11
  import type { PromptAction } from './prompts/logic/prompts.js';
@@ -120,6 +122,14 @@ export interface ThreadCard {
120
122
  export interface VisualHost {
121
123
  frameUrl: string;
122
124
  openLink(url: string): void;
125
+ actions?(scopeId: string, chatId: string, visual: ChatVisual): readonly HostMenuAction[];
126
+ }
127
+ export interface HostMenuAction {
128
+ id: string;
129
+ label: string;
130
+ icon?: LucideIcon;
131
+ disabled?: boolean;
132
+ run(): void;
123
133
  }
124
134
  export interface ReplyAuthor {
125
135
  name: string;
@@ -200,6 +210,7 @@ export interface ChatHost {
200
210
  read(scopeId: string, chatId: string, attachmentId: string): Promise<Blob>;
201
211
  open?(scopeId: string, chatId: string, attachmentId: string, suggestedName: string): void;
202
212
  saveToProject?(scopeId: string, chatId: string, attachmentId: string, suggestedName: string): Promise<string | null>;
213
+ actions?(scopeId: string, chatId: string, attachment: ChatAttachment): readonly HostMenuAction[];
203
214
  };
204
215
  ReadImage: ComponentType<{
205
216
  path: string;
@@ -247,6 +258,8 @@ export interface ChatHost {
247
258
  id: string;
248
259
  title: string;
249
260
  }>;
261
+ useReferables?(scopeId: string, chatId: string): Referables;
262
+ openReference?(scopeId: string, id: string): void;
250
263
  openLogin: ((scopeId: string, kind: AgentKind, accountId: string, name: string) => Promise<void>) | null;
251
264
  useLoginBlocked(scopeId: string): string | null;
252
265
  runProviderCommand?(scopeId: string, kind: AgentKind, command: string): void;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { type ChatActions, type FileRef, type ShellCodeBlockContext, type ChatPlace, type SubagentTask, type TimelineFindOptions, type TimelineFind, type ComposerDictationProps, type ComposerSlotProps, type SubagentSlotProps, type ThreadCard, type VisualHost, type ReplyAuthor, type ChatHost, type UiMapSource, type UiModelViewProps, type CommandLook, type CommandLookMatch, type CommandName, ChatHostProvider, useChatHost, type AccentChoice, type ChatToast, type TextareaProps, type ResourceUrl } from './host.js';
1
+ export { type ChatActions, type FileRef, type ShellCodeBlockContext, type ChatPlace, type SubagentTask, type TimelineFindOptions, type TimelineFind, type ComposerDictationProps, type ComposerSlotProps, type SubagentSlotProps, type ThreadCard, type VisualHost, type HostMenuAction, type ReplyAuthor, type ChatHost, type UiMapSource, type UiModelViewProps, type CommandLook, type CommandLookMatch, type CommandName, ChatHostProvider, useChatHost, type AccentChoice, type ChatToast, type TextareaProps, type ResourceUrl } from './host.js';
2
2
  export { type ChatScope, ChatScopeContext, useChatScope } from './scope.js';
3
3
  export { type ChatRequestMap, type ChatEventMap, type ChatTransportStatus, type ChatTransport, ChatTransportError, errorCode, isConnectionError } from './transport.js';
4
4
  export { portTransport, type PortTransport } from './port-transport.js';
@@ -16,10 +16,9 @@ declare const _default: {
16
16
  unreadable: string;
17
17
  unreadableThumbnail: string;
18
18
  };
19
- chatReference: {
19
+ references: {
20
20
  gone: string;
21
21
  untitled: string;
22
- remove: string;
23
22
  };
24
23
  fork: {
25
24
  refusal: {
@@ -305,6 +304,7 @@ declare const _default: {
305
304
  commands: string;
306
305
  skills: string;
307
306
  mentions: string;
307
+ references: string;
308
308
  };
309
309
  held: {
310
310
  question: string;
@@ -349,10 +349,27 @@ declare const _default: {
349
349
  mentions: {
350
350
  here: string;
351
351
  files: string;
352
- chats: string;
353
352
  noMatch: string;
354
353
  empty: string;
355
354
  };
355
+ references: {
356
+ canvas: string;
357
+ views: string;
358
+ noMatch: string;
359
+ kinds: {
360
+ canvas: string;
361
+ chat: string;
362
+ terminal: string;
363
+ note: string;
364
+ text: string;
365
+ drawing: string;
366
+ diagram: string;
367
+ browser: string;
368
+ device: string;
369
+ file: string;
370
+ database: string;
371
+ };
372
+ };
356
373
  queue: {
357
374
  attachments_one: string;
358
375
  attachments_other: string;