@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,21 +5,28 @@ import { EditorView } from '@codemirror/view';
5
5
  import { useChatHost } from '../../../host.js';
6
6
  import { checkAttachmentLimits, filesOf, readAttachments, uploadBytes } from '../../attachments.js';
7
7
  import { pasteBecomesAttachment, pastedTextName } from '../../guards.js';
8
- import { carriesMentions, droppedMentions, pastedMentions } from '../../mentions.js';
8
+ import { carriesMentions, droppedMentions, pastedMentions, readClipboardChips } from '../../mentions.js';
9
+ import { copyWithChipsFromEditor, pasteWithChips, withPastedChips } from './chip-paste.js';
9
10
  /* The card turns dropped files and paths into attachments and chips; CodeMirror would also paste their text at the drop point. */
10
11
  export const LEAVE_DROPS_TO_THE_CARD = EditorView.domEventHandlers({
11
12
  drop: event => event.dataTransfer !== null && (event.dataTransfer.types.includes('Files') || carriesMentions(event.dataTransfer.types))
12
13
  });
13
- /* What reaches the draft besides typing: files as attachments, dragged paths as mentions, and a long paste as a file of its own. */
14
+ /*
15
+ * What reaches the draft besides typing: files as attachments, dragged paths as mentions, a long paste
16
+ * as a file of its own, and the chips a copy carried or a pasted text spells.
17
+ */
14
18
  export function useDraftFiles(t0) {
15
- const $ = _c(35);
19
+ const $ = _c(41);
16
20
  const {
17
21
  capabilities,
18
22
  providerName,
19
23
  writable,
20
24
  draft: t1,
21
25
  inputRef,
22
- setNotice
26
+ setNotice,
27
+ skills,
28
+ referables,
29
+ referenceChips
23
30
  } = t0;
24
31
  const {
25
32
  draft,
@@ -103,7 +110,7 @@ export function useDraftFiles(t0) {
103
110
  }
104
111
  const noteKey = t4;
105
112
  let t5;
106
- if ($[13] !== addFiles || $[14] !== capabilities?.attachments || $[15] !== capabilities?.mentions || $[16] !== draft || $[17] !== setDraft) {
113
+ if ($[13] !== addFiles || $[14] !== capabilities?.attachments || $[15] !== capabilities?.mentions || $[16] !== draft || $[17] !== referables || $[18] !== setDraft || $[19] !== skills) {
107
114
  t5 = (e_0, view) => {
108
115
  const data = e_0.clipboardData;
109
116
  if (!data) {
@@ -130,7 +137,18 @@ export function useDraftFiles(t0) {
130
137
  return true;
131
138
  }
132
139
  if (inline || capabilities?.attachments === false || !pasteBecomesAttachment(clip)) {
133
- return false;
140
+ const choices = {
141
+ skills,
142
+ referables,
143
+ referenced: [...draft.chats, ...draft.references],
144
+ mentions: capabilities?.mentions !== false
145
+ };
146
+ const chips = pasteWithChips(view, clip, readClipboardChips(data), choices);
147
+ if (chips === null) {
148
+ return false;
149
+ }
150
+ setDraft(current_1 => withPastedChips(current_1, chips, choices));
151
+ return true;
134
152
  }
135
153
  const {
136
154
  from,
@@ -155,88 +173,102 @@ export function useDraftFiles(t0) {
155
173
  $[14] = capabilities?.attachments;
156
174
  $[15] = capabilities?.mentions;
157
175
  $[16] = draft;
158
- $[17] = setDraft;
159
- $[18] = t5;
176
+ $[17] = referables;
177
+ $[18] = setDraft;
178
+ $[19] = skills;
179
+ $[20] = t5;
160
180
  } else {
161
- t5 = $[18];
181
+ t5 = $[20];
162
182
  }
163
183
  const onPaste = t5;
164
184
  let t6;
165
- if ($[19] !== writable) {
166
- t6 = e_1 => {
167
- if (writable && (e_1.dataTransfer.types.includes("Files") || carriesMentions(e_1.dataTransfer.types))) {
168
- e_1.preventDefault();
169
- e_1.stopPropagation();
170
- setDragging(true);
171
- }
172
- };
173
- $[19] = writable;
174
- $[20] = t6;
185
+ if ($[21] !== draft || $[22] !== referenceChips) {
186
+ t6 = (e_1, view_0) => copyWithChipsFromEditor(e_1, view_0, draft, referenceChips);
187
+ $[21] = draft;
188
+ $[22] = referenceChips;
189
+ $[23] = t6;
175
190
  } else {
176
- t6 = $[20];
191
+ t6 = $[23];
177
192
  }
193
+ const onCopy = t6;
178
194
  let t7;
179
- if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
195
+ if ($[24] !== writable) {
180
196
  t7 = e_2 => {
181
- if (!e_2.currentTarget.contains(e_2.relatedTarget)) {
182
- setDragging(false);
197
+ if (writable && (e_2.dataTransfer.types.includes("Files") || carriesMentions(e_2.dataTransfer.types))) {
198
+ e_2.preventDefault();
199
+ e_2.stopPropagation();
200
+ setDragging(true);
183
201
  }
184
202
  };
185
- $[21] = t7;
203
+ $[24] = writable;
204
+ $[25] = t7;
186
205
  } else {
187
- t7 = $[21];
206
+ t7 = $[25];
188
207
  }
189
208
  let t8;
190
- if ($[22] !== addFiles || $[23] !== addMentions || $[24] !== inputRef) {
209
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
191
210
  t8 = e_3 => {
192
- e_3.preventDefault();
193
- e_3.stopPropagation();
194
- setDragging(false);
195
- addMentions(droppedMentions(e_3.dataTransfer));
196
- addFiles(filesOf(e_3.dataTransfer));
197
- inputRef.current?.focus();
211
+ if (!e_3.currentTarget.contains(e_3.relatedTarget)) {
212
+ setDragging(false);
213
+ }
198
214
  };
199
- $[22] = addFiles;
200
- $[23] = addMentions;
201
- $[24] = inputRef;
202
- $[25] = t8;
215
+ $[26] = t8;
203
216
  } else {
204
- t8 = $[25];
217
+ t8 = $[26];
205
218
  }
206
219
  let t9;
207
- if ($[26] !== t6 || $[27] !== t8) {
208
- t9 = {
209
- "data-takes-drop": "all",
210
- onDragOver: t6,
211
- onDragLeave: t7,
212
- onDrop: t8
220
+ if ($[27] !== addFiles || $[28] !== addMentions || $[29] !== inputRef) {
221
+ t9 = e_4 => {
222
+ e_4.preventDefault();
223
+ e_4.stopPropagation();
224
+ setDragging(false);
225
+ addMentions(droppedMentions(e_4.dataTransfer));
226
+ addFiles(filesOf(e_4.dataTransfer));
227
+ inputRef.current?.focus();
213
228
  };
214
- $[26] = t6;
215
- $[27] = t8;
216
- $[28] = t9;
229
+ $[27] = addFiles;
230
+ $[28] = addMentions;
231
+ $[29] = inputRef;
232
+ $[30] = t9;
217
233
  } else {
218
- t9 = $[28];
234
+ t9 = $[30];
219
235
  }
220
- const dropTarget = t9;
221
236
  let t10;
222
- if ($[29] !== addFiles || $[30] !== dragging || $[31] !== dropTarget || $[32] !== noteKey || $[33] !== onPaste) {
237
+ if ($[31] !== t7 || $[32] !== t9) {
223
238
  t10 = {
239
+ "data-takes-drop": "all",
240
+ onDragOver: t7,
241
+ onDragLeave: t8,
242
+ onDrop: t9
243
+ };
244
+ $[31] = t7;
245
+ $[32] = t9;
246
+ $[33] = t10;
247
+ } else {
248
+ t10 = $[33];
249
+ }
250
+ const dropTarget = t10;
251
+ let t11;
252
+ if ($[34] !== addFiles || $[35] !== dragging || $[36] !== dropTarget || $[37] !== noteKey || $[38] !== onCopy || $[39] !== onPaste) {
253
+ t11 = {
224
254
  dragging,
225
255
  dropTarget,
226
256
  addFiles,
227
257
  noteKey,
228
- onPaste
258
+ onPaste,
259
+ onCopy
229
260
  };
230
- $[29] = addFiles;
231
- $[30] = dragging;
232
- $[31] = dropTarget;
233
- $[32] = noteKey;
234
- $[33] = onPaste;
235
- $[34] = t10;
261
+ $[34] = addFiles;
262
+ $[35] = dragging;
263
+ $[36] = dropTarget;
264
+ $[37] = noteKey;
265
+ $[38] = onCopy;
266
+ $[39] = onPaste;
267
+ $[40] = t11;
236
268
  } else {
237
- t10 = $[34];
269
+ t11 = $[40];
238
270
  }
239
- return t10;
271
+ return t11;
240
272
  }
241
273
  function _temp6(attachment_0) {
242
274
  return attachment_0.name;
@@ -60,7 +60,8 @@ export function useTakeBack({
60
60
  mentions: message.mentions ?? [],
61
61
  skills: message.skills ?? [],
62
62
  chats: message.chats ?? [],
63
- attachments: uploads
63
+ attachments: uploads,
64
+ references: message.references ?? []
64
65
  };
65
66
  // A file that would not fit is refused here, while the message still holds it on the machine.
66
67
  const wouldReject = takeBackIntoDraft(latest.current, taken).rejected[0];
@@ -2,7 +2,6 @@ export { AccountPill } from './AccountPill.js';
2
2
  export { AnsiOutput } from './AnsiOutput.js';
3
3
  export { BookmarkSubmenu } from './BookmarkSubmenu.js';
4
4
  export { ChatActivity, StatusIcon } from './ChatActivity.js';
5
- export { ChatReferenceChip } from './ChatReferenceChip.js';
6
5
  export { CodeBlock } from './CodeBlock.js';
7
6
  export { Composer } from './Composer.js';
8
7
  export { type ComposerInputHandle, ComposerInput, type InputSelection } from './ComposerInput.js';
@@ -22,6 +21,7 @@ export { Timeline } from './Timeline.js';
22
21
  export { TimelineMenuPopup } from './TimelineMenu.js';
23
22
  export { default as UnifiedDiff } from './UnifiedDiff.js';
24
23
  export { UploadThumb } from './UploadThumb.js';
24
+ export { VisualPageFrame, type VisualPageFrameProps } from './VisualFrame.js';
25
25
  export { WelcomeGreeting } from './Welcome.js';
26
26
  export { externalChange, composerEditorExtensions } from './composer/editor.js';
27
27
  export { createDiffSyntaxRuntime, diffSyntaxRuntime, type DiffSyntaxRuntime, type DiffSyntaxRuntimeOptions, type DiffSyntaxSession, type DiffSyntaxMapping, type DiffSourceTokenSession, diffSourceTokens } from './diff-syntax.js';
@@ -3,7 +3,6 @@ export { AccountPill } from './AccountPill.js';
3
3
  export { AnsiOutput } from './AnsiOutput.js';
4
4
  export { BookmarkSubmenu } from './BookmarkSubmenu.js';
5
5
  export { ChatActivity, StatusIcon } from './ChatActivity.js';
6
- export { ChatReferenceChip } from './ChatReferenceChip.js';
7
6
  export { CodeBlock } from './CodeBlock.js';
8
7
  export { Composer } from './Composer.js';
9
8
  export { ComposerInput } from './ComposerInput.js';
@@ -23,6 +22,7 @@ export { Timeline } from './Timeline.js';
23
22
  export { TimelineMenuPopup } from './TimelineMenu.js';
24
23
  export { default as UnifiedDiff } from './UnifiedDiff.js';
25
24
  export { UploadThumb } from './UploadThumb.js';
25
+ export { VisualPageFrame } from './VisualFrame.js';
26
26
  export { WelcomeGreeting } from './Welcome.js';
27
27
  export { externalChange, composerEditorExtensions } from './composer/editor.js';
28
28
  export { createDiffSyntaxRuntime, diffSyntaxRuntime, diffSourceTokens } from './diff-syntax.js';
@@ -0,0 +1,3 @@
1
+ import { type LucideIcon } from 'lucide-react';
2
+ import type { ReferableKind } from '../chat-references.js';
3
+ export declare const REFERENCE_ICONS: Record<ReferableKind, LucideIcon>;
@@ -0,0 +1,15 @@
1
+ import { Database, FileText, Frame, Globe, MessageSquare, PenTool, Smartphone, StickyNote, Terminal, Type, Workflow } from 'lucide-react';
2
+ /* The mark of what a `#` points at, in the picker and on its chip. */
3
+ export const REFERENCE_ICONS = {
4
+ canvas: Frame,
5
+ chat: MessageSquare,
6
+ terminal: Terminal,
7
+ note: StickyNote,
8
+ text: Type,
9
+ drawing: PenTool,
10
+ diagram: Workflow,
11
+ browser: Globe,
12
+ device: Smartphone,
13
+ file: FileText,
14
+ database: Database
15
+ };
@@ -0,0 +1,7 @@
1
+ import type { Referable } from '../chat-references.js';
2
+ export interface ReferenceLookup {
3
+ items: readonly Referable[];
4
+ open: ((id: string) => void) | null;
5
+ referenced?: readonly string[];
6
+ }
7
+ export declare const ReferenceLookupContext: import("react").Context<ReferenceLookup>;
@@ -0,0 +1,6 @@
1
+ import { createContext } from 'react';
2
+ /* What the views and nodes of a message stand for now, handed down by the row that draws it. */
3
+ export const ReferenceLookupContext = createContext({
4
+ items: [],
5
+ open: null
6
+ });
@@ -1,3 +1,4 @@
1
+ import { type ReferenceToken } from '../mentions.js';
1
2
  interface HastText {
2
3
  type: 'text';
3
4
  value: string;
@@ -18,6 +19,12 @@ interface HastParent {
18
19
  export interface ChipOptions {
19
20
  mentions?: string[];
20
21
  skills?: string[];
22
+ references?: readonly ReferenceToken[];
21
23
  }
22
- export declare function rehypeChips({ mentions, skills }?: ChipOptions): (tree: HastParent) => void;
24
+ export interface NamedReferenceOptions {
25
+ items: readonly ReferenceToken[];
26
+ referenced?: readonly string[];
27
+ }
28
+ export declare function rehypeChips({ mentions, skills, references }?: ChipOptions): (tree: HastParent) => void;
29
+ export declare function rehypeNamedReferences({ items, referenced }: NamedReferenceOptions): (tree: HastParent) => void;
23
30
  export {};
@@ -1,14 +1,22 @@
1
- import { chipText, tokenizeChips } from '../mentions.js';
1
+ import { chipText, tokenizeChips, tokenizeNamedReferences } from '../mentions.js';
2
+ function valueOf(segment) {
3
+ if (segment.kind === 'mention') {
4
+ return segment.path;
5
+ }
6
+ return segment.kind === 'skill' ? segment.name : segment.id;
7
+ }
2
8
  // Inline code overrules a chip: `@a.ts` between backticks is code, not a mention.
3
9
  const SKIPPED = new Set(['code', 'pre']);
4
- /* A chip as an element: the renderer reads `data-chip` and `data-value`, the text keeps the sigil. */
10
+ // A link already leads somewhere of its own.
11
+ const SKIPPED_IN_REPLIES = new Set(['code', 'pre', 'a']);
12
+ /* A chip as an element: the renderer reads `data-chip` and `data-value` (a reference's id), the text keeps the sigil. */
5
13
  function chipElement(segment) {
6
14
  return {
7
15
  type: 'element',
8
16
  tagName: 'span',
9
17
  properties: {
10
18
  dataChip: segment.kind,
11
- dataValue: segment.kind === 'mention' ? segment.path : segment.name
19
+ dataValue: valueOf(segment)
12
20
  },
13
21
  children: [{
14
22
  type: 'text',
@@ -16,29 +24,45 @@ function chipElement(segment) {
16
24
  }]
17
25
  };
18
26
  }
19
- function split(parent, mentions, skills) {
27
+ function split(parent, tokenize, skipped) {
20
28
  parent.children = parent.children.flatMap(child => {
21
29
  if (child.type === 'text') {
22
- return tokenizeChips(child.value, mentions, skills).map(segment => segment.kind === 'text' ? {
30
+ return tokenize(child.value).map(segment => segment.kind === 'text' ? {
23
31
  type: 'text',
24
32
  value: segment.text
25
33
  } : chipElement(segment));
26
34
  }
27
- if (child.type === 'element' && !SKIPPED.has(child.tagName)) {
28
- split(child, mentions, skills);
35
+ if (child.type === 'element' && !skipped.has(child.tagName)) {
36
+ split(child, tokenize, skipped);
29
37
  }
30
38
  return [child];
31
39
  });
32
40
  }
33
- /* The `@path` and `$name` tokens a person picked in the composer, cut out of the text as chips. */
41
+ /* The `@path`, `$name` and `#name` tokens a person picked in the composer, cut out of the text as chips. */
34
42
  export function rehypeChips({
35
43
  mentions = [],
36
- skills = []
44
+ skills = [],
45
+ references = []
37
46
  } = {}) {
38
47
  return tree => {
39
- if (mentions.length === 0 && skills.length === 0) {
48
+ if (mentions.length === 0 && skills.length === 0 && references.length === 0) {
49
+ return;
50
+ }
51
+ split(tree, text => tokenizeChips(text, mentions, skills, references), SKIPPED);
52
+ };
53
+ }
54
+ /* The `#Name` a reply spells for a view, node or chat by exactly its name, cut out of the text as chips. */
55
+ export function rehypeNamedReferences({
56
+ items,
57
+ referenced = []
58
+ }) {
59
+ return tree => {
60
+ if (items.length === 0) {
40
61
  return;
41
62
  }
42
- split(tree, mentions, skills);
63
+ split(tree, text => text.includes('#') ? tokenizeNamedReferences(text, items, referenced) : [{
64
+ kind: 'text',
65
+ text
66
+ }], SKIPPED_IN_REPLIES);
43
67
  };
44
68
  }
@@ -12,6 +12,7 @@ import { attachmentAspect, generatedImageView } from '../../logic/generated-imag
12
12
  import { toolStartedAt } from '../../logic/tools.js';
13
13
  import { CHIP_IN_MESSAGE, MENTION_TONE } from '../chips.js';
14
14
  import { useFileLinkCwd, useOpenFileLink } from '../file-links.js';
15
+ import { HostMenuItems } from '../HostMenuItems.js';
15
16
  import { ImageThumb } from '../ImageView.js';
16
17
  import { ROW_GUTTER } from '../icons.js';
17
18
  import { RunningFor, WorkRow } from './WorkRows.js';
@@ -299,6 +300,7 @@ function ReadyImage({
299
300
  open,
300
301
  saveToProject
301
302
  } = attachments;
303
+ const extra = attachments.actions?.(scopeId, chatId, attachment) ?? [];
302
304
  const detail = [attachment.width !== undefined && attachment.height !== undefined ? t('generatedImage.dimensions', {
303
305
  width: attachment.width,
304
306
  height: attachment.height
@@ -359,21 +361,23 @@ function ReadyImage({
359
361
  size: "sm",
360
362
  label: t('generatedImage.openLarge'),
361
363
  onClick: () => setLightbox(true)
362
- }), prompt !== null && /*#__PURE__*/_jsxs(Menu.Root, {
364
+ }), (prompt !== null || extra.length > 0) && /*#__PURE__*/_jsxs(Menu.Root, {
363
365
  children: [/*#__PURE__*/_jsx(IconButton, {
364
366
  icon: Ellipsis,
365
367
  size: "sm",
366
368
  label: t('generatedImage.more'),
367
369
  render: /*#__PURE__*/_jsx(Menu.Trigger, {})
368
- }), /*#__PURE__*/_jsx(Menu.Popup, {
370
+ }), /*#__PURE__*/_jsxs(Menu.Popup, {
369
371
  align: "end",
370
- children: /*#__PURE__*/_jsxs(Menu.Item, {
372
+ children: [prompt !== null && /*#__PURE__*/_jsxs(Menu.Item, {
371
373
  onClick: () => copyText(prompt),
372
374
  children: [/*#__PURE__*/_jsx(Icon, {
373
375
  icon: Copy,
374
376
  size: 14
375
377
  }), " ", t('generatedImage.copyPrompt')]
376
- })
378
+ }), /*#__PURE__*/_jsx(HostMenuItems, {
379
+ actions: extra
380
+ })]
377
381
  })]
378
382
  })]
379
383
  })