@agent-native/core 0.7.7 → 0.7.11

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 (338) hide show
  1. package/dist/agent/engine/ai-sdk-engine.d.ts +14 -2
  2. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  3. package/dist/agent/engine/ai-sdk-engine.js +70 -54
  4. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  5. package/dist/agent/engine/anthropic-engine.d.ts +1 -6
  6. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  7. package/dist/agent/engine/anthropic-engine.js +3 -14
  8. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  9. package/dist/agent/engine/builtin.d.ts.map +1 -1
  10. package/dist/agent/engine/builtin.js +3 -0
  11. package/dist/agent/engine/builtin.js.map +1 -1
  12. package/dist/agent/engine/translate-ai-sdk.d.ts +35 -10
  13. package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
  14. package/dist/agent/engine/translate-ai-sdk.js +190 -91
  15. package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
  16. package/dist/agent/engine/types.d.ts +10 -1
  17. package/dist/agent/engine/types.d.ts.map +1 -1
  18. package/dist/agent/production-agent.d.ts +15 -1
  19. package/dist/agent/production-agent.d.ts.map +1 -1
  20. package/dist/agent/production-agent.js +78 -21
  21. package/dist/agent/production-agent.js.map +1 -1
  22. package/dist/agent/thread-data-builder.js +1 -1
  23. package/dist/agent/thread-data-builder.js.map +1 -1
  24. package/dist/agent/types.d.ts +4 -0
  25. package/dist/agent/types.d.ts.map +1 -1
  26. package/dist/application-state/script-helpers.d.ts +12 -5
  27. package/dist/application-state/script-helpers.d.ts.map +1 -1
  28. package/dist/application-state/script-helpers.js +41 -20
  29. package/dist/application-state/script-helpers.js.map +1 -1
  30. package/dist/catalog.json +15 -0
  31. package/dist/chat-threads/store.d.ts.map +1 -1
  32. package/dist/chat-threads/store.js +7 -5
  33. package/dist/chat-threads/store.js.map +1 -1
  34. package/dist/checkpoints/index.d.ts +3 -0
  35. package/dist/checkpoints/index.d.ts.map +1 -0
  36. package/dist/checkpoints/index.js +3 -0
  37. package/dist/checkpoints/index.js.map +1 -0
  38. package/dist/checkpoints/service.d.ts +6 -0
  39. package/dist/checkpoints/service.d.ts.map +1 -0
  40. package/dist/checkpoints/service.js +107 -0
  41. package/dist/checkpoints/service.js.map +1 -0
  42. package/dist/checkpoints/store.d.ts +27 -0
  43. package/dist/checkpoints/store.d.ts.map +1 -0
  44. package/dist/checkpoints/store.js +92 -0
  45. package/dist/checkpoints/store.js.map +1 -0
  46. package/dist/cli/create.d.ts.map +1 -1
  47. package/dist/cli/create.js +85 -1
  48. package/dist/cli/create.js.map +1 -1
  49. package/dist/cli/index.js +46 -3
  50. package/dist/cli/index.js.map +1 -1
  51. package/dist/cli/templates-meta.d.ts.map +1 -1
  52. package/dist/cli/templates-meta.js +33 -0
  53. package/dist/cli/templates-meta.js.map +1 -1
  54. package/dist/client/AgentPanel.d.ts.map +1 -1
  55. package/dist/client/AgentPanel.js +3 -1
  56. package/dist/client/AgentPanel.js.map +1 -1
  57. package/dist/client/AssistantChat.d.ts +15 -0
  58. package/dist/client/AssistantChat.d.ts.map +1 -1
  59. package/dist/client/AssistantChat.js +145 -67
  60. package/dist/client/AssistantChat.js.map +1 -1
  61. package/dist/client/CommandMenu.d.ts.map +1 -1
  62. package/dist/client/CommandMenu.js +9 -5
  63. package/dist/client/CommandMenu.js.map +1 -1
  64. package/dist/client/ConnectBuilderCard.js +1 -1
  65. package/dist/client/ConnectBuilderCard.js.map +1 -1
  66. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  67. package/dist/client/MultiTabAssistantChat.js +78 -4
  68. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  69. package/dist/client/agent-chat-adapter.d.ts +6 -0
  70. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  71. package/dist/client/agent-chat-adapter.js +4 -0
  72. package/dist/client/agent-chat-adapter.js.map +1 -1
  73. package/dist/client/composer/TiptapComposer.d.ts +12 -1
  74. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  75. package/dist/client/composer/TiptapComposer.js +71 -3
  76. package/dist/client/composer/TiptapComposer.js.map +1 -1
  77. package/dist/client/notifications/NotificationsBell.d.ts +23 -0
  78. package/dist/client/notifications/NotificationsBell.d.ts.map +1 -0
  79. package/dist/client/notifications/NotificationsBell.js +165 -0
  80. package/dist/client/notifications/NotificationsBell.js.map +1 -0
  81. package/dist/client/notifications/index.d.ts +2 -0
  82. package/dist/client/notifications/index.d.ts.map +1 -0
  83. package/dist/client/notifications/index.js +2 -0
  84. package/dist/client/notifications/index.js.map +1 -0
  85. package/dist/client/onboarding/OnboardingPanel.js +6 -3
  86. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  87. package/dist/client/progress/RunsTray.d.ts +18 -0
  88. package/dist/client/progress/RunsTray.d.ts.map +1 -0
  89. package/dist/client/progress/RunsTray.js +70 -0
  90. package/dist/client/progress/RunsTray.js.map +1 -0
  91. package/dist/client/progress/index.d.ts +2 -0
  92. package/dist/client/progress/index.d.ts.map +1 -0
  93. package/dist/client/progress/index.js +2 -0
  94. package/dist/client/progress/index.js.map +1 -0
  95. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  96. package/dist/client/resources/ResourcesPanel.js +19 -4
  97. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  98. package/dist/client/settings/AutomationsSection.d.ts +2 -0
  99. package/dist/client/settings/AutomationsSection.d.ts.map +1 -0
  100. package/dist/client/settings/AutomationsSection.js +214 -0
  101. package/dist/client/settings/AutomationsSection.js.map +1 -0
  102. package/dist/client/settings/ComingSoonSection.d.ts.map +1 -1
  103. package/dist/client/settings/ComingSoonSection.js +2 -1
  104. package/dist/client/settings/ComingSoonSection.js.map +1 -1
  105. package/dist/client/settings/LLMSection.d.ts.map +1 -1
  106. package/dist/client/settings/LLMSection.js +137 -10
  107. package/dist/client/settings/LLMSection.js.map +1 -1
  108. package/dist/client/settings/SecretsSection.d.ts.map +1 -1
  109. package/dist/client/settings/SecretsSection.js +122 -3
  110. package/dist/client/settings/SecretsSection.js.map +1 -1
  111. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  112. package/dist/client/settings/SettingsPanel.js +140 -11
  113. package/dist/client/settings/SettingsPanel.js.map +1 -1
  114. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  115. package/dist/client/settings/VoiceTranscriptionSection.js +2 -2
  116. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  117. package/dist/client/use-pausing-interval.d.ts +11 -0
  118. package/dist/client/use-pausing-interval.d.ts.map +1 -0
  119. package/dist/client/use-pausing-interval.js +49 -0
  120. package/dist/client/use-pausing-interval.js.map +1 -0
  121. package/dist/db/client.d.ts +26 -0
  122. package/dist/db/client.d.ts.map +1 -1
  123. package/dist/db/client.js +84 -2
  124. package/dist/db/client.js.map +1 -1
  125. package/dist/db/drizzle-config.d.ts +33 -0
  126. package/dist/db/drizzle-config.d.ts.map +1 -0
  127. package/dist/db/drizzle-config.js +132 -0
  128. package/dist/db/drizzle-config.js.map +1 -0
  129. package/dist/db/migrations.d.ts.map +1 -1
  130. package/dist/db/migrations.js +11 -6
  131. package/dist/db/migrations.js.map +1 -1
  132. package/dist/deploy/build.js +2 -1
  133. package/dist/deploy/build.js.map +1 -1
  134. package/dist/event-bus/bus.d.ts +20 -0
  135. package/dist/event-bus/bus.d.ts.map +1 -0
  136. package/dist/event-bus/bus.js +108 -0
  137. package/dist/event-bus/bus.js.map +1 -0
  138. package/dist/event-bus/index.d.ts +4 -0
  139. package/dist/event-bus/index.d.ts.map +1 -0
  140. package/dist/event-bus/index.js +3 -0
  141. package/dist/event-bus/index.js.map +1 -0
  142. package/dist/event-bus/registry.d.ts +22 -0
  143. package/dist/event-bus/registry.d.ts.map +1 -0
  144. package/dist/event-bus/registry.js +63 -0
  145. package/dist/event-bus/registry.js.map +1 -0
  146. package/dist/event-bus/types.d.ts +27 -0
  147. package/dist/event-bus/types.d.ts.map +1 -0
  148. package/dist/event-bus/types.js +2 -0
  149. package/dist/event-bus/types.js.map +1 -0
  150. package/dist/integrations/config-store.d.ts.map +1 -1
  151. package/dist/integrations/config-store.js +16 -12
  152. package/dist/integrations/config-store.js.map +1 -1
  153. package/dist/integrations/google-docs-poller.d.ts.map +1 -1
  154. package/dist/integrations/google-docs-poller.js +5 -1
  155. package/dist/integrations/google-docs-poller.js.map +1 -1
  156. package/dist/jobs/scheduler.d.ts.map +1 -1
  157. package/dist/jobs/scheduler.js +7 -3
  158. package/dist/jobs/scheduler.js.map +1 -1
  159. package/dist/notifications/actions.d.ts +10 -0
  160. package/dist/notifications/actions.d.ts.map +1 -0
  161. package/dist/notifications/actions.js +114 -0
  162. package/dist/notifications/actions.js.map +1 -0
  163. package/dist/notifications/channels.d.ts +15 -0
  164. package/dist/notifications/channels.d.ts.map +1 -0
  165. package/dist/notifications/channels.js +97 -0
  166. package/dist/notifications/channels.js.map +1 -0
  167. package/dist/notifications/index.d.ts +4 -0
  168. package/dist/notifications/index.d.ts.map +1 -0
  169. package/dist/notifications/index.js +3 -0
  170. package/dist/notifications/index.js.map +1 -0
  171. package/dist/notifications/registry.d.ts +9 -0
  172. package/dist/notifications/registry.d.ts.map +1 -0
  173. package/dist/notifications/registry.js +146 -0
  174. package/dist/notifications/registry.js.map +1 -0
  175. package/dist/notifications/routes.d.ts +34 -0
  176. package/dist/notifications/routes.d.ts.map +1 -0
  177. package/dist/notifications/routes.js +69 -0
  178. package/dist/notifications/routes.js.map +1 -0
  179. package/dist/notifications/store.d.ts +25 -0
  180. package/dist/notifications/store.d.ts.map +1 -0
  181. package/dist/notifications/store.js +158 -0
  182. package/dist/notifications/store.js.map +1 -0
  183. package/dist/notifications/types.d.ts +43 -0
  184. package/dist/notifications/types.d.ts.map +1 -0
  185. package/dist/notifications/types.js +2 -0
  186. package/dist/notifications/types.js.map +1 -0
  187. package/dist/org/handlers.d.ts.map +1 -1
  188. package/dist/org/handlers.js +7 -26
  189. package/dist/org/handlers.js.map +1 -1
  190. package/dist/progress/actions.d.ts +8 -0
  191. package/dist/progress/actions.d.ts.map +1 -0
  192. package/dist/progress/actions.js +158 -0
  193. package/dist/progress/actions.js.map +1 -0
  194. package/dist/progress/index.d.ts +3 -0
  195. package/dist/progress/index.d.ts.map +1 -0
  196. package/dist/progress/index.js +2 -0
  197. package/dist/progress/index.js.map +1 -0
  198. package/dist/progress/registry.d.ts +22 -0
  199. package/dist/progress/registry.d.ts.map +1 -0
  200. package/dist/progress/registry.js +98 -0
  201. package/dist/progress/registry.js.map +1 -0
  202. package/dist/progress/routes.d.ts +21 -0
  203. package/dist/progress/routes.d.ts.map +1 -0
  204. package/dist/progress/routes.js +59 -0
  205. package/dist/progress/routes.js.map +1 -0
  206. package/dist/progress/store.d.ts +7 -0
  207. package/dist/progress/store.d.ts.map +1 -0
  208. package/dist/progress/store.js +195 -0
  209. package/dist/progress/store.js.map +1 -0
  210. package/dist/progress/types.d.ts +49 -0
  211. package/dist/progress/types.d.ts.map +1 -0
  212. package/dist/progress/types.js +7 -0
  213. package/dist/progress/types.js.map +1 -0
  214. package/dist/resources/store.d.ts.map +1 -1
  215. package/dist/resources/store.js +19 -15
  216. package/dist/resources/store.js.map +1 -1
  217. package/dist/secrets/index.d.ts +3 -2
  218. package/dist/secrets/index.d.ts.map +1 -1
  219. package/dist/secrets/index.js +3 -2
  220. package/dist/secrets/index.js.map +1 -1
  221. package/dist/secrets/routes.d.ts +41 -2
  222. package/dist/secrets/routes.d.ts.map +1 -1
  223. package/dist/secrets/routes.js +167 -1
  224. package/dist/secrets/routes.js.map +1 -1
  225. package/dist/secrets/schema.d.ts +39 -1
  226. package/dist/secrets/schema.d.ts.map +1 -1
  227. package/dist/secrets/schema.js +6 -0
  228. package/dist/secrets/schema.js.map +1 -1
  229. package/dist/secrets/storage.d.ts +26 -0
  230. package/dist/secrets/storage.d.ts.map +1 -1
  231. package/dist/secrets/storage.js +111 -5
  232. package/dist/secrets/storage.js.map +1 -1
  233. package/dist/secrets/substitution.d.ts +39 -0
  234. package/dist/secrets/substitution.d.ts.map +1 -0
  235. package/dist/secrets/substitution.js +93 -0
  236. package/dist/secrets/substitution.js.map +1 -0
  237. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  238. package/dist/server/agent-chat-plugin.js +1657 -1410
  239. package/dist/server/agent-chat-plugin.js.map +1 -1
  240. package/dist/server/auth.d.ts +11 -0
  241. package/dist/server/auth.d.ts.map +1 -1
  242. package/dist/server/auth.js +74 -21
  243. package/dist/server/auth.js.map +1 -1
  244. package/dist/server/better-auth-instance.d.ts.map +1 -1
  245. package/dist/server/better-auth-instance.js +34 -16
  246. package/dist/server/better-auth-instance.js.map +1 -1
  247. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  248. package/dist/server/core-routes-plugin.js +115 -1
  249. package/dist/server/core-routes-plugin.js.map +1 -1
  250. package/dist/server/email-templates.d.ts +43 -0
  251. package/dist/server/email-templates.d.ts.map +1 -0
  252. package/dist/server/email-templates.js +86 -0
  253. package/dist/server/email-templates.js.map +1 -0
  254. package/dist/server/framework-request-handler.d.ts +15 -0
  255. package/dist/server/framework-request-handler.d.ts.map +1 -1
  256. package/dist/server/framework-request-handler.js +64 -1
  257. package/dist/server/framework-request-handler.js.map +1 -1
  258. package/dist/server/onboarding-html.d.ts +11 -0
  259. package/dist/server/onboarding-html.d.ts.map +1 -1
  260. package/dist/server/onboarding-html.js +275 -16
  261. package/dist/server/onboarding-html.js.map +1 -1
  262. package/dist/server/schema-prompt.d.ts.map +1 -1
  263. package/dist/server/schema-prompt.js +5 -0
  264. package/dist/server/schema-prompt.js.map +1 -1
  265. package/dist/shared/index.d.ts +1 -0
  266. package/dist/shared/index.d.ts.map +1 -1
  267. package/dist/shared/index.js +1 -0
  268. package/dist/shared/index.js.map +1 -1
  269. package/dist/shared/truncate.d.ts +8 -0
  270. package/dist/shared/truncate.d.ts.map +1 -0
  271. package/dist/shared/truncate.js +12 -0
  272. package/dist/shared/truncate.js.map +1 -0
  273. package/dist/templates/default/.agents/skills/agent-engines/SKILL.md +60 -4
  274. package/dist/templates/default/.agents/skills/notifications/SKILL.md +95 -0
  275. package/dist/templates/default/.agents/skills/progress/SKILL.md +97 -0
  276. package/dist/templates/default/AGENTS.md +12 -10
  277. package/dist/templates/default/package.json +10 -10
  278. package/dist/templates/workspace-core/package.json +5 -5
  279. package/dist/templates/workspace-root/package.json +1 -1
  280. package/dist/templates/workspace-root/tsconfig.base.json +1 -2
  281. package/dist/tools/fetch-tool.d.ts +22 -0
  282. package/dist/tools/fetch-tool.d.ts.map +1 -0
  283. package/dist/tools/fetch-tool.js +156 -0
  284. package/dist/tools/fetch-tool.js.map +1 -0
  285. package/dist/tracking/index.d.ts +4 -0
  286. package/dist/tracking/index.d.ts.map +1 -0
  287. package/dist/tracking/index.js +3 -0
  288. package/dist/tracking/index.js.map +1 -0
  289. package/dist/tracking/providers.d.ts +15 -0
  290. package/dist/tracking/providers.d.ts.map +1 -0
  291. package/dist/tracking/providers.js +195 -0
  292. package/dist/tracking/providers.js.map +1 -0
  293. package/dist/tracking/registry.d.ts +10 -0
  294. package/dist/tracking/registry.d.ts.map +1 -0
  295. package/dist/tracking/registry.js +75 -0
  296. package/dist/tracking/registry.js.map +1 -0
  297. package/dist/tracking/types.d.ts +13 -0
  298. package/dist/tracking/types.d.ts.map +1 -0
  299. package/dist/tracking/types.js +2 -0
  300. package/dist/tracking/types.js.map +1 -0
  301. package/dist/triggers/actions.d.ts +10 -0
  302. package/dist/triggers/actions.d.ts.map +1 -0
  303. package/dist/triggers/actions.js +277 -0
  304. package/dist/triggers/actions.js.map +1 -0
  305. package/dist/triggers/condition-evaluator.d.ts +15 -0
  306. package/dist/triggers/condition-evaluator.d.ts.map +1 -0
  307. package/dist/triggers/condition-evaluator.js +107 -0
  308. package/dist/triggers/condition-evaluator.js.map +1 -0
  309. package/dist/triggers/dispatcher.d.ts +32 -0
  310. package/dist/triggers/dispatcher.d.ts.map +1 -0
  311. package/dist/triggers/dispatcher.js +291 -0
  312. package/dist/triggers/dispatcher.js.map +1 -0
  313. package/dist/triggers/index.d.ts +5 -0
  314. package/dist/triggers/index.d.ts.map +1 -0
  315. package/dist/triggers/index.js +4 -0
  316. package/dist/triggers/index.js.map +1 -0
  317. package/dist/triggers/types.d.ts +35 -0
  318. package/dist/triggers/types.d.ts.map +1 -0
  319. package/dist/triggers/types.js +9 -0
  320. package/dist/triggers/types.js.map +1 -0
  321. package/dist/vite/client.d.ts.map +1 -1
  322. package/dist/vite/client.js +66 -16
  323. package/dist/vite/client.js.map +1 -1
  324. package/docs/content/automations.md +239 -0
  325. package/docs/content/multi-tenancy.md +88 -0
  326. package/docs/content/notifications.md +199 -0
  327. package/docs/content/progress.md +176 -0
  328. package/docs/content/tracking.md +168 -0
  329. package/package.json +54 -35
  330. package/src/templates/default/.agents/skills/agent-engines/SKILL.md +60 -4
  331. package/src/templates/default/.agents/skills/notifications/SKILL.md +95 -0
  332. package/src/templates/default/.agents/skills/progress/SKILL.md +97 -0
  333. package/src/templates/default/AGENTS.md +12 -10
  334. package/src/templates/default/package.json +10 -10
  335. package/src/templates/workspace-core/package.json +5 -5
  336. package/src/templates/workspace-root/package.json +1 -1
  337. package/src/templates/workspace-root/tsconfig.base.json +1 -2
  338. package/tsconfig.base.json +1 -1
