@agent-native/core 0.12.23 → 0.12.24
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/thread-data-builder.d.ts +10 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +80 -0
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/agent/types.d.ts +7 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +3 -3
- package/dist/cli/create.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +9 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +49 -10
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +3 -2
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +93 -45
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/PromptComposer.js +1 -1
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +5 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +10 -1
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +2 -1
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/progress/RunsTray.d.ts.map +1 -1
- package/dist/client/progress/RunsTray.js +18 -3
- package/dist/client/progress/RunsTray.js.map +1 -1
- package/dist/client/resources/ResourceTree.d.ts.map +1 -1
- package/dist/client/resources/ResourceTree.js +5 -4
- package/dist/client/resources/ResourceTree.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +5 -3
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/collab/client.d.ts +9 -0
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +36 -10
- package/dist/collab/client.js.map +1 -1
- package/dist/onboarding/default-steps.js +1 -1
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/progress/store.d.ts.map +1 -1
- package/dist/progress/store.js +1 -1
- package/dist/progress/store.js.map +1 -1
- package/dist/server/action-routes.d.ts +2 -0
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +4 -1
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +27 -15
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/request-context.d.ts +9 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +13 -0
- package/dist/server/request-context.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/client/ErrorBoundary.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/client/ErrorBoundary.tsx"],"names":[],"mappings":"AAoHA,wBAAgB,aAAa,4CAS5B"}
|
|
@@ -31,7 +31,8 @@ function ErrorScreen({ error, canUseRouterLink, }) {
|
|
|
31
31
|
status = error.status;
|
|
32
32
|
if (error.status === 404) {
|
|
33
33
|
title = "Page not found";
|
|
34
|
-
|
|
34
|
+
const path = typeof window !== "undefined" ? window.location.pathname : "this path";
|
|
35
|
+
details = `The app does not define a route for ${path}. If this should be a workspace app, make sure it is added and enabled in Dispatch; if it is a new screen, it may need to be shipped first.`;
|
|
35
36
|
}
|
|
36
37
|
else {
|
|
37
38
|
title = `${error.status} Error`;
|
|
@@ -59,7 +60,7 @@ function ErrorScreen({ error, canUseRouterLink, }) {
|
|
|
59
60
|
if (typeof console !== "undefined" && error) {
|
|
60
61
|
console.error("[ErrorBoundary]", error);
|
|
61
62
|
}
|
|
62
|
-
return (_jsx("main", { className: "flex items-center justify-center min-h-screen p-4 bg-background text-foreground", children: _jsxs("div", { className: "flex flex-col items-center text-center max-w-md", children: [status && (_jsx("span", { className: "text-7xl font-bold tracking-tight text-muted-foreground/40", children: status })), _jsx("h1", { className: "mt-3 text-2xl font-semibold", children: title }), _jsx("p", { className: "mt-2 text-muted-foreground text-sm", children: details }), canUseRouterLink ? (_jsx(Link, { to: "/", className: homeLinkClassName, children: "Go home" })) : (_jsx("a", { href: "/", className: homeLinkClassName, children: "Go home" })), stack && (_jsx("pre", { className: "mt-6 w-full text-left text-xs overflow-auto p-4 bg-muted rounded", children: _jsx("code", { children: stack }) }))] }) }));
|
|
63
|
+
return (_jsx("main", { className: "flex items-center justify-center min-h-screen p-4 bg-background text-foreground", children: _jsxs("div", { className: "flex flex-col items-center text-center max-w-md", children: [status && (_jsx("span", { className: "text-7xl font-bold tracking-tight text-muted-foreground/40", children: status })), _jsx("h1", { className: "mt-3 text-2xl font-semibold", children: title }), _jsx("p", { className: "mt-2 text-muted-foreground text-sm", children: details }), canUseRouterLink ? (_jsx(Link, { to: "/", className: homeLinkClassName, children: "Go home" })) : (_jsx("a", { href: "/", className: homeLinkClassName, children: "Go home" })), _jsx("button", { type: "button", onClick: () => window.location.reload(), className: "mt-3 inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-accent", children: "Reload" }), stack && (_jsx("pre", { className: "mt-6 w-full text-left text-xs overflow-auto p-4 bg-muted rounded", children: _jsx("code", { children: stack }) }))] }) }));
|
|
63
64
|
}
|
|
64
65
|
function RoutedErrorScreen() {
|
|
65
66
|
return _jsx(ErrorScreen, { error: useRouteError(), canUseRouterLink: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorBoundary.js","sourceRoot":"","sources":["../../src/client/ErrorBoundary.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EACL,oBAAoB,EACpB,IAAI,EACJ,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,MAAM,iBAAiB,GACrB,gKAAgK,CAAC;AAEnK,SAAS,kBAAkB;IACzB,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAC;QACtC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC;YACrE,OAAO;QACT,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;iBAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;iBAAM,IAAI,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC,OAAO,EAAE,CAAC;gBACrE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,KAAK,EACL,gBAAgB,GAIjB;IACC,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,KAAK,GAAG,sBAAsB,CAAC;IACnC,IAAI,OAAO,GAAG,+BAA+B,CAAC;IAC9C,IAAI,KAAyB,CAAC;IAE9B,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QACtB,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACzB,KAAK,GAAG,gBAAgB,CAAC;YACzB,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.js","sourceRoot":"","sources":["../../src/client/ErrorBoundary.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect } from \"react\";\nimport {\n isRouteErrorResponse,\n Link,\n useInRouterContext,\n useRouteError,\n} from \"react-router\";\n\nconst homeLinkClassName =\n \"mt-6 inline-flex items-center gap-1.5 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90 cursor-pointer\";\n\nfunction useApplyThemeClass() {\n useEffect(() => {\n const root = document.documentElement;\n if (root.classList.contains(\"dark\") || root.classList.contains(\"light\"))\n return;\n try {\n const stored = localStorage.getItem(\"theme\");\n if (stored === \"dark\") {\n root.classList.add(\"dark\");\n } else if (stored === \"light\") {\n root.classList.add(\"light\");\n } else if (window.matchMedia(\"(prefers-color-scheme: dark)\").matches) {\n root.classList.add(\"dark\");\n }\n } catch {}\n }, []);\n}\n\nfunction ErrorScreen({\n error,\n canUseRouterLink,\n}: {\n error: unknown;\n canUseRouterLink: boolean;\n}) {\n let status: number | null = null;\n let title = \"Something went wrong\";\n let details = \"An unexpected error occurred.\";\n let stack: string | undefined;\n\n if (isRouteErrorResponse(error)) {\n status = error.status;\n if (error.status === 404) {\n title = \"Page not found\";\n const path =\n typeof window !== \"undefined\" ? window.location.pathname : \"this path\";\n details = `The app does not define a route for ${path}. If this should be a workspace app, make sure it is added and enabled in Dispatch; if it is a new screen, it may need to be shipped first.`;\n } else {\n title = `${error.status} Error`;\n details = error.statusText || details;\n }\n } else if (error instanceof Error) {\n // Always surface the underlying error message — a generic\n // \"An unexpected error occurred.\" in production tells users (and us)\n // nothing. The stack trace is still gated to dev so we don't leak\n // internals to end users.\n if (error.message) {\n details = error.message;\n }\n if (\n typeof process !== \"undefined\" &&\n process.env.NODE_ENV !== \"production\"\n ) {\n stack = error.stack;\n }\n } else if (typeof error === \"string\" && error) {\n details = error;\n }\n\n // Log to the console so the underlying failure is recoverable from\n // browser devtools / Sentry even when the UI hides the stack.\n if (typeof console !== \"undefined\" && error) {\n console.error(\"[ErrorBoundary]\", error);\n }\n\n return (\n <main className=\"flex items-center justify-center min-h-screen p-4 bg-background text-foreground\">\n <div className=\"flex flex-col items-center text-center max-w-md\">\n {status && (\n <span className=\"text-7xl font-bold tracking-tight text-muted-foreground/40\">\n {status}\n </span>\n )}\n <h1 className=\"mt-3 text-2xl font-semibold\">{title}</h1>\n <p className=\"mt-2 text-muted-foreground text-sm\">{details}</p>\n {canUseRouterLink ? (\n <Link to=\"/\" className={homeLinkClassName}>\n Go home\n </Link>\n ) : (\n <a href=\"/\" className={homeLinkClassName}>\n Go home\n </a>\n )}\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n className=\"mt-3 inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-accent\"\n >\n Reload\n </button>\n {stack && (\n <pre className=\"mt-6 w-full text-left text-xs overflow-auto p-4 bg-muted rounded\">\n <code>{stack}</code>\n </pre>\n )}\n </div>\n </main>\n );\n}\n\nfunction RoutedErrorScreen() {\n return <ErrorScreen error={useRouteError()} canUseRouterLink />;\n}\n\nexport function ErrorBoundary() {\n useApplyThemeClass();\n const inRouterContext = useInRouterContext();\n\n if (!inRouterContext) {\n return <ErrorScreen error={undefined} canUseRouterLink={false} />;\n }\n\n return <RoutedErrorScreen />;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-chat-adapter.d.ts","sourceRoot":"","sources":["../../src/client/agent-chat-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAehF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-chat-adapter.d.ts","sourceRoot":"","sources":["../../src/client/agent-chat-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAehF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAggBrE;;;;GAIG;AACH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,SAAS,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;CACzD,GAAG,gBAAgB,CAw0BnB"}
|
|
@@ -23,6 +23,7 @@ const MAX_STALLED_TRANSIENT_CONTINUATIONS = 8;
|
|
|
23
23
|
const MAX_TOTAL_TRANSIENT_CONTINUATIONS = 32;
|
|
24
24
|
const RETRY_BASE_DELAY_MS = 500;
|
|
25
25
|
const RETRY_MAX_DELAY_MS = 8_000;
|
|
26
|
+
const MAX_HISTORY_ATTACHMENT_CHARS = 60_000;
|
|
26
27
|
function normalizeMentions(text) {
|
|
27
28
|
return text.replace(/@\[([^\]|]+)\|[^\]]+\]/g, "@$1");
|
|
28
29
|
}
|
|
@@ -58,6 +59,13 @@ function messageTextFromContent(content) {
|
|
|
58
59
|
.map((p) => normalizeMentions(p.text))
|
|
59
60
|
.join("\n");
|
|
60
61
|
}
|
|
62
|
+
function escapeAttachmentAttribute(value) {
|
|
63
|
+
return value
|
|
64
|
+
.replace(/&/g, "&")
|
|
65
|
+
.replace(/"/g, """)
|
|
66
|
+
.replace(/</g, "<")
|
|
67
|
+
.replace(/>/g, ">");
|
|
68
|
+
}
|
|
61
69
|
function isTextAttachmentContentType(value) {
|
|
62
70
|
if (!value)
|
|
63
71
|
return false;
|
|
@@ -84,6 +92,78 @@ function decodeTextDataUrl(dataUrl) {
|
|
|
84
92
|
return null;
|
|
85
93
|
}
|
|
86
94
|
}
|
|
95
|
+
function extractAttachmentsFromMessage(message) {
|
|
96
|
+
const attachments = [];
|
|
97
|
+
for (const att of message.attachments ?? []) {
|
|
98
|
+
for (const part of att.content) {
|
|
99
|
+
if (part.type === "image" && typeof part.image === "string") {
|
|
100
|
+
attachments.push({
|
|
101
|
+
type: "image",
|
|
102
|
+
name: att.name,
|
|
103
|
+
contentType: att.contentType,
|
|
104
|
+
data: part.image,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
else if (part.type === "file" && typeof part.data === "string") {
|
|
108
|
+
const contentType = att.contentType ??
|
|
109
|
+
(typeof part.mimeType === "string" ? part.mimeType : undefined);
|
|
110
|
+
const decodedText = part.data.startsWith("data:")
|
|
111
|
+
? decodeTextDataUrl(part.data)
|
|
112
|
+
: null;
|
|
113
|
+
attachments.push({
|
|
114
|
+
type: "file",
|
|
115
|
+
name: att.name,
|
|
116
|
+
contentType,
|
|
117
|
+
...(decodedText !== null
|
|
118
|
+
? { text: decodedText }
|
|
119
|
+
: part.data.startsWith("data:")
|
|
120
|
+
? { data: part.data }
|
|
121
|
+
: { text: part.data }),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else if (part.type === "text" && typeof part.text === "string") {
|
|
125
|
+
attachments.push({
|
|
126
|
+
type: "file",
|
|
127
|
+
name: att.name,
|
|
128
|
+
contentType: att.contentType,
|
|
129
|
+
text: unwrapAttachmentEnvelope(part.text),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return attachments;
|
|
135
|
+
}
|
|
136
|
+
function truncateHistoryAttachment(text) {
|
|
137
|
+
if (text.length <= MAX_HISTORY_ATTACHMENT_CHARS)
|
|
138
|
+
return text;
|
|
139
|
+
const omitted = text.length - MAX_HISTORY_ATTACHMENT_CHARS;
|
|
140
|
+
return `${text.slice(0, MAX_HISTORY_ATTACHMENT_CHARS)}\n\n[Attachment truncated after ${MAX_HISTORY_ATTACHMENT_CHARS.toLocaleString()} characters; ${omitted.toLocaleString()} characters omitted from prior chat history.]`;
|
|
141
|
+
}
|
|
142
|
+
function attachmentHistoryText(attachment) {
|
|
143
|
+
if (typeof attachment.text === "string" && attachment.text.length > 0) {
|
|
144
|
+
const attrs = [
|
|
145
|
+
`name="${escapeAttachmentAttribute(attachment.name || "attachment")}"`,
|
|
146
|
+
attachment.contentType
|
|
147
|
+
? `contentType="${escapeAttachmentAttribute(attachment.contentType)}"`
|
|
148
|
+
: null,
|
|
149
|
+
attachment.type
|
|
150
|
+
? `type="${escapeAttachmentAttribute(attachment.type)}"`
|
|
151
|
+
: null,
|
|
152
|
+
].filter(Boolean);
|
|
153
|
+
return `<attachment ${attrs.join(" ")}>\n${truncateHistoryAttachment(attachment.text)}\n</attachment>`;
|
|
154
|
+
}
|
|
155
|
+
if (attachment.name) {
|
|
156
|
+
return `[Attached ${attachment.type || "file"}: ${attachment.name}${attachment.contentType ? ` (${attachment.contentType})` : ""}]`;
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
function messageTextForHistory(message) {
|
|
161
|
+
const text = messageTextFromContent(message.content);
|
|
162
|
+
const attachments = extractAttachmentsFromMessage(message)
|
|
163
|
+
.map(attachmentHistoryText)
|
|
164
|
+
.filter((part) => !!part && part.trim().length > 0);
|
|
165
|
+
return [text, ...attachments].filter((part) => part.trim()).join("\n\n");
|
|
166
|
+
}
|
|
87
167
|
function isToolCallContentPart(part) {
|
|
88
168
|
return Boolean(part && typeof part === "object" && part.type === "tool-call");
|
|
89
169
|
}
|
|
@@ -150,7 +230,7 @@ function assistantUiMessagesToStructuredHistory(messages) {
|
|
|
150
230
|
const structured = [];
|
|
151
231
|
for (const message of messages) {
|
|
152
232
|
if (message.role === "user") {
|
|
153
|
-
const text =
|
|
233
|
+
const text = messageTextForHistory(message);
|
|
154
234
|
if (text.trim()) {
|
|
155
235
|
structured.push({
|
|
156
236
|
role: "user",
|
|
@@ -361,47 +441,9 @@ export function createAgentChatAdapter(options) {
|
|
|
361
441
|
// Extract attachments (images as base64, text as content).
|
|
362
442
|
// assistant-ui puts user attachments on msg.attachments (not on content);
|
|
363
443
|
// each attachment carries its own content parts from the adapter.
|
|
364
|
-
const attachments =
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
for (const att of msgAttachments ?? []) {
|
|
368
|
-
for (const part of att.content) {
|
|
369
|
-
if (part.type === "image" && typeof part.image === "string") {
|
|
370
|
-
attachments.push({
|
|
371
|
-
type: "image",
|
|
372
|
-
name: att.name,
|
|
373
|
-
contentType: att.contentType,
|
|
374
|
-
data: part.image,
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
else if (part.type === "file" && typeof part.data === "string") {
|
|
378
|
-
const contentType = att.contentType ??
|
|
379
|
-
(typeof part.mimeType === "string" ? part.mimeType : undefined);
|
|
380
|
-
const decodedText = part.data.startsWith("data:")
|
|
381
|
-
? decodeTextDataUrl(part.data)
|
|
382
|
-
: null;
|
|
383
|
-
attachments.push({
|
|
384
|
-
type: "file",
|
|
385
|
-
name: att.name,
|
|
386
|
-
contentType,
|
|
387
|
-
...(decodedText !== null
|
|
388
|
-
? { text: decodedText }
|
|
389
|
-
: part.data.startsWith("data:")
|
|
390
|
-
? { data: part.data }
|
|
391
|
-
: { text: part.data }),
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
else if (part.type === "text" && typeof part.text === "string") {
|
|
395
|
-
attachments.push({
|
|
396
|
-
type: "file",
|
|
397
|
-
name: att.name,
|
|
398
|
-
contentType: att.contentType,
|
|
399
|
-
text: unwrapAttachmentEnvelope(part.text),
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
444
|
+
const attachments = lastUserMsg
|
|
445
|
+
? extractAttachmentsFromMessage(lastUserMsg)
|
|
446
|
+
: [];
|
|
405
447
|
const userMessageText = rawMessageText.trim() || attachments.length === 0
|
|
406
448
|
? rawMessageText
|
|
407
449
|
: "Use the attached context.";
|
|
@@ -410,7 +452,9 @@ export function createAgentChatAdapter(options) {
|
|
|
410
452
|
.filter((m) => m.role === "user" || m.role === "assistant")
|
|
411
453
|
.map((m) => ({
|
|
412
454
|
role: m.role,
|
|
413
|
-
content:
|
|
455
|
+
content: m.role === "user"
|
|
456
|
+
? messageTextForHistory(m)
|
|
457
|
+
: messageTextFromContent(m.content),
|
|
414
458
|
}))
|
|
415
459
|
.filter((m) => m.content.trim());
|
|
416
460
|
const structuredHistory = assistantUiMessagesToStructuredHistory(priorMessages);
|
|
@@ -711,8 +755,12 @@ export function createAgentChatAdapter(options) {
|
|
|
711
755
|
...structuredCombinedHistory,
|
|
712
756
|
];
|
|
713
757
|
currentMessageText = autoContinueMessage(signal);
|
|
714
|
-
|
|
715
|
-
|
|
758
|
+
// Continuation requests are stateless new POSTs. If the interrupted
|
|
759
|
+
// turn depended on uploaded context, re-send that context; otherwise
|
|
760
|
+
// an attachment-only prompt degrades to "Use the attached context."
|
|
761
|
+
// with nothing attached after a stale run or reconnect recovery.
|
|
762
|
+
includeAttachments = attachments.length > 0;
|
|
763
|
+
includeReferences = Boolean(runConfig?.custom?.references);
|
|
716
764
|
startupRecoveryAttempts = 0;
|
|
717
765
|
clearActiveRun();
|
|
718
766
|
if (!isTransient) {
|