@agent-native/toolkit 0.16.16 → 0.17.0-nightly-20260826025507
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.
- package/dist/composer/MentionItemMedia.d.ts +9 -0
- package/dist/composer/MentionItemMedia.d.ts.map +1 -0
- package/dist/composer/MentionItemMedia.js +57 -0
- package/dist/composer/MentionItemMedia.js.map +1 -0
- package/dist/composer/MentionItemMedia.spec.d.ts +2 -0
- package/dist/composer/MentionItemMedia.spec.d.ts.map +1 -0
- package/dist/composer/MentionItemMedia.spec.js +72 -0
- package/dist/composer/MentionItemMedia.spec.js.map +1 -0
- package/dist/composer/MentionPopover.d.ts.map +1 -1
- package/dist/composer/MentionPopover.js +3 -24
- package/dist/composer/MentionPopover.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +4 -1
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.spec.js +54 -0
- package/dist/composer/TiptapComposer.spec.js.map +1 -1
- package/dist/composer/extensions/MentionReference.d.ts.map +1 -1
- package/dist/composer/extensions/MentionReference.js +43 -23
- package/dist/composer/extensions/MentionReference.js.map +1 -1
- package/dist/composer/index.d.ts +1 -1
- package/dist/composer/index.d.ts.map +1 -1
- package/dist/composer/runtime-adapters.d.ts +2 -0
- package/dist/composer/runtime-adapters.d.ts.map +1 -1
- package/dist/composer/runtime-adapters.js.map +1 -1
- package/dist/composer/types.d.ts +21 -0
- package/dist/composer/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/composer/MentionItemMedia.spec.tsx +150 -0
- package/src/composer/MentionItemMedia.tsx +130 -0
- package/src/composer/MentionPopover.tsx +5 -32
- package/src/composer/TiptapComposer.spec.ts +63 -0
- package/src/composer/TiptapComposer.tsx +8 -1
- package/src/composer/extensions/MentionReference.tsx +54 -34
- package/src/composer/index.ts +2 -0
- package/src/composer/runtime-adapters.tsx +3 -0
- package/src/composer/types.ts +23 -0
|
@@ -188,6 +188,69 @@ describe("createTiptapComposerExtensions", () => {
|
|
|
188
188
|
editor.destroy();
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
+
it.each([
|
|
192
|
+
[
|
|
193
|
+
"text",
|
|
194
|
+
{
|
|
195
|
+
type: "text",
|
|
196
|
+
text: "PK",
|
|
197
|
+
backgroundColor: "#4f46e5",
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
[
|
|
201
|
+
"image",
|
|
202
|
+
{
|
|
203
|
+
type: "image",
|
|
204
|
+
src: "/agents/property.png",
|
|
205
|
+
fit: "cover",
|
|
206
|
+
backgroundColor: "#ffffff",
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
["none", { type: "none" }],
|
|
210
|
+
] as const)(
|
|
211
|
+
"preserves %s mention media through HTML drafts",
|
|
212
|
+
(_type, media) => {
|
|
213
|
+
const first = new Editor({
|
|
214
|
+
element: document.createElement("div"),
|
|
215
|
+
extensions: createTiptapComposerExtensions(() => "Message agent..."),
|
|
216
|
+
content: {
|
|
217
|
+
type: "doc",
|
|
218
|
+
content: [
|
|
219
|
+
{
|
|
220
|
+
type: "paragraph",
|
|
221
|
+
content: [
|
|
222
|
+
{
|
|
223
|
+
type: "mentionReference",
|
|
224
|
+
attrs: {
|
|
225
|
+
label: "Property agent",
|
|
226
|
+
media,
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
],
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
const html = first.getHTML();
|
|
235
|
+
first.destroy();
|
|
236
|
+
|
|
237
|
+
expect(html).toContain("data-media=");
|
|
238
|
+
expect(html).not.toContain("[object Object]");
|
|
239
|
+
|
|
240
|
+
const restored = new Editor({
|
|
241
|
+
element: document.createElement("div"),
|
|
242
|
+
extensions: createTiptapComposerExtensions(() => "Message agent..."),
|
|
243
|
+
content: html,
|
|
244
|
+
});
|
|
245
|
+
const mentionNode = restored.getJSON().content?.[0]?.content?.[0] as
|
|
246
|
+
| { attrs?: Record<string, unknown> }
|
|
247
|
+
| undefined;
|
|
248
|
+
restored.destroy();
|
|
249
|
+
|
|
250
|
+
expect(mentionNode?.attrs?.media).toEqual(media);
|
|
251
|
+
},
|
|
252
|
+
);
|
|
253
|
+
|
|
191
254
|
it("allows sending an attachment-only prompt", () => {
|
|
192
255
|
expect(
|
|
193
256
|
canSubmitComposerContent({
|
|
@@ -44,6 +44,7 @@ import { getComposerDraftKey } from "./draft-key.js";
|
|
|
44
44
|
import { FileReference } from "./extensions/FileReference.js";
|
|
45
45
|
import { MentionReference } from "./extensions/MentionReference.js";
|
|
46
46
|
import { SkillReference } from "./extensions/SkillReference.js";
|
|
47
|
+
import { MentionItemMedia } from "./MentionItemMedia.js";
|
|
47
48
|
import { MentionPopover, type MentionPopoverRef } from "./MentionPopover.js";
|
|
48
49
|
import {
|
|
49
50
|
isClaudeCodeAgentId,
|
|
@@ -179,6 +180,7 @@ function composerReferenceFromMentionItem(
|
|
|
179
180
|
return {
|
|
180
181
|
label: item.label,
|
|
181
182
|
icon: item.icon || "file",
|
|
183
|
+
media: item.media,
|
|
182
184
|
source: item.source,
|
|
183
185
|
refType: item.refType,
|
|
184
186
|
refId: item.refId || null,
|
|
@@ -195,6 +197,7 @@ function mentionReferenceAttrs(ref: AgentComposerReference) {
|
|
|
195
197
|
return {
|
|
196
198
|
label: ref.label,
|
|
197
199
|
icon: ref.icon || "file",
|
|
200
|
+
media: ref.media || null,
|
|
198
201
|
source: ref.source,
|
|
199
202
|
refType: ref.refType,
|
|
200
203
|
refId: ref.refId || null,
|
|
@@ -3693,7 +3696,11 @@ export function TiptapComposer({
|
|
|
3693
3696
|
key={ref.slotKey}
|
|
3694
3697
|
className="inline-flex max-w-full items-center gap-1.5 rounded-md border border-border bg-background px-2 py-1 text-[11px] font-medium text-foreground shadow-sm"
|
|
3695
3698
|
>
|
|
3696
|
-
<
|
|
3699
|
+
<MentionItemMedia
|
|
3700
|
+
media={ref.media}
|
|
3701
|
+
size="sm"
|
|
3702
|
+
fallbackIcon="clipboard"
|
|
3703
|
+
/>
|
|
3697
3704
|
{ref.slotLabel && (
|
|
3698
3705
|
<span className="shrink-0 text-muted-foreground">
|
|
3699
3706
|
{ref.slotLabel}
|
|
@@ -1,40 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IconFile,
|
|
3
|
-
IconFolder,
|
|
4
|
-
IconFileText,
|
|
5
|
-
IconCheckbox,
|
|
6
|
-
IconMail,
|
|
7
|
-
IconUser,
|
|
8
|
-
IconPresentation,
|
|
9
|
-
IconStack2,
|
|
10
|
-
IconMessageChatbot,
|
|
11
|
-
} from "@tabler/icons-react";
|
|
12
1
|
import { mergeAttributes, Node } from "@tiptap/core";
|
|
13
2
|
import { NodeViewWrapper, ReactNodeViewRenderer } from "@tiptap/react";
|
|
14
3
|
|
|
15
|
-
|
|
4
|
+
import { MentionItemMedia } from "../MentionItemMedia.js";
|
|
5
|
+
import type { MentionItemMedia as MentionItemMediaValue } from "../types.js";
|
|
16
6
|
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
7
|
+
function parseMentionItemMedia(
|
|
8
|
+
value: string | null,
|
|
9
|
+
): MentionItemMediaValue | null {
|
|
10
|
+
if (!value) return null;
|
|
11
|
+
try {
|
|
12
|
+
const parsed: unknown = JSON.parse(value);
|
|
13
|
+
if (
|
|
14
|
+
typeof parsed !== "object" ||
|
|
15
|
+
parsed === null ||
|
|
16
|
+
Array.isArray(parsed)
|
|
17
|
+
) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const candidate = parsed as Record<string, unknown>;
|
|
21
|
+
const backgroundColor =
|
|
22
|
+
typeof candidate.backgroundColor === "string"
|
|
23
|
+
? candidate.backgroundColor
|
|
24
|
+
: undefined;
|
|
25
|
+
if (candidate.type === "none") return { type: "none" };
|
|
26
|
+
if (candidate.type === "text" && typeof candidate.text === "string") {
|
|
27
|
+
return {
|
|
28
|
+
type: "text",
|
|
29
|
+
text: candidate.text,
|
|
30
|
+
...(backgroundColor ? { backgroundColor } : {}),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (candidate.type === "image" && typeof candidate.src === "string") {
|
|
34
|
+
return {
|
|
35
|
+
type: "image",
|
|
36
|
+
src: candidate.src,
|
|
37
|
+
...(candidate.fit === "cover" ? { fit: "cover" } : {}),
|
|
38
|
+
...(backgroundColor ? { backgroundColor } : {}),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// coercion-ok: Malformed optional media must preserve legacy draft rendering.
|
|
42
|
+
} catch {}
|
|
43
|
+
return null;
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
const MentionReferenceComponent = ({ node }: { node: any }) => {
|
|
@@ -44,7 +50,12 @@ const MentionReferenceComponent = ({ node }: { node: any }) => {
|
|
|
44
50
|
className="inline-flex items-center gap-1 rounded-md border border-input bg-muted/50 px-1.5 py-0.5 text-xs font-medium text-foreground align-middle mx-0.5 max-w-[200px] select-none"
|
|
45
51
|
title={node.attrs.refPath || node.attrs.refId || node.attrs.label}
|
|
46
52
|
>
|
|
47
|
-
<
|
|
53
|
+
<MentionItemMedia
|
|
54
|
+
icon={node.attrs.icon}
|
|
55
|
+
media={node.attrs.media}
|
|
56
|
+
size="sm"
|
|
57
|
+
fallbackIcon="stack"
|
|
58
|
+
/>
|
|
48
59
|
<span className="truncate">{node.attrs.label}</span>
|
|
49
60
|
</span>
|
|
50
61
|
</NodeViewWrapper>
|
|
@@ -62,6 +73,15 @@ export const MentionReference = Node.create({
|
|
|
62
73
|
return {
|
|
63
74
|
label: { default: null },
|
|
64
75
|
icon: { default: "file" },
|
|
76
|
+
media: {
|
|
77
|
+
default: null,
|
|
78
|
+
parseHTML: (element) =>
|
|
79
|
+
parseMentionItemMedia(element.getAttribute("data-media")),
|
|
80
|
+
renderHTML: (attributes) =>
|
|
81
|
+
attributes.media
|
|
82
|
+
? { "data-media": JSON.stringify(attributes.media) }
|
|
83
|
+
: {},
|
|
84
|
+
},
|
|
65
85
|
source: { default: "" },
|
|
66
86
|
refType: { default: "file" },
|
|
67
87
|
refId: { default: null },
|
package/src/composer/index.ts
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
type ReactNode,
|
|
7
7
|
} from "react";
|
|
8
8
|
|
|
9
|
+
import type { MentionItemMedia } from "./types.js";
|
|
10
|
+
|
|
9
11
|
export type ComposerTranslate = (
|
|
10
12
|
key: string,
|
|
11
13
|
options?: Record<string, unknown>,
|
|
@@ -86,6 +88,7 @@ export interface ComposerBuilderConnectFlowOptions {
|
|
|
86
88
|
export interface AgentComposerReference {
|
|
87
89
|
label: string;
|
|
88
90
|
icon?: string;
|
|
91
|
+
media?: MentionItemMedia;
|
|
89
92
|
source?: string;
|
|
90
93
|
refType: string;
|
|
91
94
|
refId?: string | null;
|
package/src/composer/types.ts
CHANGED
|
@@ -12,11 +12,32 @@ export interface SkillResult {
|
|
|
12
12
|
source: "codebase" | "resource";
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
export type MentionItemMedia =
|
|
16
|
+
| {
|
|
17
|
+
type: "text";
|
|
18
|
+
/** Short text shown inside the media frame, such as an emoji or initials. */
|
|
19
|
+
text: string;
|
|
20
|
+
/** Optional CSS color used behind the text. */
|
|
21
|
+
backgroundColor?: string;
|
|
22
|
+
}
|
|
23
|
+
| {
|
|
24
|
+
type: "image";
|
|
25
|
+
/** Image URL shown inside the media frame. Relative URLs are supported. */
|
|
26
|
+
src: string;
|
|
27
|
+
/** How the image fits the frame. Defaults to contain. */
|
|
28
|
+
fit?: "contain" | "cover";
|
|
29
|
+
/** Optional CSS color visible behind contained images. */
|
|
30
|
+
backgroundColor?: string;
|
|
31
|
+
}
|
|
32
|
+
| { type: "none" };
|
|
33
|
+
|
|
15
34
|
export interface MentionItem {
|
|
16
35
|
id: string;
|
|
17
36
|
label: string;
|
|
18
37
|
description?: string;
|
|
19
38
|
icon?: string;
|
|
39
|
+
/** Optional presentation that takes precedence over the legacy icon. */
|
|
40
|
+
media?: MentionItemMedia;
|
|
20
41
|
source: string;
|
|
21
42
|
refType: string;
|
|
22
43
|
refPath?: string;
|
|
@@ -44,6 +65,8 @@ export interface Reference {
|
|
|
44
65
|
export interface MentionReferenceInsert {
|
|
45
66
|
label: string;
|
|
46
67
|
icon?: string;
|
|
68
|
+
/** Optional presentation that takes precedence over the legacy icon. */
|
|
69
|
+
media?: MentionItemMedia;
|
|
47
70
|
source?: string;
|
|
48
71
|
refType: string;
|
|
49
72
|
refId?: string | null;
|