@@ -11,8 +11,9 @@ import { cn } from "./utils.js";
11
11
  import { AgentTaskCard } from "./AgentTaskCard.js";
12
12
  import { ConnectBuilderCard } from "./ConnectBuilderCard.js";
13
13
  import { IframeEmbed, parseEmbedBody } from "./IframeEmbed.js";
14
+ import { useDevMode } from "./use-dev-mode.js";
14
15
  import { TiptapComposer, } from "./composer/TiptapComposer.js";
15
- import { IconMessage, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, IconLock, } from "@tabler/icons-react";
16
+ import { IconMessage, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, IconLock, IconArrowBackUp, IconExternalLink, } from "@tabler/icons-react";
16
17
  // ─── Markdown Text ──────────────────────────────────────────────────────────
17
18
  const markdownStyles = `
18
19
  .agent-markdown > :first-child { margin-top: 0; }
@@ -449,14 +450,17 @@ function UserMessage() {
449
450
  Text: UserMessageText,
450
451
  } }) }), !expanded && isExpandable && (_jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-lg bg-gradient-to-t from-accent via-accent/90 to-transparent" }))] }), isExpandable && (_jsxs("button", { type: "button", onClick: () => setExpanded((prev) => !prev), className: "mt-1 inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { className: cn("h-3.5 w-3.5 transition-transform", expanded && "rotate-180") }), expanded ? "Collapse" : "Expand"] }))] }) }));
451
452
  }
453
+ const CheckpointContext = React.createContext(null);
452
454
  function AssistantMessage() {
453
455
  const [copied, setCopied] = useState(false);
456
+ const [restoreState, setRestoreState] = useState("idle");
454
457
  const messageRuntime = useMessageRuntime();
455
458
  const thread = useThread();
456
459
  const msg = messageRuntime.getState();
457
460
  const isLast = thread.messages.length > 0 &&
458
461
  thread.messages[thread.messages.length - 1].id === msg.id;
459
462
  const isComplete = !isLast || !thread.isRunning;
463
+ const cpCtx = React.useContext(CheckpointContext);
460
464
  const handleCopy = useCallback(() => {
461
465
  const m = messageRuntime.getState();
462
466
  const text = m.content
@@ -467,12 +471,56 @@ function AssistantMessage() {
467
471
  setCopied(true);
468
472
  setTimeout(() => setCopied(false), 2000);
469
473
  }, [messageRuntime]);
474
+ const handleRestore = useCallback(async () => {
475
+ if (restoreState === "idle") {
476
+ setRestoreState("confirming");
477
+ return;
478
+ }
479
+ if (restoreState !== "confirming" || !cpCtx)
480
+ return;
481
+ setRestoreState("restoring");
482
+ try {
483
+ const m = messageRuntime.getState();
484
+ const runId = m.metadata?.runId;
485
+ if (!runId) {
486
+ setRestoreState("idle");
487
+ return;
488
+ }
489
+ // Look up checkpoint by runId
490
+ const tid = cpCtx.threadId || "";
491
+ const res = await fetch(`${cpCtx.apiUrl}/checkpoints?threadId=${encodeURIComponent(tid)}`);
492
+ const checkpoints = res.ok ? await res.json() : [];
493
+ const checkpoint = checkpoints.find((cp) => cp.runId === runId);
494
+ if (!checkpoint) {
495
+ setRestoreState("idle");
496
+ return;
497
+ }
498
+ const restoreRes = await fetch(`${cpCtx.apiUrl}/checkpoints/restore`, {
499
+ method: "POST",
500
+ headers: { "Content-Type": "application/json" },
501
+ body: JSON.stringify({ checkpointId: checkpoint.id }),
502
+ });
503
+ if (restoreRes.ok) {
504
+ window.location.reload();
505
+ }
506
+ else {
507
+ setRestoreState("idle");
508
+ }
509
+ }
510
+ catch {
511
+ setRestoreState("idle");
512
+ }
513
+ }, [restoreState, cpCtx, messageRuntime]);
514
+ const cancelRestore = useCallback(() => {
515
+ setRestoreState("idle");
516
+ }, []);
517
+ const showRestore = cpCtx?.devMode && isComplete && !isLast;
470
518
  return (_jsxs("div", { className: "group relative", style: { contentVisibility: isComplete ? "auto" : "visible" }, children: [_jsx("div", { className: "max-w-[95%] text-sm leading-relaxed text-foreground", children: _jsx(MessagePrimitive.Parts, { components: {
471
519
  Text: MarkdownText,
472
520
  tools: {
473
521
  Fallback: ToolCallFallback,
474
522
  },
475
- } }) }), isComplete && (_jsx("div", { className: "mt-1 flex items-center gap-0.5 opacity-0 group-hover:opacity-100", children: _jsx("button", { onClick: handleCopy, className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: copied ? (_jsx(IconCheck, { className: "h-3 w-3" })) : (_jsx(IconCopy, { className: "h-3 w-3" })) }) }))] }));
523
+ } }) }), isComplete && (_jsxs("div", { className: "mt-1 flex items-center gap-0.5 opacity-0 group-hover:opacity-100", children: [_jsx("button", { onClick: handleCopy, className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: copied ? (_jsx(IconCheck, { className: "h-3 w-3" })) : (_jsx(IconCopy, { className: "h-3 w-3" })) }), showRestore && restoreState === "idle" && (_jsx("button", { onClick: handleRestore, title: "Restore project files to this point", className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(IconArrowBackUp, { className: "h-3 w-3" }) })), showRestore && restoreState === "confirming" && (_jsxs("div", { className: "flex items-center gap-1 text-xs", children: [_jsx("button", { onClick: handleRestore, className: "rounded-md bg-destructive px-1.5 py-0.5 text-destructive-foreground hover:bg-destructive/90", children: "Restore to here?" }), _jsx("button", { onClick: cancelRestore, className: "rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: "Cancel" })] })), showRestore && restoreState === "restoring" && (_jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), "Restoring..."] }))] }))] }));
476
524
  }
477
525
  // ─── Thinking Indicator ─────────────────────────────────────────────────────
478
526
  function ThinkingIndicator({ label = "Thinking" } = {}) {
@@ -500,7 +548,7 @@ function ApiKeySetupCard({ apiUrl }) {
500
548
  const res = await fetch(`${apiUrl}/save-key`, {
501
549
  method: "POST",
502
550
  headers: { "Content-Type": "application/json" },
503
- body: JSON.stringify({ key: apiKey.trim() }),
551
+ body: JSON.stringify({ key: apiKey.trim(), provider: "anthropic" }),
504
552
  });
505
553
  if (!res.ok) {
506
554
  const data = await res.json().catch(() => ({}));
@@ -519,13 +567,13 @@ function ApiKeySetupCard({ apiUrl }) {
519
567
  if (saved) {
520
568
  return (_jsx("div", { className: "mx-4 my-6 rounded-lg border border-emerald-500/30 bg-emerald-500/5 p-4", children: _jsxs("div", { className: "flex items-center gap-2 text-sm text-emerald-400", children: [_jsx(IconCheck, { className: "h-4 w-4" }), "API key saved. Reloading..."] }) }));
521
569
  }
522
- return (_jsxs("div", { className: "mx-4 my-6 rounded-lg border border-border bg-card p-5", children: [_jsxs("div", { className: "flex items-center gap-3 mb-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted", children: _jsx(IconMessage, { className: "h-4.5 w-4.5 text-muted-foreground" }) }), _jsxs("div", { children: [_jsx("h3", { className: "text-sm font-medium text-foreground", children: "Connect your AI" }), _jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Connect Builder or add an Anthropic API key to enable the agent" })] })] }), _jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "rounded-md border border-border px-3 py-2.5", children: _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Connect Builder" }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: "Use Builder's managed Anthropic proxy \u2014 no API key needed" })] }), _jsx("span", { className: "shrink-0 rounded border border-border px-2 py-0.5 text-[10px] font-medium text-muted-foreground", children: "Coming soon" })] }) }), _jsxs("div", { className: "relative flex items-center", children: [_jsx("div", { className: "flex-grow border-t border-border" }), _jsx("span", { className: "mx-2 text-[10px] uppercase tracking-wider text-muted-foreground/60", children: "or" }), _jsx("div", { className: "flex-grow border-t border-border" })] }), _jsxs("div", { className: "rounded-md bg-muted/50 px-3 py-2.5 text-xs text-muted-foreground leading-relaxed", children: [_jsxs("p", { children: ["1. Go to", " ", _jsx("a", { href: "https://console.anthropic.com/settings/keys", target: "_blank", rel: "noopener noreferrer", className: "underline text-foreground/80 hover:text-foreground", children: "console.anthropic.com/settings/keys" })] }), _jsx("p", { className: "mt-1", children: "2. Create a new API key and paste it below" })] }), _jsx("input", { type: "password", value: apiKey, onChange: (e) => {
570
+ return (_jsxs("div", { className: "mx-4 my-6 rounded-lg border border-border bg-card p-5", children: [_jsxs("div", { className: "flex items-center gap-3 mb-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted", children: _jsx(IconMessage, { className: "h-4.5 w-4.5 text-muted-foreground" }) }), _jsx("h3", { className: "text-sm font-medium text-foreground", children: "Connect your AI" })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center gap-3 rounded-md border border-border px-3 py-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Connect Builder.io" }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5 max-w-[200px]", children: "Managed LLM, hosting, and more \u2014 no API key needed" })] }), _jsxs("a", { href: "https://forms.agent-native.com/f/builder-waitlist/36GWqf", target: "_blank", rel: "noopener noreferrer", className: "ml-auto inline-flex items-center gap-1 shrink-0 rounded-md bg-muted/60 px-3 py-1.5 text-[11px] font-medium no-underline text-foreground hover:bg-muted", children: ["Join waitlist", _jsx(IconExternalLink, { size: 10 })] })] }), _jsxs("div", { className: "relative flex items-center", children: [_jsx("div", { className: "flex-grow border-t border-border" }), _jsx("span", { className: "mx-2 text-[10px] uppercase tracking-wider text-muted-foreground/60", children: "or" }), _jsx("div", { className: "flex-grow border-t border-border" })] }), _jsx("input", { type: "password", value: apiKey, onChange: (e) => {
523
571
  setApiKey(e.target.value);
524
572
  setError(null);
525
573
  }, onKeyDown: (e) => {
526
574
  if (e.key === "Enter")
527
575
  handleSave();
528
- }, placeholder: "sk-ant-...", className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground/50 outline-none focus:ring-1 focus:ring-ring", autoComplete: "off" }), error && _jsx("p", { className: "text-xs text-destructive", children: error }), _jsx("button", { onClick: handleSave, disabled: saving || !apiKey.trim(), className: "w-full rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 disabled:opacity-40 disabled:cursor-not-allowed", children: saving ? "Saving..." : "Save API key" })] })] }));
576
+ }, placeholder: "sk-ant-...", className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground/50 outline-none focus:ring-1 focus:ring-ring", autoComplete: "off" }), error && _jsx("p", { className: "text-xs text-destructive", children: error }), apiKey.trim() && (_jsx("button", { onClick: handleSave, disabled: saving, className: "w-full rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 disabled:opacity-40 disabled:cursor-not-allowed", children: saving ? "Saving..." : "Save API key" })), _jsx("p", { className: "text-[10px] text-muted-foreground/60 text-center", children: _jsx("a", { href: "https://console.anthropic.com/settings/keys", target: "_blank", rel: "noopener noreferrer", className: "underline hover:text-foreground/80", children: "Get an Anthropic key" }) })] })] }));
529
577
  }
530
578
  // ─── Builder.io CTA Card (usage limit / code changes / CLI) ─────────────────
531
579
  export function BuilderCtaCard({ reason, usageCents, limitCents, apiUrl = "/_agent-native/agent-chat", }) {
@@ -546,7 +594,7 @@ export function BuilderCtaCard({ reason, usageCents, limitCents, apiUrl = "/_age
546
594
  const res = await fetch(`${apiUrl}/save-key`, {
547
595
  method: "POST",
548
596
  headers: { "Content-Type": "application/json" },
549
- body: JSON.stringify({ key: apiKey.trim() }),
597
+ body: JSON.stringify({ key: apiKey.trim(), provider: "anthropic" }),
550
598
  });
551
599
  if (!res.ok) {
552
600
  const data = await res.json().catch(() => ({}));
@@ -581,7 +629,7 @@ export function BuilderCtaCard({ reason, usageCents, limitCents, apiUrl = "/_age
581
629
  }, onKeyDown: (e) => {
582
630
  if (e.key === "Enter")
583
631
  handleSave();
584
- }, placeholder: "sk-ant-...", className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground/50 outline-none focus:ring-1 focus:ring-ring", autoComplete: "off" }), error && _jsx("p", { className: "text-xs text-destructive", children: error }), _jsx("button", { onClick: handleSave, disabled: saving || !apiKey.trim(), className: "w-full rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 disabled:opacity-40 disabled:cursor-not-allowed", children: saving ? "Saving..." : "Save API key" }), _jsxs("div", { className: "relative", children: [_jsx("div", { className: "absolute inset-0 flex items-center", children: _jsx("span", { className: "w-full border-t border-border" }) }), _jsx("div", { className: "relative flex justify-center text-xs", children: _jsx("span", { className: "bg-card px-2 text-muted-foreground", children: "or" }) })] }), _jsxs("div", { className: "rounded-md bg-muted/50 px-3 py-2.5", children: [_jsx("p", { className: "text-xs text-muted-foreground mb-1.5", children: "Clone and run locally:" }), _jsx("code", { className: "block text-xs text-foreground/80 font-mono break-all select-all", children: cloneCommand })] }), _jsx("div", { className: "rounded-md border border-border px-3 py-2.5", children: _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Connect Builder.io" }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: "Builder's managed Anthropic proxy \u2014 no API key needed" })] }), _jsx("span", { className: "shrink-0 rounded border border-border px-2 py-0.5 text-[10px] font-medium text-muted-foreground", children: "Coming soon" })] }) })] })] }));
632
+ }, placeholder: "sk-ant-...", className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground/50 outline-none focus:ring-1 focus:ring-ring", autoComplete: "off" }), error && _jsx("p", { className: "text-xs text-destructive", children: error }), _jsx("button", { onClick: handleSave, disabled: saving || !apiKey.trim(), className: "w-full rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 disabled:opacity-40 disabled:cursor-not-allowed", children: saving ? "Saving..." : "Save API key" }), _jsxs("div", { className: "relative", children: [_jsx("div", { className: "absolute inset-0 flex items-center", children: _jsx("span", { className: "w-full border-t border-border" }) }), _jsx("div", { className: "relative flex justify-center text-xs", children: _jsx("span", { className: "bg-card px-2 text-muted-foreground", children: "or" }) })] }), _jsxs("div", { className: "rounded-md bg-muted/50 px-3 py-2.5", children: [_jsx("p", { className: "text-xs text-muted-foreground mb-1.5", children: "Clone and run locally:" }), _jsx("code", { className: "block text-xs text-foreground/80 font-mono break-all select-all", children: cloneCommand })] }), _jsxs("div", { className: "rounded-md border border-border px-3 py-2.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Builder.io" }), _jsxs("a", { href: "https://forms.agent-native.com/f/builder-waitlist/36GWqf", target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1 shrink-0 rounded border border-border px-2 py-0.5 text-[10px] font-medium no-underline text-muted-foreground hover:text-foreground hover:bg-accent/40", children: ["Join waitlist", _jsx(IconExternalLink, { size: 10 })] })] }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: "Managed hosting, LLM, and more" })] })] })] }));
585
633
  }
586
634
  export const CHAT_STORAGE_PREFIX = "agent-chat:";
587
635
  /** Remove persisted chat for a given tabId (or "default"). */
@@ -611,7 +659,7 @@ function ensureMessageMetadata(repo) {
611
659
  // Re-export for backwards compatibility
612
660
  import { extractThreadMeta } from "../agent/thread-data-builder.js";
613
661
  export { extractThreadMeta };
614
- const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, showHeader = true, onSwitchToCli, className, apiUrl, tabId, threadId, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, isNewThread, onSlashCommand, execMode, onExecModeChange, }, ref) {
662
+ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, showHeader = true, onSwitchToCli, className, apiUrl, tabId, threadId, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, isNewThread, onSlashCommand, execMode, onExecModeChange, selectedModel, defaultModel, selectedEngine, availableModels, onModelChange, }, ref) {
615
663
  const scrollRef = useRef(null);
616
664
  const thread = useThread();
617
665
  const threadRuntime = useThreadRuntime();
@@ -1009,6 +1057,30 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1009
1057
  window.addEventListener("agent-chat:missing-api-key", handler);
1010
1058
  return () => window.removeEventListener("agent-chat:missing-api-key", handler);
1011
1059
  }, []);
1060
+ // Proactively check if any LLM API key is configured on mount.
1061
+ // Without this, users see suggestions and only discover the key is missing
1062
+ // after their first message fails.
1063
+ useEffect(() => {
1064
+ if (missingApiKey)
1065
+ return;
1066
+ Promise.all([
1067
+ fetch("/_agent-native/env-status")
1068
+ .then((r) => (r.ok ? r.json() : []))
1069
+ .catch(() => []),
1070
+ fetch("/_agent-native/builder/status")
1071
+ .then((r) => (r.ok ? r.json() : null))
1072
+ .catch(() => null),
1073
+ ]).then(([envKeys, builderStatus]) => {
1074
+ const keys = envKeys;
1075
+ const llmKeys = keys.filter((k) => k.key === "ANTHROPIC_API_KEY" ||
1076
+ k.key === "OPENAI_API_KEY" ||
1077
+ k.key === "GOOGLE_GENERATIVE_AI_API_KEY");
1078
+ const anyConfigured = llmKeys.some((k) => k.configured) || builderStatus?.configured === true;
1079
+ if (!anyConfigured && llmKeys.length > 0) {
1080
+ setMissingApiKey(true);
1081
+ }
1082
+ });
1083
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
1012
1084
  // Listen for auth error events from the adapter
1013
1085
  useEffect(() => {
1014
1086
  const handler = (e) => {
@@ -1191,68 +1263,74 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1191
1263
  }, 100);
1192
1264
  return () => clearInterval(interval);
1193
1265
  }, [isRunning]);
1194
- return (_jsx(ChatRunningContext.Provider, { value: isRunning, children: _jsxs("div", { className: cn("flex flex-1 flex-col h-full min-h-0 text-foreground", className), children: [showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsxs("button", { onClick: onSwitchToCli, className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", title: "Switch to CLI", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] })) })] })), _jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-destructive/10", children: _jsx(IconLock, { className: "h-5 w-5 text-destructive" }) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authError.sessionExpired
1195
- ? "Session expired"
1196
- : "Authentication required" }), _jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: authError.sessionExpired ? ("Your session may have expired. Log out and log back in to reconnect.") : (_jsxs(_Fragment, { children: ["You need to log in to use the agent. If you're running locally, add", " ", _jsx("code", { className: "bg-muted px-1 py-0.5 rounded text-[10px]", children: "AUTH_MODE=local" }), " ", "to your", " ", _jsx("code", { className: "bg-muted px-1 py-0.5 rounded text-[10px]", children: ".env" }), " ", "file and restart the dev server."] })) })] }), _jsxs("div", { className: "flex gap-2", children: [authError.sessionExpired && (_jsx("button", { onClick: async () => {
1197
- try {
1198
- await fetch("/_agent-native/auth/logout", {
1199
- method: "POST",
1200
- });
1201
- }
1202
- catch { }
1203
- window.location.reload();
1204
- }, className: "text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10", children: "Log out" })), _jsx("button", { onClick: () => {
1205
- setAuthError(null);
1206
- window.location.reload();
1207
- }, className: "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: "Retry" })] })] })) : missingApiKey ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(ApiKeySetupCard, { apiUrl: apiUrl }) })) : usageLimitReached ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(BuilderCtaCard, { reason: "usage_limit", usageCents: usageLimitReached.usageCents, limitCents: usageLimitReached.limitCents, apiUrl: apiUrl }) })) : isRestoring ? (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "h-8 w-32 rounded-lg bg-muted animate-pulse" }) }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "h-4 w-48 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-64 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-40 rounded bg-muted animate-pulse" })] })] })) : messages.length === 0 && !isReconnecting ? (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-16 px-4 h-full", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-muted", children: _jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground" }) }), _jsx("p", { className: "text-sm text-muted-foreground text-center max-w-[240px]", children: emptyStateText ?? "How can I help you?" }), suggestions && suggestions.length > 0 && (_jsx("div", { className: "flex flex-col gap-1.5 w-full max-w-[280px]", children: suggestions.map((suggestion) => (_jsx("button", { onClick: () => {
1208
- threadRuntime.append({
1209
- role: "user",
1210
- content: [{ type: "text", text: suggestion }],
1211
- });
1212
- }, className: "w-full rounded-lg border border-border px-3 py-2 text-left text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground", children: suggestion }, suggestion))) }))] })) : (_jsxs("div", { className: "agent-thread-content flex flex-col gap-4 px-4 py-4", children: [_jsx(ThreadPrimitive.Messages, { components: {
1213
- UserMessage,
1214
- AssistantMessage,
1215
- } }), showContinue && !showRunningInUI && (_jsx("div", { className: "flex justify-center py-2", children: _jsx("button", { type: "button", onClick: () => {
1216
- setShowContinue(false);
1217
- addToQueue("Continue from where you left off.");
1218
- }, className: "rounded-lg border border-border bg-background px-4 py-2 text-sm font-medium text-foreground hover:bg-accent", children: "Continue" }) })), (isReconnecting || reconnectFrozen) &&
1219
- reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), showRunningInUI && (_jsx(ThinkingIndicator, { label: isReconnecting ? "Reconnecting" : "Thinking" })), queuedMessages.map((msg) => {
1220
- const displayText = msg.text
1221
- .replace(/<context>[\s\S]*?<\/context>\n?/g, "")
1222
- .trim();
1223
- 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));
1224
- })] })) }), 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("div", { className: "agent-composer-area shrink-0 px-3 py-2", 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, placeholder: isRunning
1225
- ? queuedMessages.length > 0
1226
- ? `${queuedMessages.length} queued type another...`
1227
- : "Queue a message..."
1228
- : undefined, onSubmit: isRunning
1229
- ? (text, references) => addToQueue(text, undefined, references.length > 0 ? references : undefined)
1230
- : undefined, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, extraActionButton: showRunningInUI ? (_jsx("button", { type: "button", onClick: () => {
1231
- // Nuclear stop: flip forceStopped so isRunning is false
1232
- // immediately. This unblocks submission even if the
1233
- // runtime or reconnect state is stuck.
1234
- setForceStopped(true);
1235
- if (isReconnecting) {
1236
- if (reconnectRunIdRef.current) {
1237
- fetch(`${apiUrl}/runs/${encodeURIComponent(reconnectRunIdRef.current)}/abort`, { method: "POST" });
1266
+ const { isDevMode: cpDevMode } = useDevMode(apiUrl);
1267
+ const checkpointCtx = useMemo(() => ({ apiUrl, devMode: cpDevMode, threadId }), [apiUrl, cpDevMode, threadId]);
1268
+ return (_jsx(CheckpointContext.Provider, { value: checkpointCtx, children: _jsx(ChatRunningContext.Provider, { value: isRunning, children: _jsxs("div", { className: cn("flex flex-1 flex-col h-full min-h-0 text-foreground", className), children: [showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsxs("button", { onClick: onSwitchToCli, className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", title: "Switch to CLI", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] })) })] })), _jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-destructive/10", children: _jsx(IconLock, { className: "h-5 w-5 text-destructive" }) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authError.sessionExpired
1269
+ ? "Session expired"
1270
+ : "Authentication required" }), _jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: authError.sessionExpired ? ("Your session may have expired. Log out and log back in to reconnect.") : (_jsxs(_Fragment, { children: ["You need to log in to use the agent. If you're running locally, add", " ", _jsx("code", { className: "bg-muted px-1 py-0.5 rounded text-[10px]", children: "AUTH_MODE=local" }), " ", "to your", " ", _jsx("code", { className: "bg-muted px-1 py-0.5 rounded text-[10px]", children: ".env" }), " ", "file and restart the dev server."] })) })] }), _jsxs("div", { className: "flex gap-2", children: [authError.sessionExpired && (_jsx("button", { onClick: async () => {
1271
+ try {
1272
+ await fetch("/_agent-native/auth/logout", {
1273
+ method: "POST",
1274
+ });
1275
+ }
1276
+ catch { }
1277
+ window.location.reload();
1278
+ }, className: "text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10", children: "Log out" })), _jsx("button", { onClick: () => {
1279
+ setAuthError(null);
1280
+ window.location.reload();
1281
+ }, className: "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: "Retry" })] })] })) : missingApiKey ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(ApiKeySetupCard, { apiUrl: apiUrl }) })) : usageLimitReached ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(BuilderCtaCard, { reason: "usage_limit", usageCents: usageLimitReached.usageCents, limitCents: usageLimitReached.limitCents, apiUrl: apiUrl }) })) : isRestoring ? (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "h-8 w-32 rounded-lg bg-muted animate-pulse" }) }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "h-4 w-48 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-64 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-40 rounded bg-muted animate-pulse" })] })] })) : messages.length === 0 && !isReconnecting ? (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-16 px-4 h-full", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-muted", children: _jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground" }) }), _jsx("p", { className: "text-sm text-muted-foreground text-center max-w-[240px]", children: emptyStateText ?? "How can I help you?" }), suggestions && suggestions.length > 0 && (_jsx("div", { className: "flex flex-col gap-1.5 w-full max-w-[280px]", children: suggestions.map((suggestion) => (_jsx("button", { onClick: () => {
1282
+ threadRuntime.append({
1283
+ role: "user",
1284
+ content: [{ type: "text", text: suggestion }],
1285
+ });
1286
+ }, className: "w-full rounded-lg border border-border px-3 py-2 text-left text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground", children: suggestion }, suggestion))) }))] })) : (_jsxs("div", { className: "agent-thread-content flex flex-col gap-4 px-4 py-4", children: [_jsx(ThreadPrimitive.Messages, { components: {
1287
+ UserMessage,
1288
+ AssistantMessage,
1289
+ } }), showContinue && !showRunningInUI && (_jsx("div", { className: "flex justify-center py-2", children: _jsx("button", { type: "button", onClick: () => {
1290
+ setShowContinue(false);
1291
+ addToQueue("Continue from where you left off.");
1292
+ }, className: "rounded-lg border border-border bg-background px-4 py-2 text-sm font-medium text-foreground hover:bg-accent", children: "Continue" }) })), (isReconnecting || reconnectFrozen) &&
1293
+ reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), showRunningInUI && (_jsx(ThinkingIndicator, { label: isReconnecting ? "Reconnecting" : "Thinking" })), queuedMessages.map((msg) => {
1294
+ const displayText = msg.text
1295
+ .replace(/<context>[\s\S]*?<\/context>\n?/g, "")
1296
+ .trim();
1297
+ 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));
1298
+ })] })) }), 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("div", { className: "agent-composer-area shrink-0 px-3 py-2", 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, placeholder: isRunning
1299
+ ? queuedMessages.length > 0
1300
+ ? `${queuedMessages.length} queued — type another...`
1301
+ : "Queue a message..."
1302
+ : undefined, onSubmit: isRunning
1303
+ ? (text, references) => addToQueue(text, undefined, references.length > 0 ? references : undefined)
1304
+ : undefined, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, selectedModel: selectedModel ?? defaultModel, availableModels: availableModels, onModelChange: onModelChange, extraActionButton: showRunningInUI ? (_jsx("button", { type: "button", onClick: () => {
1305
+ // Nuclear stop: flip forceStopped so isRunning is false
1306
+ // immediately. This unblocks submission even if the
1307
+ // runtime or reconnect state is stuck.
1308
+ setForceStopped(true);
1309
+ if (isReconnecting) {
1310
+ if (reconnectRunIdRef.current) {
1311
+ fetch(`${apiUrl}/runs/${encodeURIComponent(reconnectRunIdRef.current)}/abort`, { method: "POST" });
1312
+ }
1313
+ reconnectAbortRef.current?.abort();
1314
+ reconnectAbortRef.current = null;
1315
+ reconnectRunIdRef.current = null;
1316
+ setIsReconnecting(false);
1317
+ setReconnectFrozen(reconnectContent.length > 0);
1238
1318
  }
1239
- reconnectAbortRef.current?.abort();
1240
- reconnectAbortRef.current = null;
1241
- reconnectRunIdRef.current = null;
1242
- setIsReconnecting(false);
1243
- setReconnectFrozen(reconnectContent.length > 0);
1244
- }
1245
- threadRuntime.cancelRun();
1246
- window.dispatchEvent(new CustomEvent("builder.chatRunning", {
1247
- detail: {
1248
- isRunning: false,
1249
- tabId: tabId || threadId,
1250
- },
1251
- }));
1252
- }, className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-muted text-foreground hover:bg-muted/80", title: "Stop generating", children: _jsx(IconPlayerStop, { className: "h-3.5 w-3.5" }) })) : undefined })] }) })] }) }));
1319
+ threadRuntime.cancelRun();
1320
+ window.dispatchEvent(new CustomEvent("builder.chatRunning", {
1321
+ detail: {
1322
+ isRunning: false,
1323
+ tabId: tabId || threadId,
1324
+ },
1325
+ }));
1326
+ }, className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-muted text-foreground hover:bg-muted/80", title: "Stop generating", children: _jsx(IconPlayerStop, { className: "h-3.5 w-3.5" }) })) : undefined })] }) })] }) }) }));
1253
1327
  });
1254
1328
  export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = "/_agent-native/agent-chat", tabId, threadId, ...props }, ref) {
1255
- const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId, threadId }), [apiUrl, tabId, threadId]);
1329
+ const modelRef = useRef(props.selectedModel);
1330
+ modelRef.current = props.selectedModel;
1331
+ const engineRef = useRef(props.selectedEngine);
1332
+ engineRef.current = props.selectedEngine;
1333
+ const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId, threadId, modelRef, engineRef }), [apiUrl, tabId, threadId]);
1256
1334
  const attachmentAdapter = useMemo(() => new CompositeAttachmentAdapter([
1257
1335
  new SimpleImageAttachmentAdapter(),
1258
1336
  new SimpleTextAttachmentAdapter(),