@agent-native/core 0.12.24 → 0.12.27

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 (76) hide show
  1. package/dist/agent/production-agent.d.ts +9 -2
  2. package/dist/agent/production-agent.d.ts.map +1 -1
  3. package/dist/agent/production-agent.js +56 -37
  4. package/dist/agent/production-agent.js.map +1 -1
  5. package/dist/agent/thread-data-builder.d.ts +16 -1
  6. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  7. package/dist/agent/thread-data-builder.js +132 -0
  8. package/dist/agent/thread-data-builder.js.map +1 -1
  9. package/dist/client/AgentTaskCard.d.ts.map +1 -1
  10. package/dist/client/AgentTaskCard.js +16 -3
  11. package/dist/client/AgentTaskCard.js.map +1 -1
  12. package/dist/client/AssistantChat.d.ts.map +1 -1
  13. package/dist/client/AssistantChat.js +22 -12
  14. package/dist/client/AssistantChat.js.map +1 -1
  15. package/dist/client/IframeEmbed.d.ts.map +1 -1
  16. package/dist/client/IframeEmbed.js +2 -2
  17. package/dist/client/IframeEmbed.js.map +1 -1
  18. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  19. package/dist/client/agent-chat-adapter.js +77 -12
  20. package/dist/client/agent-chat-adapter.js.map +1 -1
  21. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  22. package/dist/client/composer/ComposerPlusMenu.js +1 -1
  23. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  24. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  25. package/dist/client/composer/PromptComposer.js +8 -7
  26. package/dist/client/composer/PromptComposer.js.map +1 -1
  27. package/dist/client/composer/attachment-accept.d.ts +7 -0
  28. package/dist/client/composer/attachment-accept.d.ts.map +1 -0
  29. package/dist/client/composer/attachment-accept.js +36 -0
  30. package/dist/client/composer/attachment-accept.js.map +1 -0
  31. package/dist/client/progress/RunsTray.d.ts.map +1 -1
  32. package/dist/client/progress/RunsTray.js +3 -1
  33. package/dist/client/progress/RunsTray.js.map +1 -1
  34. package/dist/client/sse-event-processor.d.ts.map +1 -1
  35. package/dist/client/sse-event-processor.js +12 -1
  36. package/dist/client/sse-event-processor.js.map +1 -1
  37. package/dist/db/client.d.ts +3 -0
  38. package/dist/db/client.d.ts.map +1 -1
  39. package/dist/db/client.js +70 -34
  40. package/dist/db/client.js.map +1 -1
  41. package/dist/db/create-get-db.d.ts.map +1 -1
  42. package/dist/db/create-get-db.js +30 -7
  43. package/dist/db/create-get-db.js.map +1 -1
  44. package/dist/deploy/build.js +64 -0
  45. package/dist/deploy/build.js.map +1 -1
  46. package/dist/onboarding/default-steps.d.ts.map +1 -1
  47. package/dist/onboarding/default-steps.js +8 -1
  48. package/dist/onboarding/default-steps.js.map +1 -1
  49. package/dist/scripts/db/exec.d.ts.map +1 -1
  50. package/dist/scripts/db/exec.js +3 -6
  51. package/dist/scripts/db/exec.js.map +1 -1
  52. package/dist/scripts/db/patch.d.ts.map +1 -1
  53. package/dist/scripts/db/patch.js +3 -6
  54. package/dist/scripts/db/patch.js.map +1 -1
  55. package/dist/scripts/db/query.d.ts.map +1 -1
  56. package/dist/scripts/db/query.js +3 -6
  57. package/dist/scripts/db/query.js.map +1 -1
  58. package/dist/scripts/db/schema.d.ts.map +1 -1
  59. package/dist/scripts/db/schema.js +3 -6
  60. package/dist/scripts/db/schema.js.map +1 -1
  61. package/dist/scripts/db/sqlite-client.d.ts +15 -0
  62. package/dist/scripts/db/sqlite-client.d.ts.map +1 -0
  63. package/dist/scripts/db/sqlite-client.js +51 -0
  64. package/dist/scripts/db/sqlite-client.js.map +1 -0
  65. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  66. package/dist/server/agent-chat-plugin.js +53 -2
  67. package/dist/server/agent-chat-plugin.js.map +1 -1
  68. package/dist/server/better-auth-instance.js +4 -3
  69. package/dist/server/better-auth-instance.js.map +1 -1
  70. package/dist/server/credential-provider.d.ts +2 -2
  71. package/dist/server/credential-provider.d.ts.map +1 -1
  72. package/dist/server/credential-provider.js +22 -1
  73. package/dist/server/credential-provider.js.map +1 -1
  74. package/dist/server/google-oauth.js +1 -1
  75. package/dist/server/google-oauth.js.map +1 -1
  76. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"IframeEmbed.d.ts","sourceRoot":"","sources":["../../src/client/IframeEmbed.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA2BD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmBtE;AAiBD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CA2D3E"}
