@agent-native/core 0.12.21 → 0.12.23
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/agent/engine/ai-sdk-engine.d.ts +2 -0
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +11 -5
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +2 -1
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +117 -8
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +24 -13
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts +2 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +21 -11
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/checkpoints/service.d.ts +1 -0
- package/dist/checkpoints/service.d.ts.map +1 -1
- package/dist/checkpoints/service.js +6 -3
- package/dist/checkpoints/service.js.map +1 -1
- package/dist/client/AgentPanel.js +1 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +133 -6
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/FeedbackButton.js +1 -1
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +26 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/components/ui/tooltip.js +1 -1
- package/dist/client/components/ui/tooltip.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +2 -6
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/useVoiceDictation.d.ts +1 -0
- package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
- package/dist/client/composer/useVoiceDictation.js +52 -7
- package/dist/client/composer/useVoiceDictation.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +1 -1
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +3 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js +12 -0
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/mcp-client/errors.d.ts +2 -0
- package/dist/mcp-client/errors.d.ts.map +1 -0
- package/dist/mcp-client/errors.js +47 -0
- package/dist/mcp-client/errors.js.map +1 -0
- package/dist/mcp-client/manager.d.ts.map +1 -1
- package/dist/mcp-client/manager.js +44 -15
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/mcp-client/routes.d.ts +1 -2
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +2 -27
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/progress/store.d.ts +2 -0
- package/dist/progress/store.d.ts.map +1 -1
- package/dist/progress/store.js +44 -0
- package/dist/progress/store.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +38 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +31 -9
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +8 -0
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +29 -3
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/security-headers.d.ts +5 -4
- package/dist/server/security-headers.d.ts.map +1 -1
- package/dist/server/security-headers.js +6 -5
- package/dist/server/security-headers.js.map +1 -1
- package/dist/terminal/terminal-plugin.d.ts.map +1 -1
- package/dist/terminal/terminal-plugin.js +4 -3
- package/dist/terminal/terminal-plugin.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AA6Bf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
|
|
@@ -70,6 +70,111 @@ function getFileDataURL(file) {
|
|
|
70
70
|
reader.readAsDataURL(file);
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
|
+
function escapeQueuedAttachmentAttribute(value) {
|
|
74
|
+
return value.replace(/&/g, "&").replace(/"/g, """);
|
|
75
|
+
}
|
|
76
|
+
function isTextLikeFile(file) {
|
|
77
|
+
if (file.type.startsWith("text/"))
|
|
78
|
+
return true;
|
|
79
|
+
if (file.type === "application/json")
|
|
80
|
+
return true;
|
|
81
|
+
return /\.(txt|md|markdown|csv|json|yaml|yml)$/i.test(file.name);
|
|
82
|
+
}
|
|
83
|
+
function textFileAttachmentEnvelope(file, text) {
|
|
84
|
+
const contentType = file.type || "text/plain";
|
|
85
|
+
return `<attachment name="${escapeQueuedAttachmentAttribute(file.name)}" contentType="${escapeQueuedAttachmentAttribute(contentType)}">\n${text}\n</attachment>`;
|
|
86
|
+
}
|
|
87
|
+
function serializeAttachmentContentPart(part) {
|
|
88
|
+
if (part.type === "image" && typeof part.image === "string") {
|
|
89
|
+
return { type: "image", image: part.image };
|
|
90
|
+
}
|
|
91
|
+
if (part.type === "text" && typeof part.text === "string") {
|
|
92
|
+
return { type: "text", text: part.text };
|
|
93
|
+
}
|
|
94
|
+
if (part.type === "file" && typeof part.data === "string") {
|
|
95
|
+
return {
|
|
96
|
+
type: "file",
|
|
97
|
+
data: part.data,
|
|
98
|
+
mimeType: typeof part.mimeType === "string"
|
|
99
|
+
? part.mimeType
|
|
100
|
+
: "application/octet-stream",
|
|
101
|
+
...(typeof part.filename === "string" ? { filename: part.filename } : {}),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
async function serializeQueuedAttachments(attachments) {
|
|
107
|
+
const queued = [];
|
|
108
|
+
for (const raw of attachments ?? []) {
|
|
109
|
+
const attachment = raw;
|
|
110
|
+
const name = attachment.name || attachment.file?.name || "attachment";
|
|
111
|
+
const id = attachment.id || name;
|
|
112
|
+
const type = attachment.type || "file";
|
|
113
|
+
const contentType = attachment.contentType || attachment.file?.type;
|
|
114
|
+
if (Array.isArray(attachment.content) && attachment.content.length > 0) {
|
|
115
|
+
const content = attachment.content
|
|
116
|
+
.map((part) => serializeAttachmentContentPart(part))
|
|
117
|
+
.filter((part) => !!part);
|
|
118
|
+
if (content.length > 0) {
|
|
119
|
+
queued.push({
|
|
120
|
+
id,
|
|
121
|
+
type,
|
|
122
|
+
name,
|
|
123
|
+
contentType,
|
|
124
|
+
status: { type: "complete" },
|
|
125
|
+
content,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (typeof File !== "undefined" && attachment.file instanceof File) {
|
|
131
|
+
const file = attachment.file;
|
|
132
|
+
if (file.type.startsWith("image/")) {
|
|
133
|
+
queued.push({
|
|
134
|
+
id,
|
|
135
|
+
type: "image",
|
|
136
|
+
name,
|
|
137
|
+
contentType: file.type,
|
|
138
|
+
status: { type: "complete" },
|
|
139
|
+
content: [{ type: "image", image: await getFileDataURL(file) }],
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else if (isTextLikeFile(file)) {
|
|
143
|
+
queued.push({
|
|
144
|
+
id,
|
|
145
|
+
type: "file",
|
|
146
|
+
name,
|
|
147
|
+
contentType: file.type || "text/plain",
|
|
148
|
+
status: { type: "complete" },
|
|
149
|
+
content: [
|
|
150
|
+
{
|
|
151
|
+
type: "text",
|
|
152
|
+
text: textFileAttachmentEnvelope(file, await file.text()),
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
queued.push({
|
|
159
|
+
id,
|
|
160
|
+
type: "document",
|
|
161
|
+
name,
|
|
162
|
+
contentType: inferDocumentContentType(file),
|
|
163
|
+
status: { type: "complete" },
|
|
164
|
+
content: [
|
|
165
|
+
{
|
|
166
|
+
type: "file",
|
|
167
|
+
filename: file.name,
|
|
168
|
+
data: await getFileDataURL(file),
|
|
169
|
+
mimeType: inferDocumentContentType(file),
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return queued.length > 0 ? queued : undefined;
|
|
177
|
+
}
|
|
73
178
|
// ─── Markdown Text ──────────────────────────────────────────────────────────
|
|
74
179
|
const markdownStyles = `
|
|
75
180
|
.agent-markdown > :first-child { margin-top: 0; }
|
|
@@ -922,6 +1027,17 @@ function getRunErrorMetadata(message) {
|
|
|
922
1027
|
...(runError.recoverable ? { recoverable: true } : {}),
|
|
923
1028
|
};
|
|
924
1029
|
}
|
|
1030
|
+
function isBuilderReconnectRunError(info) {
|
|
1031
|
+
const code = (info.errorCode ?? "").toLowerCase();
|
|
1032
|
+
const message = info.message.toLowerCase();
|
|
1033
|
+
const isAuthCode = code === "authentication_error" ||
|
|
1034
|
+
code === "unauthorized" ||
|
|
1035
|
+
code === "http_401" ||
|
|
1036
|
+
code === "http_403";
|
|
1037
|
+
return (code === "builder_auth_error" ||
|
|
1038
|
+
message.includes("builder authentication failed") ||
|
|
1039
|
+
(isAuthCode && message.includes("invalid token")));
|
|
1040
|
+
}
|
|
925
1041
|
function getMessageText(message) {
|
|
926
1042
|
const msg = message?.message ?? message;
|
|
927
1043
|
const content = msg?.content;
|
|
@@ -938,6 +1054,7 @@ function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDismiss, })
|
|
|
938
1054
|
const [detailsOpen, setDetailsOpen] = useState(false);
|
|
939
1055
|
const [copied, setCopied] = useState(false);
|
|
940
1056
|
const canRecover = info.recoverable === true;
|
|
1057
|
+
const shouldShowBuilderReconnect = isBuilderReconnectRunError(info);
|
|
941
1058
|
const copyDetails = useCallback(() => {
|
|
942
1059
|
const text = [
|
|
943
1060
|
info.message,
|
|
@@ -953,7 +1070,7 @@ function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDismiss, })
|
|
|
953
1070
|
}, [info]);
|
|
954
1071
|
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: canRecover
|
|
955
1072
|
? "The agent stopped before finishing"
|
|
956
|
-
: "The agent hit an error" }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: info.message }), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), "Details"] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [canRecover && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), "Continue"] }), _jsxs("button", { type: "button", onClick: onRetry, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { size: 13 }), "Retry"] })] })), canRecover && onFork && (_jsxs("button", { type: "button", onClick: onFork, title: "Fork this conversation into a separate chat thread.", "aria-label": "Fork this conversation into a separate chat thread", className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconGitFork, { size: 13 }), "Fork chat"] })), _jsxs("button", { type: "button", onClick: copyDetails, className: "ml-auto inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground hover:bg-background/80 hover:text-foreground", children: [copied ? _jsx(IconCheck, { size: 13 }) : _jsx(IconCopy, { size: 13 }), copied ? "Copied" : "Copy"] })] })] }));
|
|
1073
|
+
: "The agent hit an error" }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: info.message }), shouldShowBuilderReconnect && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "The current Builder.io or model-provider credential was rejected. Reconnect Builder.io, then retry this message." })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), "Details"] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [shouldShowBuilderReconnect && (_jsxs("a", { href: agentNativePath("/_agent-native/builder/connect"), target: "_blank", rel: "noreferrer", className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconExternalLink, { size: 13 }), "Reconnect Builder.io"] })), canRecover && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), "Continue"] }), _jsxs("button", { type: "button", onClick: onRetry, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { size: 13 }), "Retry"] })] })), canRecover && onFork && (_jsxs("button", { type: "button", onClick: onFork, title: "Fork this conversation into a separate chat thread.", "aria-label": "Fork this conversation into a separate chat thread", className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconGitFork, { size: 13 }), "Fork chat"] })), _jsxs("button", { type: "button", onClick: copyDetails, className: "ml-auto inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground hover:bg-background/80 hover:text-foreground", children: [copied ? _jsx(IconCheck, { size: 13 }) : _jsx(IconCopy, { size: 13 }), copied ? "Copied" : "Copy"] })] })] }));
|
|
957
1074
|
}
|
|
958
1075
|
function LoopLimitContinueCard({ info, onContinue, }) {
|
|
959
1076
|
const [settings, setSettings] = useState(null);
|
|
@@ -1697,6 +1814,9 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1697
1814
|
threadRuntime.append({
|
|
1698
1815
|
role: "user",
|
|
1699
1816
|
content,
|
|
1817
|
+
...(next.attachments && next.attachments.length > 0
|
|
1818
|
+
? { attachments: next.attachments }
|
|
1819
|
+
: {}),
|
|
1700
1820
|
...(next.references && next.references.length > 0
|
|
1701
1821
|
? { runConfig: { custom: { references: next.references } } }
|
|
1702
1822
|
: {}),
|
|
@@ -1735,7 +1855,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1735
1855
|
setForceStopped(false);
|
|
1736
1856
|
}
|
|
1737
1857
|
}, [isReconnecting, forceStopped]);
|
|
1738
|
-
const addToQueue = useCallback((text, images, references) => {
|
|
1858
|
+
const addToQueue = useCallback(async (text, images, references, attachments) => {
|
|
1739
1859
|
setShowContinue(false);
|
|
1740
1860
|
setLoopLimitInfo(null);
|
|
1741
1861
|
setRunErrorInfo(null);
|
|
@@ -1746,6 +1866,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1746
1866
|
// Selection context attached via Cmd+I is one-shot — clear it as soon
|
|
1747
1867
|
// as the user actually sends a message so it can't be re-used.
|
|
1748
1868
|
clearPendingSelection();
|
|
1869
|
+
const queuedAttachments = await serializeQueuedAttachments(attachments);
|
|
1749
1870
|
if (isRunning) {
|
|
1750
1871
|
setQueuedMessages((prev) => [
|
|
1751
1872
|
...prev,
|
|
@@ -1755,6 +1876,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1755
1876
|
: `q-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
1756
1877
|
text,
|
|
1757
1878
|
images,
|
|
1879
|
+
attachments: queuedAttachments,
|
|
1758
1880
|
references,
|
|
1759
1881
|
},
|
|
1760
1882
|
]);
|
|
@@ -1766,7 +1888,13 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1766
1888
|
content.push({ type: "image", image: img });
|
|
1767
1889
|
}
|
|
1768
1890
|
}
|
|
1769
|
-
threadRuntime.append({
|
|
1891
|
+
threadRuntime.append({
|
|
1892
|
+
role: "user",
|
|
1893
|
+
content,
|
|
1894
|
+
...(queuedAttachments && queuedAttachments.length > 0
|
|
1895
|
+
? { attachments: queuedAttachments }
|
|
1896
|
+
: {}),
|
|
1897
|
+
});
|
|
1770
1898
|
}
|
|
1771
1899
|
}, [isRunning, threadRuntime]);
|
|
1772
1900
|
// Expose imperative handle
|
|
@@ -1967,8 +2095,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1967
2095
|
return (_jsx("div", { className: "flex justify-end group", children: _jsxs("div", { className: "relative max-w-[85%] rounded-lg bg-accent/50 text-foreground/60 px-3 py-2 text-sm leading-relaxed whitespace-pre-wrap break-words", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground mb-1 font-medium uppercase tracking-wide", children: [_jsx(IconClock, { className: "h-3 w-3" }), "Queued"] }), displayText, msg.images && msg.images.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: msg.images.map((img, j) => (_jsx("img", { src: img, alt: "", className: "h-12 w-12 rounded object-cover border border-border/50" }, j))) })), _jsx("button", { type: "button", onClick: () => setQueuedMessages((prev) => prev.filter((m) => m.id !== msg.id)), "aria-label": "Remove from queue", className: "absolute -top-2 -right-2 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:text-foreground hover:bg-accent shadow-sm", children: _jsx(IconX, { className: "h-3 w-3" }) })] }) }, msg.id));
|
|
1968
2096
|
})] })) }), showScrollToBottom && (_jsx("div", { className: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { type: "button", onClick: scrollToBottom, className: "flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent", "aria-label": "Scroll to bottom", children: _jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) }) })), composerSlot, _jsx(SelectionAttachedPill, {}), _jsx("div", { className: cn("agent-composer-area shrink-0 px-3 py-2", missingApiKey && "cursor-pointer", isComposerDisabled && "opacity-70"), onClick: missingApiKey
|
|
1969
2097
|
? () => setMissingKeyBouncePulse((p) => p + 1)
|
|
1970
|
-
: undefined, children: _jsxs(ComposerPrimitive.Root, { className:
|
|
1971
|
-
"border-amber-500/50 bg-amber-500/[0.03] focus-within:ring-amber-500/30"), children: [_jsx(ComposerAttachmentPreviewStrip, {}), _jsx(TiptapComposer, { focusRef: tiptapRef, disabled: isComposerDisabled, placeholder: missingApiKey
|
|
2098
|
+
: undefined, children: _jsxs(ComposerPrimitive.Root, { className: "flex flex-col rounded-lg border border-input bg-background focus-within:ring-1 focus-within:ring-ring", children: [_jsx(ComposerAttachmentPreviewStrip, {}), _jsx(TiptapComposer, { focusRef: tiptapRef, disabled: isComposerDisabled, placeholder: missingApiKey
|
|
1972
2099
|
? "Connect an AI engine above to start chatting…"
|
|
1973
2100
|
: composerDisabled
|
|
1974
2101
|
? (composerDisabledPlaceholder ??
|
|
@@ -1978,7 +2105,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1978
2105
|
? `${queuedMessages.length} queued — type another...`
|
|
1979
2106
|
: "Queue a message..."
|
|
1980
2107
|
: undefined, onSubmit: isRunning
|
|
1981
|
-
? (text, references) => addToQueue(text, undefined, references.length > 0 ? references : undefined)
|
|
2108
|
+
? (text, references, attachments) => void addToQueue(text, undefined, references.length > 0 ? references : undefined, attachments)
|
|
1982
2109
|
: undefined, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason, selectedModel: selectedModel ?? defaultModel, selectedEffort: selectedEffort, availableModels: availableModels, onModelChange: onModelChange, onEffortChange: onEffortChange, draftScope: threadId || tabId, interceptBuildRequestsForBuilder: true, extraActionButton: showRunningInUI ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => {
|
|
1983
2110
|
// Nuclear stop: flip forceStopped so isRunning is false
|
|
1984
2111
|
// immediately. This unblocks submission even if the
|