@tutti-os/agent-gui 0.0.104 → 0.0.105

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 (81) hide show
  1. package/dist/{AgentGUI-DQ9gVoXh.d.ts → AgentGUI-Do6py-T_.d.ts} +10 -5
  2. package/dist/AgentRichTextReadonly-F6PHC5SX.js +18 -0
  3. package/dist/AgentRichTextReadonly-F6PHC5SX.js.map +1 -0
  4. package/dist/agent-conversation/index.d.ts +3 -3
  5. package/dist/agent-conversation/index.js +11 -7
  6. package/dist/agent-conversation/index.js.map +1 -1
  7. package/dist/agent-gui.d.ts +4 -4
  8. package/dist/agent-gui.js +18 -14
  9. package/dist/agent-message-center/index.d.ts +1 -1
  10. package/dist/agent-message-center/index.js +13 -9
  11. package/dist/agent-message-center/index.js.map +1 -1
  12. package/dist/{agentConversationVM-CkcYM5Wg.d.ts → agentConversationVM-Bf3Zv3iI.d.ts} +9 -1
  13. package/dist/{agentFileMentionContracts-58IjMU-u.d.ts → agentFileMentionContracts-B70VnPWO.d.ts} +2 -0
  14. package/dist/{agentGuiNodeTypes-B9vcvjmR.d.ts → agentGuiNodeTypes-DbgQBiYz.d.ts} +4 -1
  15. package/dist/app/renderer/agentactivity.css +99 -0
  16. package/dist/{chunk-FJ4W2VC5.js → chunk-4ZWV57MF.js} +42 -10
  17. package/dist/chunk-4ZWV57MF.js.map +1 -0
  18. package/dist/{chunk-VAB7EIL5.js → chunk-6R7GHXRQ.js} +12 -6
  19. package/dist/chunk-6R7GHXRQ.js.map +1 -0
  20. package/dist/{chunk-TPV2SV6L.js → chunk-7MPN2JGL.js} +122 -154
  21. package/dist/chunk-7MPN2JGL.js.map +1 -0
  22. package/dist/{chunk-5X7YDOC6.js → chunk-D2JUDUYY.js} +1 -1
  23. package/dist/chunk-D2JUDUYY.js.map +1 -0
  24. package/dist/{chunk-HLVC4NNL.js → chunk-IR2CL2X2.js} +721 -1280
  25. package/dist/chunk-IR2CL2X2.js.map +1 -0
  26. package/dist/{chunk-NOXQOGT5.js → chunk-J2HG7UCP.js} +46 -22
  27. package/dist/chunk-J2HG7UCP.js.map +1 -0
  28. package/dist/{chunk-747L443E.js → chunk-JG7HGKZL.js} +595 -61
  29. package/dist/chunk-JG7HGKZL.js.map +1 -0
  30. package/dist/chunk-KPMQGPYU.js +43 -0
  31. package/dist/chunk-KPMQGPYU.js.map +1 -0
  32. package/dist/{chunk-OFSDOID4.js → chunk-LDZ6C3YV.js} +3 -39
  33. package/dist/chunk-LDZ6C3YV.js.map +1 -0
  34. package/dist/{chunk-7N524ZK7.js → chunk-N3HTEYLZ.js} +1308 -936
  35. package/dist/chunk-N3HTEYLZ.js.map +1 -0
  36. package/dist/{chunk-MUPZPISC.js → chunk-N4WVVCNI.js} +2 -2
  37. package/dist/{chunk-F5LFPORI.js → chunk-OWW7CU4U.js} +2 -2
  38. package/dist/chunk-SN6UYX54.js +42 -0
  39. package/dist/chunk-SN6UYX54.js.map +1 -0
  40. package/dist/{chunk-SKCLZXSW.js → chunk-TKBEVCHG.js} +5 -1
  41. package/dist/chunk-TKBEVCHG.js.map +1 -0
  42. package/dist/chunk-UFIEUC3Y.js +755 -0
  43. package/dist/chunk-UFIEUC3Y.js.map +1 -0
  44. package/dist/{chunk-AKKDP2LI.js → chunk-V5ROOS2O.js} +124 -2
  45. package/dist/chunk-V5ROOS2O.js.map +1 -0
  46. package/dist/chunk-XJ34OIEQ.js +18 -0
  47. package/dist/chunk-XJ34OIEQ.js.map +1 -0
  48. package/dist/{chunk-QI3JAO4J.js → chunk-ZSJBCZUH.js} +54 -7
  49. package/dist/chunk-ZSJBCZUH.js.map +1 -0
  50. package/dist/context-mention-palette/index.d.ts +1 -1
  51. package/dist/context-mention-palette/index.js +10 -8
  52. package/dist/{contribution-CTVBPN0R.d.ts → contribution-C6K5YfJ7.d.ts} +1 -0
  53. package/dist/custom-mention.d.ts +6 -0
  54. package/dist/custom-mention.js +1 -1
  55. package/dist/i18n/index.d.ts +4 -0
  56. package/dist/i18n/index.js +2 -2
  57. package/dist/index.d.ts +6 -6
  58. package/dist/index.js +18 -14
  59. package/dist/index.js.map +1 -1
  60. package/dist/mention-search.d.ts +42 -6
  61. package/dist/mention-search.js +8 -6
  62. package/dist/workbench/contribution.d.ts +1 -1
  63. package/dist/workbench/contribution.js +3 -3
  64. package/dist/workbench/index.d.ts +3 -2
  65. package/dist/workbench/index.js +3 -3
  66. package/dist/workbench/sessionTitle.js +2 -2
  67. package/package.json +12 -12
  68. package/dist/chunk-5X7YDOC6.js.map +0 -1
  69. package/dist/chunk-747L443E.js.map +0 -1
  70. package/dist/chunk-7N524ZK7.js.map +0 -1
  71. package/dist/chunk-AKKDP2LI.js.map +0 -1
  72. package/dist/chunk-FJ4W2VC5.js.map +0 -1
  73. package/dist/chunk-HLVC4NNL.js.map +0 -1
  74. package/dist/chunk-NOXQOGT5.js.map +0 -1
  75. package/dist/chunk-OFSDOID4.js.map +0 -1
  76. package/dist/chunk-QI3JAO4J.js.map +0 -1
  77. package/dist/chunk-SKCLZXSW.js.map +0 -1
  78. package/dist/chunk-TPV2SV6L.js.map +0 -1
  79. package/dist/chunk-VAB7EIL5.js.map +0 -1
  80. /package/dist/{chunk-MUPZPISC.js.map → chunk-N4WVVCNI.js.map} +0 -0
  81. /package/dist/{chunk-F5LFPORI.js.map → chunk-OWW7CU4U.js.map} +0 -0