1
+ {"version":3,"file":"IframeEmbed.d.ts","sourceRoot":"","sources":["../../src/client/IframeEmbed.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA2BD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmBtE;AAiBD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAqE3E"}
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useRef, useState } from "react";
3
3
  import { IconAlertTriangle } from "@tabler/icons-react";
4
- import { cn } from "./utils.js";
5
4
  import { AGENT_NAVIGATE_MESSAGE_TYPE } from "./embed.js";
6
5
  const ALLOWED_ASPECTS = new Set(["16/9", "4/3", "1/1", "21/9", "3/2", "2/1"]);
7
6
  function isSameOriginSrc(src) {
@@ -73,6 +72,7 @@ export function IframeEmbed({ src, aspect, title, height }) {
73
72
  const [loaded, setLoaded] = useState(false);
74
73
  const iframeRef = useRef(null);
75
74
  const resolvedAspect = aspect && ALLOWED_ASPECTS.has(aspect) ? aspect : "16/9";
75
+ const displayTitle = title?.trim() || "Embedded content";
76
76
  const paddingBottom = useMemo(() => aspectToPaddingBottom(resolvedAspect), [resolvedAspect]);
77
77
  useEffect(() => {
78
78
  function onMessage(e) {
@@ -103,6 +103,6 @@ export function IframeEmbed({ src, aspect, title, height }) {
103
103
  const style = height
104
104
  ? { height: `${height}px` }
105
105
  : { paddingBottom };
106
- return (_jsxs("div", { className: cn("my-2 rounded-lg border border-border overflow-hidden bg-muted/20 relative w-full"), style: style, children: [!loaded && (_jsx("div", { className: "absolute inset-0 animate-pulse bg-muted/40" })), _jsx("iframe", { ref: iframeRef, src: src, title: title || "Embedded content", sandbox: "allow-scripts allow-same-origin allow-forms allow-popups", referrerPolicy: "same-origin", loading: "lazy", onLoad: () => setLoaded(true), className: "absolute inset-0 w-full h-full border-0 bg-transparent" })] }));
106
+ return (_jsxs("div", { className: "my-2 w-full overflow-hidden rounded-lg border border-border bg-background/60", children: [_jsxs("div", { className: "flex min-h-8 items-center gap-2 border-b border-border bg-muted/30 px-3 py-1.5", children: [_jsx("span", { className: "shrink-0 text-[10px] font-medium uppercase text-muted-foreground", children: "Preview" }), _jsx("span", { "aria-hidden": "true", className: "h-3 w-px shrink-0 bg-border" }), _jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium text-foreground", title: displayTitle, children: displayTitle })] }), _jsxs("div", { className: "relative w-full bg-muted/20", style: style, children: [!loaded && (_jsx("div", { className: "absolute inset-0 animate-pulse bg-muted/40" })), _jsx("iframe", { ref: iframeRef, src: src, title: displayTitle, sandbox: "allow-scripts allow-same-origin allow-forms allow-popups", referrerPolicy: "same-origin", loading: "lazy", onLoad: () => setLoaded(true), className: "absolute inset-0 h-full w-full border-0 bg-transparent" })] })] }));
107
107
  }
108
108
  //# sourceMappingURL=IframeEmbed.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IframeEmbed.js","sourceRoot":"","sources":["../../src/client/IframeEmbed.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { IconAlertTriangle } from \"@tabler/icons-react\";\nimport { cn } from \"./utils.js\";\nimport { AGENT_NAVIGATE_MESSAGE_TYPE } from \"./embed.js\";\n\nexport interface IframeEmbedProps {\n src?: string;\n aspect?: string;\n title?: string;\n height?: number;\n}\n\nconst ALLOWED_ASPECTS = new Set([\"16/9\", \"4/3\", \"1/1\", \"21/9\", \"3/2\", \"2/1\"]);\n\nfunction isSameOriginSrc(src: string): boolean {\n if (typeof window === \"undefined\") return false;\n const trimmed = src.trim();\n if (!trimmed) return false;\n if (trimmed.startsWith(\"javascript:\") || trimmed.startsWith(\"data:\")) {\n return false;\n }\n if (trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\")) return true;\n if (trimmed.startsWith(\"./\") || trimmed.startsWith(\"../\")) return true;\n try {\n const url = new URL(trimmed, window.location.origin);\n return url.origin === window.location.origin;\n } catch {\n return false;\n }\n}\n\nfunction aspectToPaddingBottom(aspect: string): string {\n const [w, h] = aspect.split(\"/\").map((n) => Number(n.trim()));\n if (!w || !h) return \"56.25%\";\n return `${(h / w) * 100}%`;\n}\n\n/**\n * Parses the body of a ```embed fenced block. Accepts simple `key: value`\n * lines, ignoring blanks and unknown keys. No YAML — keeps the surface small.\n */\nexport function parseEmbedBody(body: string): Partial<IframeEmbedProps> {\n const out: Partial<IframeEmbedProps> = {};\n for (const raw of body.split(/\\r?\\n/)) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const idx = line.indexOf(\":\");\n if (idx <= 0) continue;\n const key = line.slice(0, idx).trim().toLowerCase();\n const value = line.slice(idx + 1).trim();\n if (!value) continue;\n if (key === \"src\") out.src = value;\n else if (key === \"aspect\") out.aspect = value;\n else if (key === \"title\") out.title = value;\n else if (key === \"height\") {\n const n = Number(value);\n if (Number.isFinite(n) && n > 0) out.height = n;\n }\n }\n return out;\n}\n\nfunction BlockedEmbed({ reason, src }: { reason: string; src?: string }) {\n return (\n <div className=\"my-2 rounded-lg border border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground flex items-start gap-2\">\n <IconAlertTriangle className=\"h-3.5 w-3.5 shrink-0 mt-0.5\" />\n <div className=\"min-w-0\">\n <div className=\"font-medium text-foreground\">Embed blocked</div>\n <div className=\"mt-0.5\">{reason}</div>\n {src && (\n <div className=\"mt-1 font-mono text-[10px] truncate\">{src}</div>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Inline iframe embed for assistant chat. Rendered from a ```embed fenced\n * code block. Same-origin paths only; sandboxed.\n */\nexport function IframeEmbed({ src, aspect, title, height }: IframeEmbedProps) {\n const [loaded, setLoaded] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const resolvedAspect =\n aspect && ALLOWED_ASPECTS.has(aspect) ? aspect : \"16/9\";\n const paddingBottom = useMemo(\n () => aspectToPaddingBottom(resolvedAspect),\n [resolvedAspect],\n );\n\n useEffect(() => {\n function onMessage(e: MessageEvent) {\n if (e.origin !== window.location.origin) return;\n const iframe = iframeRef.current;\n if (!iframe || e.source !== iframe.contentWindow) return;\n const data = e.data as { type?: unknown; path?: unknown } | null;\n if (!data || data.type !== AGENT_NAVIGATE_MESSAGE_TYPE) return;\n if (typeof data.path !== \"string\" || !data.path.startsWith(\"/\")) return;\n if (data.path.startsWith(\"//\")) return;\n window.history.pushState({}, \"\", data.path);\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n }\n window.addEventListener(\"message\", onMessage);\n return () => window.removeEventListener(\"message\", onMessage);\n }, []);\n\n if (!src) {\n return <BlockedEmbed reason=\"Missing src\" />;\n }\n if (!isSameOriginSrc(src)) {\n return <BlockedEmbed reason=\"Cross-origin URL not allowed\" src={src} />;\n }\n\n const style: React.CSSProperties = height\n ? { height: `${height}px` }\n : { paddingBottom };\n\n return (\n <div\n className={cn(\n \"my-2 rounded-lg border border-border overflow-hidden bg-muted/20 relative w-full\",\n )}\n style={style}\n >\n {!loaded && (\n <div className=\"absolute inset-0 animate-pulse bg-muted/40\" />\n )}\n <iframe\n ref={iframeRef}\n src={src}\n title={title || \"Embedded content\"}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups\"\n referrerPolicy=\"same-origin\"\n loading=\"lazy\"\n onLoad={() => setLoaded(true)}\n className=\"absolute inset-0 w-full h-full border-0 bg-transparent\"\n />\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"IframeEmbed.js","sourceRoot":"","sources":["../../src/client/IframeEmbed.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { IconAlertTriangle } from \"@tabler/icons-react\";\nimport { cn } from \"./utils.js\";\nimport { AGENT_NAVIGATE_MESSAGE_TYPE } from \"./embed.js\";\n\nexport interface IframeEmbedProps {\n src?: string;\n aspect?: string;\n title?: string;\n height?: number;\n}\n\nconst ALLOWED_ASPECTS = new Set([\"16/9\", \"4/3\", \"1/1\", \"21/9\", \"3/2\", \"2/1\"]);\n\nfunction isSameOriginSrc(src: string): boolean {\n if (typeof window === \"undefined\") return false;\n const trimmed = src.trim();\n if (!trimmed) return false;\n if (trimmed.startsWith(\"javascript:\") || trimmed.startsWith(\"data:\")) {\n return false;\n }\n if (trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\")) return true;\n if (trimmed.startsWith(\"./\") || trimmed.startsWith(\"../\")) return true;\n try {\n const url = new URL(trimmed, window.location.origin);\n return url.origin === window.location.origin;\n } catch {\n return false;\n }\n}\n\nfunction aspectToPaddingBottom(aspect: string): string {\n const [w, h] = aspect.split(\"/\").map((n) => Number(n.trim()));\n if (!w || !h) return \"56.25%\";\n return `${(h / w) * 100}%`;\n}\n\n/**\n * Parses the body of a ```embed fenced block. Accepts simple `key: value`\n * lines, ignoring blanks and unknown keys. No YAML — keeps the surface small.\n */\nexport function parseEmbedBody(body: string): Partial<IframeEmbedProps> {\n const out: Partial<IframeEmbedProps> = {};\n for (const raw of body.split(/\\r?\\n/)) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const idx = line.indexOf(\":\");\n if (idx <= 0) continue;\n const key = line.slice(0, idx).trim().toLowerCase();\n const value = line.slice(idx + 1).trim();\n if (!value) continue;\n if (key === \"src\") out.src = value;\n else if (key === \"aspect\") out.aspect = value;\n else if (key === \"title\") out.title = value;\n else if (key === \"height\") {\n const n = Number(value);\n if (Number.isFinite(n) && n > 0) out.height = n;\n }\n }\n return out;\n}\n\nfunction BlockedEmbed({ reason, src }: { reason: string; src?: string }) {\n return (\n <div className=\"my-2 rounded-lg border border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground flex items-start gap-2\">\n <IconAlertTriangle className=\"h-3.5 w-3.5 shrink-0 mt-0.5\" />\n <div className=\"min-w-0\">\n <div className=\"font-medium text-foreground\">Embed blocked</div>\n <div className=\"mt-0.5\">{reason}</div>\n {src && (\n <div className=\"mt-1 font-mono text-[10px] truncate\">{src}</div>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Inline iframe embed for assistant chat. Rendered from a ```embed fenced\n * code block. Same-origin paths only; sandboxed.\n */\nexport function IframeEmbed({ src, aspect, title, height }: IframeEmbedProps) {\n const [loaded, setLoaded] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const resolvedAspect =\n aspect && ALLOWED_ASPECTS.has(aspect) ? aspect : \"16/9\";\n const displayTitle = title?.trim() || \"Embedded content\";\n const paddingBottom = useMemo(\n () => aspectToPaddingBottom(resolvedAspect),\n [resolvedAspect],\n );\n\n useEffect(() => {\n function onMessage(e: MessageEvent) {\n if (e.origin !== window.location.origin) return;\n const iframe = iframeRef.current;\n if (!iframe || e.source !== iframe.contentWindow) return;\n const data = e.data as { type?: unknown; path?: unknown } | null;\n if (!data || data.type !== AGENT_NAVIGATE_MESSAGE_TYPE) return;\n if (typeof data.path !== \"string\" || !data.path.startsWith(\"/\")) return;\n if (data.path.startsWith(\"//\")) return;\n window.history.pushState({}, \"\", data.path);\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n }\n window.addEventListener(\"message\", onMessage);\n return () => window.removeEventListener(\"message\", onMessage);\n }, []);\n\n if (!src) {\n return <BlockedEmbed reason=\"Missing src\" />;\n }\n if (!isSameOriginSrc(src)) {\n return <BlockedEmbed reason=\"Cross-origin URL not allowed\" src={src} />;\n }\n\n const style: React.CSSProperties = height\n ? { height: `${height}px` }\n : { paddingBottom };\n\n return (\n <div className=\"my-2 w-full overflow-hidden rounded-lg border border-border bg-background/60\">\n <div className=\"flex min-h-8 items-center gap-2 border-b border-border bg-muted/30 px-3 py-1.5\">\n <span className=\"shrink-0 text-[10px] font-medium uppercase text-muted-foreground\">\n Preview\n </span>\n <span aria-hidden=\"true\" className=\"h-3 w-px shrink-0 bg-border\" />\n <span\n className=\"min-w-0 flex-1 truncate text-xs font-medium text-foreground\"\n title={displayTitle}\n >\n {displayTitle}\n </span>\n </div>\n <div className=\"relative w-full bg-muted/20\" style={style}>\n {!loaded && (\n <div className=\"absolute inset-0 animate-pulse bg-muted/40\" />\n )}\n <iframe\n ref={iframeRef}\n src={src}\n title={displayTitle}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups\"\n referrerPolicy=\"same-origin\"\n loading=\"lazy\"\n onLoad={() => setLoaded(true)}\n className=\"absolute inset-0 h-full w-full border-0 bg-transparent\"\n />\n </div>\n </div>\n );\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;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"}
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;AA0jBrE;;;;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,CAk2BnB"}
@@ -1,7 +1,7 @@
1
1
  import { setActiveRun, updateActiveRunSeq, clearActiveRun, } from "./active-run-state.js";
2
2
  import { AgentAutoContinueSignal, readSSEStream, } from "./sse-event-processor.js";
3
3
  import { agentNativePath } from "./api-path.js";
4
- import { normalizeChatError } from "./error-format.js";
4
+ import { formatChatErrorText, normalizeChatError } from "./error-format.js";
5
5
  import { captureError } from "./analytics.js";
6
6
  import { unwrapAttachmentEnvelope } from "./composer/pasted-text.js";
7
7
  const TEXT_ATTACHMENT_CONTENT_TYPES = new Set([
@@ -115,10 +115,10 @@ function extractAttachmentsFromMessage(message) {
115
115
  name: att.name,
116
116
  contentType,
117
117
  ...(decodedText !== null
118
- ? { text: decodedText }
118
+ ? { text: truncateOutboundAttachment(decodedText) }
119
119
  : part.data.startsWith("data:")
120
120
  ? { data: part.data }
121
- : { text: part.data }),
121
+ : { text: truncateOutboundAttachment(part.data) }),
122
122
  });
123
123
  }
124
124
  else if (part.type === "text" && typeof part.text === "string") {
@@ -126,7 +126,7 @@ function extractAttachmentsFromMessage(message) {
126
126
  type: "file",
127
127
  name: att.name,
128
128
  contentType: att.contentType,
129
- text: unwrapAttachmentEnvelope(part.text),
129
+ text: truncateOutboundAttachment(unwrapAttachmentEnvelope(part.text)),
130
130
  });
131
131
  }
132
132
  }
@@ -139,6 +139,12 @@ function truncateHistoryAttachment(text) {
139
139
  const omitted = text.length - MAX_HISTORY_ATTACHMENT_CHARS;
140
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
141
  }
142
+ function truncateOutboundAttachment(text) {
143
+ if (text.length <= MAX_HISTORY_ATTACHMENT_CHARS)
144
+ return text;
145
+ const omitted = text.length - MAX_HISTORY_ATTACHMENT_CHARS;
146
+ return `${text.slice(0, MAX_HISTORY_ATTACHMENT_CHARS)}\n\n[Attachment truncated after ${MAX_HISTORY_ATTACHMENT_CHARS.toLocaleString()} characters; ${omitted.toLocaleString()} characters omitted from the submitted attachment.]`;
147
+ }
142
148
  function attachmentHistoryText(attachment) {
143
149
  if (typeof attachment.text === "string" && attachment.text.length > 0) {
144
150
  const attrs = [
@@ -383,6 +389,25 @@ function authErrorReasonFromMessage(message) {
383
389
  ? "session-expired"
384
390
  : "auth-required";
385
391
  }
392
+ function authErrorText(reason, message) {
393
+ const fallback = reason === "session-expired"
394
+ ? "Your chat session expired. Refresh chat and sign in again to continue."
395
+ : "Authentication required. Sign in again to use chat.";
396
+ if (!message)
397
+ return formatChatErrorText(fallback);
398
+ try {
399
+ const parsed = JSON.parse(message);
400
+ const raw = typeof parsed.error === "string"
401
+ ? parsed.error
402
+ : typeof parsed.message === "string"
403
+ ? parsed.message
404
+ : undefined;
405
+ return formatChatErrorText(raw || fallback);
406
+ }
407
+ catch {
408
+ return formatChatErrorText(message || fallback);
409
+ }
410
+ }
386
411
  function safeAgentNativePath(path) {
387
412
  try {
388
413
  return agentNativePath(path);
@@ -402,6 +427,20 @@ function isMissingCredentialMessage(message) {
402
427
  msg.includes("no llm provider") ||
403
428
  msg.includes("llm provider is connected"));
404
429
  }
430
+ function missingCredentialErrorText(message) {
431
+ try {
432
+ const parsed = JSON.parse(message);
433
+ const raw = typeof parsed.error === "string"
434
+ ? parsed.error
435
+ : typeof parsed.message === "string"
436
+ ? parsed.message
437
+ : message;
438
+ return formatChatErrorText(raw, typeof parsed.upgradeUrl === "string" ? parsed.upgradeUrl : undefined, typeof parsed.errorCode === "string" ? parsed.errorCode : undefined);
439
+ }
440
+ catch {
441
+ return formatChatErrorText(message);
442
+ }
443
+ }
405
444
  /**
406
445
  * The composer's exec mode is sent as explicit request metadata. The server
407
446
  * owns the plan-mode prompt and read-only tool filtering so the chat history
@@ -473,6 +512,7 @@ export function createAgentChatAdapter(options) {
473
512
  let currentStructuredHistory = structuredHistory;
474
513
  let includeAttachments = attachments.length > 0;
475
514
  let includeReferences = Boolean(runConfig?.custom?.references);
515
+ let internalContinuationRequest = false;
476
516
  let startupRecoveryAttempts = 0;
477
517
  let staleRunContinuationAttempts = 0;
478
518
  let stalledTransientContinuationAttempts = 0;
@@ -761,6 +801,7 @@ export function createAgentChatAdapter(options) {
761
801
  // with nothing attached after a stale run or reconnect recovery.
762
802
  includeAttachments = attachments.length > 0;
763
803
  includeReferences = Boolean(runConfig?.custom?.references);
804
+ internalContinuationRequest = true;
764
805
  startupRecoveryAttempts = 0;
765
806
  clearActiveRun();
766
807
  if (!isTransient) {
@@ -780,9 +821,13 @@ export function createAgentChatAdapter(options) {
780
821
  headers,
781
822
  body: JSON.stringify({
782
823
  message: currentMessageText,
824
+ displayMessage: userMessageText,
783
825
  history: currentHistory,
784
826
  structuredHistory: currentStructuredHistory,
785
827
  ...(threadId ? { threadId } : {}),
828
+ ...(internalContinuationRequest
829
+ ? { internalContinuation: true }
830
+ : {}),
786
831
  ...(requestMode ? { mode: requestMode } : {}),
787
832
  ...(modelRef?.current ? { model: modelRef.current } : {}),
788
833
  ...(engineRef?.current ? { engine: engineRef.current } : {}),
@@ -848,7 +893,10 @@ export function createAgentChatAdapter(options) {
848
893
  continue;
849
894
  }
850
895
  dispatchAuthError("auth-required");
851
- content.push({ type: "text", text: "" });
896
+ content.push({
897
+ type: "text",
898
+ text: authErrorText("auth-required"),
899
+ });
852
900
  yield {
853
901
  content: [...content],
854
902
  status: {
@@ -865,7 +913,10 @@ export function createAgentChatAdapter(options) {
865
913
  continue;
866
914
  }
867
915
  dispatchAuthError("session-expired");
868
- content.push({ type: "text", text: "" });
916
+ content.push({
917
+ type: "text",
918
+ text: authErrorText("session-expired"),
919
+ });
869
920
  yield {
870
921
  content: [...content],
871
922
  status: {
@@ -882,8 +933,12 @@ export function createAgentChatAdapter(options) {
882
933
  if (await tryRecoverAuthOnce()) {
883
934
  continue;
884
935
  }
885
- dispatchAuthError(authErrorReasonFromMessage(body));
886
- content.push({ type: "text", text: "" });
936
+ const reason = authErrorReasonFromMessage(body);
937
+ dispatchAuthError(reason);
938
+ content.push({
939
+ type: "text",
940
+ text: authErrorText(reason, body),
941
+ });
887
942
  yield {
888
943
  content: [...content],
889
944
  status: {
@@ -897,7 +952,10 @@ export function createAgentChatAdapter(options) {
897
952
  if (typeof window !== "undefined") {
898
953
  window.dispatchEvent(new Event("agent-chat:missing-api-key"));
899
954
  }
900
- content.push({ type: "text", text: "" });
955
+ content.push({
956
+ type: "text",
957
+ text: missingCredentialErrorText(body),
958
+ });
901
959
  yield {
902
960
  content: [...content],
903
961
  status: {
@@ -1010,8 +1068,12 @@ export function createAgentChatAdapter(options) {
1010
1068
  if (await tryRecoverAuthOnce()) {
1011
1069
  continue;
1012
1070
  }
1013
- dispatchAuthError(authErrorReasonFromMessage(errMsg));
1014
- content.push({ type: "text", text: "" });
1071
+ const reason = authErrorReasonFromMessage(errMsg);
1072
+ dispatchAuthError(reason);
1073
+ content.push({
1074
+ type: "text",
1075
+ text: authErrorText(reason, errMsg),
1076
+ });
1015
1077
  yield {
1016
1078
  content: [...content],
1017
1079
  status: {
@@ -1026,7 +1088,10 @@ export function createAgentChatAdapter(options) {
1026
1088
  if (typeof window !== "undefined") {
1027
1089
  window.dispatchEvent(new Event("agent-chat:missing-api-key"));
1028
1090
  }
1029
- content.push({ type: "text", text: "" });
1091
+ content.push({
1092
+ type: "text",
1093
+ text: missingCredentialErrorText(errMsg),
1094
+ });
1030
1095
  yield {
1031
1096
  content: [...content],
1032
1097
  status: {