@@ -0,0 +1,755 @@
1
+ import {
2
+ AGENT_RICH_TEXT_CARET_ANCHOR,
3
+ attrsToMentionItem,
4
+ createAgentFileMentionExtension,
5
+ formatAgentMentionMarkdown,
6
+ mentionItemToAttrs,
7
+ parseAgentMentionMarkdown
8
+ } from "./chunk-J2HG7UCP.js";
9
+ import {
10
+ cn,
11
+ resolveAgentTargetPresentation,
12
+ useAgentTargetPresentations
13
+ } from "./chunk-KPMQGPYU.js";
14
+
15
+ // shared/AgentRichTextReadonly.tsx
16
+ import { useEffect } from "react";
17
+ import { EditorContent, useEditor } from "@tiptap/react";
18
+
19
+ // agent-gui/agentGuiNode/agentRichText/agentSkillTokenExtension.ts
20
+ import { mergeAttributes, Node } from "@tiptap/core";
21
+
22
+ // agent-gui/agentGuiNode/model/agentSkillOptions.ts
23
+ function skillTriggerForPrefix(skill, prefix) {
24
+ const trigger = skill.trigger.trim();
25
+ if (!trigger) {
26
+ return "";
27
+ }
28
+ if (prefix === void 0 || trigger.startsWith(prefix)) {
29
+ return trigger;
30
+ }
31
+ if (trigger.startsWith("$") || trigger.startsWith("/")) {
32
+ return `${prefix}${trigger.slice(1)}`;
33
+ }
34
+ return `${prefix}${trigger}`;
35
+ }
36
+ function labelForProviderSkill(skill, prefix) {
37
+ return stripSkillTriggerPrefix(skillTriggerForPrefix(skill, prefix));
38
+ }
39
+ function promptForProviderSkills(input) {
40
+ let prompt = input.prompt;
41
+ for (const skill of input.skills) {
42
+ if (!skill.invocation) {
43
+ continue;
44
+ }
45
+ const nativePrefix = skill.invocation === "promptItem" ? "$" : "/";
46
+ const nativeTrigger = skillTriggerForPrefix(skill, nativePrefix);
47
+ const aliasPrefix = nativePrefix === "$" ? "/" : "$";
48
+ const aliasTrigger = skillTriggerForPrefix(skill, aliasPrefix);
49
+ if (!nativeTrigger || !aliasTrigger || nativeTrigger === aliasTrigger) {
50
+ continue;
51
+ }
52
+ prompt = replaceSkillTriggerToken(prompt, aliasTrigger, nativeTrigger);
53
+ }
54
+ return prompt;
55
+ }
56
+ function skillDescriptionForDisplay(description) {
57
+ const line = description?.split(/\r?\n/).map((part) => part.trim()).find((part) => part !== "");
58
+ return line || void 0;
59
+ }
60
+ function replaceSkillTriggerToken(prompt, from, to) {
61
+ return prompt.replace(
62
+ new RegExp(`(^|\\s)${escapeRegExp(from)}(?=$|\\s)`, "g"),
63
+ (_match, separator) => `${separator}${to}`
64
+ );
65
+ }
66
+ function escapeRegExp(value) {
67
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
68
+ }
69
+ function stripSkillTriggerPrefix(trigger) {
70
+ if (trigger.startsWith("$") || trigger.startsWith("/")) {
71
+ return trigger.slice(1);
72
+ }
73
+ return trigger;
74
+ }
75
+
76
+ // agent-gui/agentGuiNode/agentRichText/agentSkillTokenExtension.ts
77
+ function createAgentSkillTokenExtension(options = {}) {
78
+ return Node.create({
79
+ name: "agentSkillToken",
80
+ group: "inline",
81
+ inline: true,
82
+ atom: true,
83
+ selectable: true,
84
+ addOptions() {
85
+ return options;
86
+ },
87
+ addAttributes() {
88
+ return {
89
+ label: { default: "" },
90
+ name: { default: "" },
91
+ trigger: { default: "" }
92
+ };
93
+ },
94
+ parseHTML() {
95
+ return [{ tag: "span[data-agent-skill-token]" }];
96
+ },
97
+ renderHTML({ HTMLAttributes }) {
98
+ const attrs = attrsToSkillTokenAttrs(HTMLAttributes);
99
+ const displayLabel = skillTokenDisplayLabel(attrs);
100
+ return [
101
+ "span",
102
+ mergeAttributes(HTMLAttributes, {
103
+ "aria-label": attrs.label,
104
+ contenteditable: "false",
105
+ "data-agent-skill-token": "true",
106
+ "data-agent-skill-trigger": attrs.trigger,
107
+ "data-agent-mention-kind": "skill",
108
+ class: "tsh-agent-object-token tsh-agent-object-token--entity"
109
+ }),
110
+ [
111
+ "span",
112
+ {
113
+ class: "tsh-agent-object-token__kind",
114
+ "aria-hidden": "true"
115
+ },
116
+ [
117
+ "span",
118
+ {
119
+ class: "tsh-agent-object-token__kind-icon",
120
+ "aria-hidden": "true"
121
+ },
122
+ ""
123
+ ]
124
+ ],
125
+ ["span", { class: "tsh-agent-object-token__main" }, displayLabel]
126
+ ];
127
+ },
128
+ renderText({ node }) {
129
+ return attrsToSkillTokenAttrs(node.attrs ?? {}).trigger;
130
+ }
131
+ });
132
+ }
133
+ function parseAgentSkillToken(text, start, skills = []) {
134
+ if (!isSkillTokenBoundary(text[start - 1] ?? "")) {
135
+ return null;
136
+ }
137
+ for (const candidate of skillTokenCandidates(skills)) {
138
+ if (!text.startsWith(candidate.trigger, start)) {
139
+ continue;
140
+ }
141
+ const end = start + candidate.trigger.length;
142
+ if (!isSkillTokenBoundary(text[end] ?? "")) {
143
+ continue;
144
+ }
145
+ return {
146
+ attrs: candidate,
147
+ end
148
+ };
149
+ }
150
+ return null;
151
+ }
152
+ function skillTokenCandidates(skills) {
153
+ const candidates = /* @__PURE__ */ new Map();
154
+ for (const skill of skills) {
155
+ for (const prefix of ["$", "/"]) {
156
+ const trigger = skillTriggerForPrefix(skill, prefix);
157
+ if (!trigger || candidates.has(trigger)) {
158
+ continue;
159
+ }
160
+ candidates.set(trigger, {
161
+ label: labelForProviderSkill(skill, prefix),
162
+ name: skill.name.trim(),
163
+ trigger
164
+ });
165
+ }
166
+ }
167
+ return [...candidates.values()].sort(
168
+ (left, right) => right.trigger.length - left.trigger.length
169
+ );
170
+ }
171
+ function isSkillTokenBoundary(value) {
172
+ return value === "" || value === " " || value === "\n" || value === " ";
173
+ }
174
+ function attrsToSkillTokenAttrs(attrs) {
175
+ return {
176
+ label: typeof attrs.label === "string" ? attrs.label : "",
177
+ name: typeof attrs.name === "string" ? attrs.name : "",
178
+ trigger: typeof attrs.trigger === "string" ? attrs.trigger : ""
179
+ };
180
+ }
181
+ function skillTokenDisplayLabel(attrs) {
182
+ const label = attrs.label.trim() || attrs.trigger.trim();
183
+ if (!label || label.startsWith("/") || label.startsWith("$")) {
184
+ return label;
185
+ }
186
+ return `/${label}`;
187
+ }
188
+
189
+ // agent-gui/agentGuiNode/agentRichText/agentCapabilityTokenExtension.ts
190
+ import { mergeAttributes as mergeAttributes2, Node as Node2 } from "@tiptap/core";
191
+ function createAgentCapabilityTokenExtension(options = {}) {
192
+ return Node2.create({
193
+ name: "agentCapabilityToken",
194
+ group: "inline",
195
+ inline: true,
196
+ atom: true,
197
+ selectable: true,
198
+ addOptions() {
199
+ return options;
200
+ },
201
+ addAttributes() {
202
+ return {
203
+ capability: { default: "" },
204
+ label: { default: "" },
205
+ name: { default: "" },
206
+ trigger: { default: "" }
207
+ };
208
+ },
209
+ parseHTML() {
210
+ return [{ tag: "span[data-agent-capability-token]" }];
211
+ },
212
+ renderHTML({ HTMLAttributes }) {
213
+ const attrs = attrsToCapabilityTokenAttrs(HTMLAttributes);
214
+ const displayLabel = capabilityTokenDisplayLabel(attrs);
215
+ return [
216
+ "span",
217
+ mergeAttributes2(HTMLAttributes, {
218
+ "aria-label": attrs.label,
219
+ contenteditable: "false",
220
+ "data-agent-capability-token": "true",
221
+ "data-agent-capability-trigger": attrs.trigger,
222
+ "data-agent-mention-kind": "capability",
223
+ class: "tsh-agent-object-token tsh-agent-object-token--entity"
224
+ }),
225
+ [
226
+ "span",
227
+ {
228
+ class: "tsh-agent-object-token__kind",
229
+ "aria-hidden": "true"
230
+ },
231
+ [
232
+ "span",
233
+ {
234
+ class: "tsh-agent-object-token__kind-icon",
235
+ "aria-hidden": "true"
236
+ },
237
+ ""
238
+ ]
239
+ ],
240
+ ["span", { class: "tsh-agent-object-token__main" }, displayLabel]
241
+ ];
242
+ },
243
+ renderText({ node }) {
244
+ return attrsToCapabilityTokenAttrs(node.attrs ?? {}).trigger;
245
+ }
246
+ });
247
+ }
248
+ function parseAgentCapabilityToken(text, start, capabilities = []) {
249
+ if (!isCapabilityTokenBoundary(text[start - 1] ?? "")) {
250
+ return null;
251
+ }
252
+ for (const candidate of capabilityTokenCandidates(capabilities)) {
253
+ if (!text.startsWith(candidate.trigger, start)) {
254
+ continue;
255
+ }
256
+ const end = start + candidate.trigger.length;
257
+ if (!isCapabilityTokenBoundary(text[end] ?? "")) {
258
+ continue;
259
+ }
260
+ return {
261
+ attrs: candidate,
262
+ end
263
+ };
264
+ }
265
+ return null;
266
+ }
267
+ function capabilityTokenCandidates(capabilities) {
268
+ const candidates = /* @__PURE__ */ new Map();
269
+ for (const capability of capabilities) {
270
+ const trigger = capability.trigger.trim();
271
+ if (!trigger || candidates.has(trigger)) {
272
+ continue;
273
+ }
274
+ candidates.set(trigger, {
275
+ capability: capability.capability.trim(),
276
+ label: capability.label.trim(),
277
+ name: capability.name.trim(),
278
+ trigger
279
+ });
280
+ }
281
+ return [...candidates.values()].sort(
282
+ (left, right) => right.trigger.length - left.trigger.length
283
+ );
284
+ }
285
+ function isCapabilityTokenBoundary(value) {
286
+ return value === "" || value === " " || value === "\n" || value === " ";
287
+ }
288
+ function attrsToCapabilityTokenAttrs(attrs) {
289
+ return {
290
+ capability: typeof attrs.capability === "string" ? attrs.capability : "",
291
+ label: typeof attrs.label === "string" ? attrs.label : "",
292
+ name: typeof attrs.name === "string" ? attrs.name : "",
293
+ trigger: typeof attrs.trigger === "string" ? attrs.trigger : ""
294
+ };
295
+ }
296
+ function capabilityTokenDisplayLabel(attrs) {
297
+ const label = attrs.label.trim() || attrs.trigger.trim();
298
+ if (!label || label.startsWith("/") || label.startsWith("$")) {
299
+ return label;
300
+ }
301
+ return `/${label}`;
302
+ }
303
+
304
+ // agent-gui/agentGuiNode/agentRichText/agentRichTextDocument.ts
305
+ function createEmptyDocument() {
306
+ return {
307
+ type: "doc",
308
+ content: [{ type: "paragraph" }]
309
+ };
310
+ }
311
+ function isVisualLineStart(content) {
312
+ return content.length === 0 || content.at(-1)?.type === "hardBreak";
313
+ }
314
+ function createParagraphFromText(text, options = {}) {
315
+ const content = [];
316
+ let index = 0;
317
+ let textBuffer = "";
318
+ const flushTextBuffer = () => {
319
+ if (textBuffer.length === 0) {
320
+ return;
321
+ }
322
+ content.push({ type: "text", text: textBuffer });
323
+ textBuffer = "";
324
+ };
325
+ while (index < text.length) {
326
+ const current = text[index];
327
+ if (current === "\n") {
328
+ flushTextBuffer();
329
+ content.push({ type: "hardBreak" });
330
+ index += 1;
331
+ continue;
332
+ }
333
+ const parsedMention = parseAgentMentionMarkdown(text, index);
334
+ if (parsedMention) {
335
+ flushTextBuffer();
336
+ if (isVisualLineStart(content)) {
337
+ content.push({ type: "text", text: AGENT_RICH_TEXT_CARET_ANCHOR });
338
+ }
339
+ content.push({
340
+ type: "agentFileMention",
341
+ // 转成规范 node attrs(如 workspace-reference 的 source/groupId/fileCount),
342
+ // 否则只读回显里的 reference chip 拿不到文件数 → 不显示「N 个文件」角标。
343
+ attrs: mentionItemToAttrs(parsedMention.item)
344
+ });
345
+ index = parsedMention.end;
346
+ continue;
347
+ }
348
+ const parsedCapabilityToken = parseAgentCapabilityToken(
349
+ text,
350
+ index,
351
+ options.capabilities
352
+ );
353
+ if (parsedCapabilityToken) {
354
+ flushTextBuffer();
355
+ content.push({
356
+ type: "agentCapabilityToken",
357
+ attrs: parsedCapabilityToken.attrs
358
+ });
359
+ index = parsedCapabilityToken.end;
360
+ continue;
361
+ }
362
+ const parsedSkillToken = parseAgentSkillToken(text, index, options.skills);
363
+ if (parsedSkillToken) {
364
+ flushTextBuffer();
365
+ content.push({
366
+ type: "agentSkillToken",
367
+ attrs: parsedSkillToken.attrs
368
+ });
369
+ index = parsedSkillToken.end;
370
+ continue;
371
+ }
372
+ textBuffer += current;
373
+ index += 1;
374
+ }
375
+ flushTextBuffer();
376
+ return content.length > 0 ? { type: "paragraph", content } : { type: "paragraph" };
377
+ }
378
+ function plainTextToAgentRichTextDoc(text, options = {}) {
379
+ if (text.length === 0) {
380
+ return createEmptyDocument();
381
+ }
382
+ const normalized = text.replace(/\r\n?/g, "\n");
383
+ return {
384
+ type: "doc",
385
+ content: [createParagraphFromText(normalized, options)]
386
+ };
387
+ }
388
+ function plainTextToAgentRichTextInlineContent(text, options = {}) {
389
+ const paragraph = createParagraphFromText(
390
+ text.replace(/\r\n?/g, "\n"),
391
+ options
392
+ );
393
+ return paragraph.content ?? [];
394
+ }
395
+ function agentRichTextDocToPromptText(doc) {
396
+ if (doc.type !== "doc") {
397
+ return nodeToPromptText(doc);
398
+ }
399
+ return agentRichTextContentToPromptText(doc.content ?? []);
400
+ }
401
+ function editorToPromptText(editor) {
402
+ return agentRichTextDocToPromptText(editor.getJSON());
403
+ }
404
+ function agentRichTextContentToPromptText(content) {
405
+ if (content.length === 0) {
406
+ return "";
407
+ }
408
+ const separator = content.some((node) => isBlockPromptNode(node)) ? "\n" : "";
409
+ return content.map((node) => nodeToPromptText(node)).join(separator);
410
+ }
411
+ function isBlockPromptNode(node) {
412
+ return node.type === "doc" || node.type === "paragraph";
413
+ }
414
+ function nodeToPromptText(node) {
415
+ if (node.type === "text") {
416
+ return (node.text ?? "").replaceAll(AGENT_RICH_TEXT_CARET_ANCHOR, "");
417
+ }
418
+ if (node.type === "agentFileMention") {
419
+ return formatAgentMentionMarkdown(attrsToMentionItem(node.attrs ?? {}));
420
+ }
421
+ if (node.type === "agentSkillToken") {
422
+ return typeof node.attrs?.trigger === "string" ? node.attrs.trigger : "";
423
+ }
424
+ if (node.type === "agentCapabilityToken") {
425
+ return typeof node.attrs?.trigger === "string" ? node.attrs.trigger : "";
426
+ }
427
+ if (node.type === "hardBreak") {
428
+ return "\n";
429
+ }
430
+ if (!node.content || node.content.length === 0) {
431
+ return "";
432
+ }
433
+ return node.content.map((child) => nodeToPromptText(child)).join("");
434
+ }
435
+
436
+ // agent-gui/agentGuiNode/agentRichText/agentRichTextExtensions.ts
437
+ import { Extension } from "@tiptap/core";
438
+ import { NodeSelection, TextSelection } from "@tiptap/pm/state";
439
+ import { Plugin } from "@tiptap/pm/state";
440
+ import StarterKit from "@tiptap/starter-kit";
441
+ function createAgentPromptStarterKit() {
442
+ return StarterKit.configure({
443
+ blockquote: false,
444
+ bold: false,
445
+ bulletList: false,
446
+ code: false,
447
+ codeBlock: false,
448
+ dropcursor: false,
449
+ gapcursor: false,
450
+ heading: false,
451
+ horizontalRule: false,
452
+ italic: false,
453
+ link: false,
454
+ listItem: false,
455
+ listKeymap: false,
456
+ orderedList: false,
457
+ strike: false,
458
+ trailingNode: false,
459
+ underline: false
460
+ });
461
+ }
462
+ function createAgentTokenKeyboardExtension() {
463
+ return Extension.create({
464
+ name: "agentTokenKeyboard",
465
+ addProseMirrorPlugins() {
466
+ return [
467
+ new Plugin({
468
+ props: {
469
+ handleKeyDown(view, event) {
470
+ if (event.key !== "Backspace" && event.key !== "ArrowLeft") {
471
+ return false;
472
+ }
473
+ const { doc, selection } = view.state;
474
+ if (selection instanceof NodeSelection && isSelectableAgentToken(selection.node)) {
475
+ event.preventDefault();
476
+ if (event.key === "ArrowLeft") {
477
+ view.dispatch(
478
+ view.state.tr.setSelection(
479
+ TextSelection.create(doc, selection.from)
480
+ )
481
+ );
482
+ } else {
483
+ view.dispatch(
484
+ view.state.tr.delete(selection.from, selection.to)
485
+ );
486
+ }
487
+ return true;
488
+ }
489
+ if (!selection.empty) {
490
+ return false;
491
+ }
492
+ const nodeBefore = selection.$from.nodeBefore;
493
+ if (!nodeBefore || !isSelectableAgentToken(nodeBefore)) {
494
+ return false;
495
+ }
496
+ event.preventDefault();
497
+ view.dispatch(
498
+ view.state.tr.setSelection(
499
+ NodeSelection.create(
500
+ doc,
501
+ selection.from - nodeBefore.nodeSize
502
+ )
503
+ )
504
+ );
505
+ return true;
506
+ }
507
+ }
508
+ })
509
+ ];
510
+ }
511
+ });
512
+ }
513
+ function isSelectableAgentToken(node) {
514
+ return node?.type.name === "agentSkillToken" || node?.type.name === "agentCapabilityToken";
515
+ }
516
+ function createAgentRichTextInputExtensions(fileMentionOptions, skillTokenOptions, capabilityTokenOptions) {
517
+ return [
518
+ createAgentTokenKeyboardExtension(),
519
+ createAgentPromptStarterKit(),
520
+ createAgentFileMentionExtension(fileMentionOptions),
521
+ createAgentCapabilityTokenExtension(capabilityTokenOptions),
522
+ createAgentSkillTokenExtension(skillTokenOptions)
523
+ ];
524
+ }
525
+ function createAgentRichTextReadonlyExtensions(skillTokenOptions, capabilityTokenOptions) {
526
+ return [
527
+ createAgentPromptStarterKit(),
528
+ createAgentFileMentionExtension({
529
+ enableSuggestions: false,
530
+ renderAsLink: true
531
+ }),
532
+ createAgentCapabilityTokenExtension(capabilityTokenOptions),
533
+ createAgentSkillTokenExtension(skillTokenOptions)
534
+ ];
535
+ }
536
+
537
+ // shared/AgentRichTextReadonly.tsx
538
+ import { jsx } from "react/jsx-runtime";
539
+ var EMPTY_WORKSPACE_APP_ICONS = [];
540
+ function AgentRichTextReadonly({
541
+ value,
542
+ className,
543
+ editorClassName,
544
+ onLinkClick,
545
+ availableSkills = [],
546
+ workspaceAppIcons = EMPTY_WORKSPACE_APP_ICONS,
547
+ agentTargets
548
+ }) {
549
+ "use memo";
550
+ const contextAgentTargets = useAgentTargetPresentations();
551
+ const effectiveAgentTargets = agentTargets ?? contextAgentTargets;
552
+ const contentDoc = plainTextToAgentRichTextDocWithMentionPresentations(
553
+ value,
554
+ availableSkills,
555
+ workspaceAppIcons,
556
+ effectiveAgentTargets
557
+ );
558
+ const isMentionOnly = isMentionOnlyRichTextDoc(contentDoc);
559
+ const editor = useEditor({
560
+ // AgentGUI is client-only. Deferring editor creation leaves every user
561
+ // message blank for one commit, then changes each transcript turn's
562
+ // measured height when TipTap mounts.
563
+ immediatelyRender: true,
564
+ editable: false,
565
+ extensions: createAgentRichTextReadonlyExtensions({
566
+ skills: availableSkills
567
+ }),
568
+ content: contentDoc,
569
+ editorProps: {
570
+ attributes: {
571
+ class: cn(
572
+ editorClassName,
573
+ "max-w-full overflow-x-hidden overflow-y-auto whitespace-pre-wrap break-words [overflow-wrap:anywhere] [&_p]:m-0 [&_p]:min-h-[1.45em] [&_a[data-agent-file-mention=true]]:cursor-pointer [&_[data-agent-file-mention=true]]:overflow-hidden"
574
+ )
575
+ },
576
+ handleDOMEvents: {
577
+ click: (_view, event) => {
578
+ if (!onLinkClick || !(event.target instanceof Element)) {
579
+ return false;
580
+ }
581
+ const mention = event.target.closest(
582
+ '[data-agent-file-mention="true"]'
583
+ );
584
+ if (!(mention instanceof HTMLElement)) {
585
+ return false;
586
+ }
587
+ const href = mention instanceof HTMLAnchorElement ? mention.getAttribute("href") || "" : mention.getAttribute("data-agent-mention-href") || "";
588
+ if (!href) {
589
+ return false;
590
+ }
591
+ event.preventDefault();
592
+ event.stopPropagation();
593
+ onLinkClick(href);
594
+ return true;
595
+ }
596
+ }
597
+ }
598
+ });
599
+ useEffect(() => {
600
+ if (!editor || editor.isDestroyed) {
601
+ return;
602
+ }
603
+ const nextDoc = plainTextToAgentRichTextDocWithMentionPresentations(
604
+ value,
605
+ availableSkills,
606
+ workspaceAppIcons,
607
+ effectiveAgentTargets
608
+ );
609
+ if (JSON.stringify(editor.getJSON()) === JSON.stringify(nextDoc)) {
610
+ return;
611
+ }
612
+ editor.commands.setContent(nextDoc, { emitUpdate: false });
613
+ }, [
614
+ availableSkills,
615
+ effectiveAgentTargets,
616
+ editor,
617
+ value,
618
+ workspaceAppIcons
619
+ ]);
620
+ if (!editor) {
621
+ return /* @__PURE__ */ jsx(
622
+ "div",
623
+ {
624
+ className,
625
+ "data-agent-mention-only": isMentionOnly ? "true" : void 0
626
+ }
627
+ );
628
+ }
629
+ return /* @__PURE__ */ jsx(
630
+ "div",
631
+ {
632
+ className,
633
+ "data-agent-mention-only": isMentionOnly ? "true" : void 0,
634
+ children: /* @__PURE__ */ jsx(EditorContent, { editor })
635
+ }
636
+ );
637
+ }
638
+ function isMentionOnlyRichTextDoc(doc) {
639
+ if (doc.type !== "doc") {
640
+ return false;
641
+ }
642
+ const blocks = doc.content ?? [];
643
+ if (blocks.length !== 1) {
644
+ return false;
645
+ }
646
+ const paragraph = blocks[0];
647
+ if (paragraph?.type !== "paragraph") {
648
+ return false;
649
+ }
650
+ const inlineContent = (paragraph.content ?? []).filter(
651
+ (node) => !(node.type === "text" && (node.text ?? "").replaceAll(AGENT_RICH_TEXT_CARET_ANCHOR, "").length === 0)
652
+ );
653
+ return inlineContent.length === 1 && inlineContent[0]?.type === "agentFileMention";
654
+ }
655
+ function plainTextToAgentRichTextDocWithMentionPresentations(value, availableSkills, workspaceAppIcons, agentTargets) {
656
+ let doc = plainTextToAgentRichTextDoc(value, { skills: availableSkills });
657
+ if (workspaceAppIcons.length > 0) {
658
+ doc = hydrateWorkspaceAppMentionIcons(doc, workspaceAppIcons);
659
+ }
660
+ if (agentTargets.length > 0) {
661
+ doc = hydrateAgentTargetMentionPresentations(doc, agentTargets);
662
+ }
663
+ return doc;
664
+ }
665
+ function hydrateWorkspaceAppMentionIcons(node, workspaceAppIcons) {
666
+ const nextContent = node.content?.map(
667
+ (child) => hydrateWorkspaceAppMentionIcons(child, workspaceAppIcons)
668
+ );
669
+ if (node.type !== "agentFileMention") {
670
+ return nextContent ? { ...node, content: nextContent } : node;
671
+ }
672
+ const attrs = node.attrs ?? {};
673
+ const kind = typeof attrs.kind === "string" ? attrs.kind : "";
674
+ const isWorkspaceAppMention = kind === "workspace-app";
675
+ const isAppWorkspaceReferenceMention = kind === "workspace-reference" && attrs.source === "app";
676
+ if (!isWorkspaceAppMention && !isAppWorkspaceReferenceMention) {
677
+ return nextContent ? { ...node, content: nextContent } : node;
678
+ }
679
+ const workspaceId = typeof attrs.workspaceId === "string" ? attrs.workspaceId.trim() : "";
680
+ const appId = isWorkspaceAppMention && typeof attrs.appId === "string" ? attrs.appId.trim() : typeof attrs.targetId === "string" ? attrs.targetId.trim() : "";
681
+ const iconUrl = resolveWorkspaceAppIconUrl({
682
+ appId,
683
+ workspaceId,
684
+ workspaceAppIcons
685
+ });
686
+ if (!iconUrl) {
687
+ return nextContent ? { ...node, content: nextContent } : node;
688
+ }
689
+ return {
690
+ ...node,
691
+ attrs: {
692
+ ...node.attrs,
693
+ iconUrl
694
+ },
695
+ ...nextContent ? { content: nextContent } : {}
696
+ };
697
+ }
698
+ function resolveWorkspaceAppIconUrl(input) {
699
+ if (!input.appId) {
700
+ return void 0;
701
+ }
702
+ const exactMatch = input.workspaceAppIcons.find(
703
+ (icon) => icon.appId.trim() === input.appId && (icon.workspaceId?.trim() ?? "") === input.workspaceId && icon.iconUrl?.trim()
704
+ );
705
+ const fallbackMatch = input.workspaceAppIcons.find(
706
+ (icon) => icon.appId.trim() === input.appId && icon.iconUrl?.trim()
707
+ );
708
+ return exactMatch?.iconUrl?.trim() || fallbackMatch?.iconUrl?.trim() || void 0;
709
+ }
710
+ function hydrateAgentTargetMentionPresentations(node, agentTargets) {
711
+ const nextContent = node.content?.map(
712
+ (child) => hydrateAgentTargetMentionPresentations(child, agentTargets)
713
+ );
714
+ if (node.type !== "agentFileMention") {
715
+ return nextContent ? { ...node, content: nextContent } : node;
716
+ }
717
+ const attrs = node.attrs ?? {};
718
+ if (attrs.kind !== "agent-target") {
719
+ return nextContent ? { ...node, content: nextContent } : node;
720
+ }
721
+ const agentTargetId = typeof attrs.targetId === "string" ? attrs.targetId.trim() : "";
722
+ const workspaceId = typeof attrs.workspaceId === "string" ? attrs.workspaceId.trim() : "";
723
+ const target = resolveAgentTargetPresentation({
724
+ agentTargetId,
725
+ agentTargets,
726
+ workspaceId
727
+ });
728
+ if (!target) {
729
+ return nextContent ? { ...node, content: nextContent } : node;
730
+ }
731
+ return {
732
+ ...node,
733
+ attrs: {
734
+ ...node.attrs,
735
+ agentProviderId: target.provider?.trim() ?? "",
736
+ iconUrl: target.iconUrl?.trim() ?? "",
737
+ name: target.name?.trim() || attrs.name
738
+ },
739
+ ...nextContent ? { content: nextContent } : {}
740
+ };
741
+ }
742
+
743
+ export {
744
+ skillTriggerForPrefix,
745
+ labelForProviderSkill,
746
+ promptForProviderSkills,
747
+ skillDescriptionForDisplay,
748
+ createAgentRichTextInputExtensions,
749
+ plainTextToAgentRichTextDoc,
750
+ plainTextToAgentRichTextInlineContent,
751
+ editorToPromptText,
752
+ agentRichTextContentToPromptText,
753
+ AgentRichTextReadonly
754
+ };
755
+ //# sourceMappingURL=chunk-UFIEUC3Y.js.map