@agent-native/core 0.4.4 → 0.5.0-dev.b51eaae

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 (509) hide show
  1. package/dist/a2a/client.d.ts +7 -0
  2. package/dist/a2a/client.d.ts.map +1 -1
  3. package/dist/a2a/client.js +24 -3
  4. package/dist/a2a/client.js.map +1 -1
  5. package/dist/a2a/handlers.d.ts +6 -3
  6. package/dist/a2a/handlers.d.ts.map +1 -1
  7. package/dist/a2a/handlers.js +45 -39
  8. package/dist/a2a/handlers.js.map +1 -1
  9. package/dist/a2a/index.d.ts +1 -1
  10. package/dist/a2a/index.d.ts.map +1 -1
  11. package/dist/a2a/index.js +2 -2
  12. package/dist/a2a/index.js.map +1 -1
  13. package/dist/a2a/server.d.ts +7 -2
  14. package/dist/a2a/server.d.ts.map +1 -1
  15. package/dist/a2a/server.js +54 -14
  16. package/dist/a2a/server.js.map +1 -1
  17. package/dist/a2a/task-store.d.ts +6 -6
  18. package/dist/a2a/task-store.d.ts.map +1 -1
  19. package/dist/a2a/task-store.js +102 -42
  20. package/dist/a2a/task-store.js.map +1 -1
  21. package/dist/a2a/types.d.ts +2 -0
  22. package/dist/a2a/types.d.ts.map +1 -1
  23. package/dist/action.d.ts +46 -0
  24. package/dist/action.d.ts.map +1 -0
  25. package/dist/action.js +35 -0
  26. package/dist/action.js.map +1 -0
  27. package/dist/adapters/sync/file-sync.js +1 -1
  28. package/dist/agent/index.d.ts +2 -2
  29. package/dist/agent/index.d.ts.map +1 -1
  30. package/dist/agent/index.js.map +1 -1
  31. package/dist/agent/production-agent.d.ts +22 -6
  32. package/dist/agent/production-agent.d.ts.map +1 -1
  33. package/dist/agent/production-agent.js +326 -107
  34. package/dist/agent/production-agent.js.map +1 -1
  35. package/dist/agent/run-manager.d.ts +43 -0
  36. package/dist/agent/run-manager.d.ts.map +1 -0
  37. package/dist/agent/run-manager.js +358 -0
  38. package/dist/agent/run-manager.js.map +1 -0
  39. package/dist/agent/run-store.d.ts +26 -0
  40. package/dist/agent/run-store.d.ts.map +1 -0
  41. package/dist/agent/run-store.js +145 -0
  42. package/dist/agent/run-store.js.map +1 -0
  43. package/dist/agent/thread-data-builder.d.ts +30 -0
  44. package/dist/agent/thread-data-builder.d.ts.map +1 -0
  45. package/dist/agent/thread-data-builder.js +88 -0
  46. package/dist/agent/thread-data-builder.js.map +1 -0
  47. package/dist/agent/types.d.ts +52 -1
  48. package/dist/agent/types.d.ts.map +1 -1
  49. package/dist/application-state/emitter.d.ts +3 -2
  50. package/dist/application-state/emitter.d.ts.map +1 -1
  51. package/dist/application-state/emitter.js +14 -4
  52. package/dist/application-state/emitter.js.map +1 -1
  53. package/dist/application-state/handlers.d.ts.map +1 -1
  54. package/dist/application-state/handlers.js +13 -16
  55. package/dist/application-state/handlers.js.map +1 -1
  56. package/dist/application-state/script-helpers.d.ts +1 -1
  57. package/dist/application-state/script-helpers.d.ts.map +1 -1
  58. package/dist/application-state/script-helpers.js +15 -5
  59. package/dist/application-state/script-helpers.js.map +1 -1
  60. package/dist/application-state/store.d.ts +4 -3
  61. package/dist/application-state/store.d.ts.map +1 -1
  62. package/dist/application-state/store.js +31 -38
  63. package/dist/application-state/store.js.map +1 -1
  64. package/dist/chat-threads/emitter.d.ts +9 -0
  65. package/dist/chat-threads/emitter.d.ts.map +1 -0
  66. package/dist/chat-threads/emitter.js +14 -0
  67. package/dist/chat-threads/emitter.js.map +1 -0
  68. package/dist/chat-threads/store.d.ts +28 -0
  69. package/dist/chat-threads/store.d.ts.map +1 -0
  70. package/dist/chat-threads/store.js +124 -0
  71. package/dist/chat-threads/store.js.map +1 -0
  72. package/dist/cli/create.d.ts.map +1 -1
  73. package/dist/cli/create.js +4 -18
  74. package/dist/cli/create.js.map +1 -1
  75. package/dist/cli/index.js +42 -3
  76. package/dist/cli/index.js.map +1 -1
  77. package/dist/cli/setup-agents.d.ts +11 -0
  78. package/dist/cli/setup-agents.d.ts.map +1 -0
  79. package/dist/cli/setup-agents.js +123 -0
  80. package/dist/cli/setup-agents.js.map +1 -0
  81. package/dist/client/AgentPanel.d.ts +14 -3
  82. package/dist/client/AgentPanel.d.ts.map +1 -1
  83. package/dist/client/AgentPanel.js +492 -21
  84. package/dist/client/AgentPanel.js.map +1 -1
  85. package/dist/client/AssistantChat.d.ts +27 -3
  86. package/dist/client/AssistantChat.d.ts.map +1 -1
  87. package/dist/client/AssistantChat.js +639 -57
  88. package/dist/client/AssistantChat.js.map +1 -1
  89. package/dist/client/ClientOnly.d.ts +14 -0
  90. package/dist/client/ClientOnly.d.ts.map +1 -0
  91. package/dist/client/ClientOnly.js +17 -0
  92. package/dist/client/ClientOnly.js.map +1 -0
  93. package/dist/client/CommandMenu.d.ts +71 -0
  94. package/dist/client/CommandMenu.d.ts.map +1 -0
  95. package/dist/client/CommandMenu.js +257 -0
  96. package/dist/client/CommandMenu.js.map +1 -0
  97. package/dist/client/DefaultSpinner.d.ts +7 -0
  98. package/dist/client/DefaultSpinner.d.ts.map +1 -0
  99. package/dist/client/DefaultSpinner.js +28 -0
  100. package/dist/client/DefaultSpinner.js.map +1 -0
  101. package/dist/client/MultiTabAssistantChat.d.ts +34 -2
  102. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  103. package/dist/client/MultiTabAssistantChat.js +346 -67
  104. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  105. package/dist/client/PoweredByBadge.d.ts.map +1 -1
  106. package/dist/client/PoweredByBadge.js +2 -1
  107. package/dist/client/PoweredByBadge.js.map +1 -1
  108. package/dist/client/active-run-state.d.ts +10 -0
  109. package/dist/client/active-run-state.d.ts.map +1 -0
  110. package/dist/client/active-run-state.js +32 -0
  111. package/dist/client/active-run-state.js.map +1 -0
  112. package/dist/client/agent-chat-adapter.d.ts +2 -1
  113. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  114. package/dist/client/agent-chat-adapter.js +83 -129
  115. package/dist/client/agent-chat-adapter.js.map +1 -1
  116. package/dist/client/agent-chat.d.ts +2 -0
  117. package/dist/client/agent-chat.d.ts.map +1 -1
  118. package/dist/client/agent-chat.js +2 -2
  119. package/dist/client/agent-chat.js.map +1 -1
  120. package/dist/client/analytics.d.ts +16 -0
  121. package/dist/client/analytics.d.ts.map +1 -0
  122. package/dist/client/analytics.js +17 -0
  123. package/dist/client/analytics.js.map +1 -0
  124. package/dist/client/components/ApiKeySettings.d.ts +2 -2
  125. package/dist/client/components/ApiKeySettings.js +4 -4
  126. package/dist/client/components/ApiKeySettings.js.map +1 -1
  127. package/dist/client/components/CodeRequiredDialog.d.ts +13 -0
  128. package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -0
  129. package/dist/client/components/CodeRequiredDialog.js +160 -0
  130. package/dist/client/components/CodeRequiredDialog.js.map +1 -0
  131. package/dist/client/composer/MentionPopover.d.ts +26 -0
  132. package/dist/client/composer/MentionPopover.d.ts.map +1 -0
  133. package/dist/client/composer/MentionPopover.js +130 -0
  134. package/dist/client/composer/MentionPopover.js.map +1 -0
  135. package/dist/client/composer/TiptapComposer.d.ts +19 -0
  136. package/dist/client/composer/TiptapComposer.d.ts.map +1 -0
  137. package/dist/client/composer/TiptapComposer.js +415 -0
  138. package/dist/client/composer/TiptapComposer.js.map +1 -0
  139. package/dist/client/composer/extensions/FileReference.d.ts +3 -0
  140. package/dist/client/composer/extensions/FileReference.d.ts.map +1 -0
  141. package/dist/client/composer/extensions/FileReference.js +36 -0
  142. package/dist/client/composer/extensions/FileReference.js.map +1 -0
  143. package/dist/client/composer/extensions/MentionReference.d.ts +3 -0
  144. package/dist/client/composer/extensions/MentionReference.d.ts.map +1 -0
  145. package/dist/client/composer/extensions/MentionReference.js +63 -0
  146. package/dist/client/composer/extensions/MentionReference.js.map +1 -0
  147. package/dist/client/composer/extensions/SkillReference.d.ts +3 -0
  148. package/dist/client/composer/extensions/SkillReference.d.ts.map +1 -0
  149. package/dist/client/composer/extensions/SkillReference.js +40 -0
  150. package/dist/client/composer/extensions/SkillReference.js.map +1 -0
  151. package/dist/client/composer/index.d.ts +8 -0
  152. package/dist/client/composer/index.d.ts.map +1 -0
  153. package/dist/client/composer/index.js +7 -0
  154. package/dist/client/composer/index.js.map +1 -0
  155. package/dist/client/composer/types.d.ts +32 -0
  156. package/dist/client/composer/types.d.ts.map +1 -0
  157. package/dist/client/composer/types.js +2 -0
  158. package/dist/client/composer/types.js.map +1 -0
  159. package/dist/client/composer/use-file-search.d.ts +6 -0
  160. package/dist/client/composer/use-file-search.d.ts.map +1 -0
  161. package/dist/client/composer/use-file-search.js +40 -0
  162. package/dist/client/composer/use-file-search.js.map +1 -0
  163. package/dist/client/composer/use-mention-search.d.ts +6 -0
  164. package/dist/client/composer/use-mention-search.d.ts.map +1 -0
  165. package/dist/client/composer/use-mention-search.js +39 -0
  166. package/dist/client/composer/use-mention-search.js.map +1 -0
  167. package/dist/client/composer/use-skills.d.ts +7 -0
  168. package/dist/client/composer/use-skills.d.ts.map +1 -0
  169. package/dist/client/composer/use-skills.js +38 -0
  170. package/dist/client/composer/use-skills.js.map +1 -0
  171. package/dist/client/index.d.ts +13 -4
  172. package/dist/client/index.d.ts.map +1 -1
  173. package/dist/client/index.js +12 -3
  174. package/dist/client/index.js.map +1 -1
  175. package/dist/client/resources/ResourceEditor.d.ts +7 -0
  176. package/dist/client/resources/ResourceEditor.d.ts.map +1 -0
  177. package/dist/client/resources/ResourceEditor.js +851 -0
  178. package/dist/client/resources/ResourceEditor.js.map +1 -0
  179. package/dist/client/resources/ResourceTree.d.ts +13 -0
  180. package/dist/client/resources/ResourceTree.d.ts.map +1 -0
  181. package/dist/client/resources/ResourceTree.js +122 -0
  182. package/dist/client/resources/ResourceTree.js.map +1 -0
  183. package/dist/client/resources/ResourcesPanel.d.ts +2 -0
  184. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -0
  185. package/dist/client/resources/ResourcesPanel.js +341 -0
  186. package/dist/client/resources/ResourcesPanel.js.map +1 -0
  187. package/dist/client/resources/index.d.ts +5 -0
  188. package/dist/client/resources/index.d.ts.map +1 -0
  189. package/dist/client/resources/index.js +5 -0
  190. package/dist/client/resources/index.js.map +1 -0
  191. package/dist/client/resources/use-resources.d.ts +45 -0
  192. package/dist/client/resources/use-resources.d.ts.map +1 -0
  193. package/dist/client/resources/use-resources.js +102 -0
  194. package/dist/client/resources/use-resources.js.map +1 -0
  195. package/dist/client/sse-event-processor.d.ts +50 -0
  196. package/dist/client/sse-event-processor.d.ts.map +1 -0
  197. package/dist/client/sse-event-processor.js +267 -0
  198. package/dist/client/sse-event-processor.js.map +1 -0
  199. package/dist/client/terminal/AgentTerminal.d.ts +1 -1
  200. package/dist/client/terminal/AgentTerminal.d.ts.map +1 -1
  201. package/dist/client/terminal/AgentTerminal.js +12 -7
  202. package/dist/client/terminal/AgentTerminal.js.map +1 -1
  203. package/dist/client/use-agent-chat.d.ts +1 -1
  204. package/dist/client/use-agent-chat.d.ts.map +1 -1
  205. package/dist/client/use-agent-chat.js +3 -3
  206. package/dist/client/use-agent-chat.js.map +1 -1
  207. package/dist/client/use-chat-threads.d.ts +36 -0
  208. package/dist/client/use-chat-threads.d.ts.map +1 -0
  209. package/dist/client/use-chat-threads.js +175 -0
  210. package/dist/client/use-chat-threads.js.map +1 -0
  211. package/dist/client/use-db-sync.d.ts +35 -0
  212. package/dist/client/use-db-sync.d.ts.map +1 -0
  213. package/dist/client/use-db-sync.js +74 -0
  214. package/dist/client/use-db-sync.js.map +1 -0
  215. package/dist/client/use-dev-mode.d.ts +11 -0
  216. package/dist/client/use-dev-mode.d.ts.map +1 -0
  217. package/dist/client/use-dev-mode.js +71 -0
  218. package/dist/client/use-dev-mode.js.map +1 -0
  219. package/dist/client/use-file-sync-status.d.ts +1 -1
  220. package/dist/client/use-file-sync-status.js +3 -3
  221. package/dist/client/use-file-sync-status.js.map +1 -1
  222. package/dist/client/use-send-to-agent-chat.d.ts +17 -0
  223. package/dist/client/use-send-to-agent-chat.d.ts.map +1 -0
  224. package/dist/client/use-send-to-agent-chat.js +40 -0
  225. package/dist/client/use-send-to-agent-chat.js.map +1 -0
  226. package/dist/client/use-session.d.ts +1 -1
  227. package/dist/client/use-session.d.ts.map +1 -1
  228. package/dist/client/use-session.js +13 -4
  229. package/dist/client/use-session.js.map +1 -1
  230. package/dist/client/useProductionAgent.d.ts +1 -1
  231. package/dist/client/useProductionAgent.d.ts.map +1 -1
  232. package/dist/client/useProductionAgent.js +38 -3
  233. package/dist/client/useProductionAgent.js.map +1 -1
  234. package/dist/credentials/index.d.ts +18 -0
  235. package/dist/credentials/index.d.ts.map +1 -0
  236. package/dist/credentials/index.js +32 -0
  237. package/dist/credentials/index.js.map +1 -0
  238. package/dist/db/client.d.ts +35 -0
  239. package/dist/db/client.d.ts.map +1 -0
  240. package/dist/db/client.js +248 -0
  241. package/dist/db/client.js.map +1 -0
  242. package/dist/db/create-get-db.d.ts.map +1 -1
  243. package/dist/db/create-get-db.js +108 -12
  244. package/dist/db/create-get-db.js.map +1 -1
  245. package/dist/db/index.d.ts +10 -6
  246. package/dist/db/index.d.ts.map +1 -1
  247. package/dist/db/index.js +10 -4
  248. package/dist/db/index.js.map +1 -1
  249. package/dist/db/migrations.d.ts.map +1 -1
  250. package/dist/db/migrations.js +52 -21
  251. package/dist/db/migrations.js.map +1 -1
  252. package/dist/db/schema.d.ts +45 -0
  253. package/dist/db/schema.d.ts.map +1 -0
  254. package/dist/db/schema.js +61 -0
  255. package/dist/db/schema.js.map +1 -0
  256. package/dist/deploy/build.d.ts +16 -0
  257. package/dist/deploy/build.d.ts.map +1 -0
  258. package/dist/deploy/build.js +453 -0
  259. package/dist/deploy/build.js.map +1 -0
  260. package/dist/deploy/route-discovery.d.ts +43 -0
  261. package/dist/deploy/route-discovery.d.ts.map +1 -0
  262. package/dist/deploy/route-discovery.js +115 -0
  263. package/dist/deploy/route-discovery.js.map +1 -0
  264. package/dist/index.browser.d.ts +1 -1
  265. package/dist/index.browser.d.ts.map +1 -1
  266. package/dist/index.browser.js +1 -1
  267. package/dist/index.browser.js.map +1 -1
  268. package/dist/index.d.ts +3 -2
  269. package/dist/index.d.ts.map +1 -1
  270. package/dist/index.js +2 -1
  271. package/dist/index.js.map +1 -1
  272. package/dist/oauth-tokens/index.d.ts +1 -1
  273. package/dist/oauth-tokens/index.d.ts.map +1 -1
  274. package/dist/oauth-tokens/index.js +1 -1
  275. package/dist/oauth-tokens/index.js.map +1 -1
  276. package/dist/oauth-tokens/store.d.ts +18 -1
  277. package/dist/oauth-tokens/store.d.ts.map +1 -1
  278. package/dist/oauth-tokens/store.js +81 -40
  279. package/dist/oauth-tokens/store.js.map +1 -1
  280. package/dist/resources/emitter.d.ts +13 -0
  281. package/dist/resources/emitter.d.ts.map +1 -0
  282. package/dist/resources/emitter.js +32 -0
  283. package/dist/resources/emitter.js.map +1 -0
  284. package/dist/resources/handlers.d.ts +45 -0
  285. package/dist/resources/handlers.d.ts.map +1 -0
  286. package/dist/resources/handlers.js +219 -0
  287. package/dist/resources/handlers.js.map +1 -0
  288. package/dist/resources/index.d.ts +5 -0
  289. package/dist/resources/index.d.ts.map +1 -0
  290. package/dist/resources/index.js +5 -0
  291. package/dist/resources/index.js.map +1 -0
  292. package/dist/resources/script-helpers.d.ts +24 -0
  293. package/dist/resources/script-helpers.d.ts.map +1 -0
  294. package/dist/resources/script-helpers.js +36 -0
  295. package/dist/resources/script-helpers.js.map +1 -0
  296. package/dist/resources/store.d.ts +35 -0
  297. package/dist/resources/store.d.ts.map +1 -0
  298. package/dist/resources/store.js +453 -0
  299. package/dist/resources/store.js.map +1 -0
  300. package/dist/scripts/call-agent.d.ts +5 -0
  301. package/dist/scripts/call-agent.d.ts.map +1 -0
  302. package/dist/scripts/call-agent.js +107 -0
  303. package/dist/scripts/call-agent.js.map +1 -0
  304. package/dist/scripts/core-scripts.d.ts.map +1 -1
  305. package/dist/scripts/core-scripts.js +2 -0
  306. package/dist/scripts/core-scripts.js.map +1 -1
  307. package/dist/scripts/db/exec.d.ts +6 -2
  308. package/dist/scripts/db/exec.d.ts.map +1 -1
  309. package/dist/scripts/db/exec.js +127 -36
  310. package/dist/scripts/db/exec.js.map +1 -1
  311. package/dist/scripts/db/query.d.ts +7 -2
  312. package/dist/scripts/db/query.d.ts.map +1 -1
  313. package/dist/scripts/db/query.js +89 -45
  314. package/dist/scripts/db/query.js.map +1 -1
  315. package/dist/scripts/db/schema.d.ts +2 -2
  316. package/dist/scripts/db/schema.d.ts.map +1 -1
  317. package/dist/scripts/db/schema.js +145 -6
  318. package/dist/scripts/db/schema.js.map +1 -1
  319. package/dist/scripts/db/scoping.d.ts +36 -0
  320. package/dist/scripts/db/scoping.d.ts.map +1 -0
  321. package/dist/scripts/db/scoping.js +198 -0
  322. package/dist/scripts/db/scoping.js.map +1 -0
  323. package/dist/scripts/dev/index.d.ts +2 -2
  324. package/dist/scripts/dev/index.js +1 -1
  325. package/dist/scripts/dev/list-files.d.ts +2 -2
  326. package/dist/scripts/dev/read-file.d.ts +2 -2
  327. package/dist/scripts/dev/read-file.js +1 -1
  328. package/dist/scripts/dev/read-file.js.map +1 -1
  329. package/dist/scripts/dev/search-files.d.ts +2 -2
  330. package/dist/scripts/dev/search-files.js +1 -1
  331. package/dist/scripts/dev/search-files.js.map +1 -1
  332. package/dist/scripts/dev/shell.d.ts +2 -2
  333. package/dist/scripts/dev/shell.js +1 -1
  334. package/dist/scripts/dev/shell.js.map +1 -1
  335. package/dist/scripts/dev/write-file.d.ts +2 -2
  336. package/dist/scripts/dev/write-file.js +1 -1
  337. package/dist/scripts/dev/write-file.js.map +1 -1
  338. package/dist/scripts/resources/delete.d.ts +10 -0
  339. package/dist/scripts/resources/delete.d.ts.map +1 -0
  340. package/dist/scripts/resources/delete.js +38 -0
  341. package/dist/scripts/resources/delete.js.map +1 -0
  342. package/dist/scripts/resources/index.d.ts +2 -0
  343. package/dist/scripts/resources/index.d.ts.map +1 -0
  344. package/dist/scripts/resources/index.js +8 -0
  345. package/dist/scripts/resources/index.js.map +1 -0
  346. package/dist/scripts/resources/list.d.ts +10 -0
  347. package/dist/scripts/resources/list.d.ts.map +1 -0
  348. package/dist/scripts/resources/list.js +57 -0
  349. package/dist/scripts/resources/list.js.map +1 -0
  350. package/dist/scripts/resources/migrate-learnings.d.ts +10 -0
  351. package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -0
  352. package/dist/scripts/resources/migrate-learnings.js +23 -0
  353. package/dist/scripts/resources/migrate-learnings.js.map +1 -0
  354. package/dist/scripts/resources/read.d.ts +10 -0
  355. package/dist/scripts/resources/read.d.ts.map +1 -0
  356. package/dist/scripts/resources/read.js +59 -0
  357. package/dist/scripts/resources/read.js.map +1 -0
  358. package/dist/scripts/resources/write.d.ts +10 -0
  359. package/dist/scripts/resources/write.d.ts.map +1 -0
  360. package/dist/scripts/resources/write.js +67 -0
  361. package/dist/scripts/resources/write.js.map +1 -0
  362. package/dist/scripts/runner.d.ts +7 -7
  363. package/dist/scripts/runner.d.ts.map +1 -1
  364. package/dist/scripts/runner.js +68 -27
  365. package/dist/scripts/runner.js.map +1 -1
  366. package/dist/scripts/utils.d.ts +4 -1
  367. package/dist/scripts/utils.d.ts.map +1 -1
  368. package/dist/scripts/utils.js +5 -3
  369. package/dist/scripts/utils.js.map +1 -1
  370. package/dist/server/action-discovery.d.ts +40 -0
  371. package/dist/server/action-discovery.d.ts.map +1 -0
  372. package/dist/server/action-discovery.js +189 -0
  373. package/dist/server/action-discovery.js.map +1 -0
  374. package/dist/server/agent-chat-plugin.d.ts +12 -23
  375. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  376. package/dist/server/agent-chat-plugin.js +1102 -39
  377. package/dist/server/agent-chat-plugin.js.map +1 -1
  378. package/dist/server/agent-discovery.d.ts +16 -0
  379. package/dist/server/agent-discovery.d.ts.map +1 -0
  380. package/dist/server/agent-discovery.js +136 -0
  381. package/dist/server/agent-discovery.js.map +1 -0
  382. package/dist/server/analytics.d.ts +19 -0
  383. package/dist/server/analytics.d.ts.map +1 -0
  384. package/dist/server/analytics.js +61 -0
  385. package/dist/server/analytics.js.map +1 -0
  386. package/dist/server/auth-plugin.d.ts +5 -0
  387. package/dist/server/auth-plugin.d.ts.map +1 -1
  388. package/dist/server/auth-plugin.js +12 -1
  389. package/dist/server/auth-plugin.js.map +1 -1
  390. package/dist/server/auth.d.ts +3 -1
  391. package/dist/server/auth.d.ts.map +1 -1
  392. package/dist/server/auth.js +598 -104
  393. package/dist/server/auth.js.map +1 -1
  394. package/dist/server/core-routes-plugin.d.ts +57 -0
  395. package/dist/server/core-routes-plugin.d.ts.map +1 -0
  396. package/dist/server/core-routes-plugin.js +125 -0
  397. package/dist/server/core-routes-plugin.js.map +1 -0
  398. package/dist/server/create-server.d.ts +4 -4
  399. package/dist/server/create-server.d.ts.map +1 -1
  400. package/dist/server/create-server.js +5 -5
  401. package/dist/server/create-server.js.map +1 -1
  402. package/dist/server/default-watcher.d.ts +9 -3
  403. package/dist/server/default-watcher.d.ts.map +1 -1
  404. package/dist/server/default-watcher.js +26 -6
  405. package/dist/server/default-watcher.js.map +1 -1
  406. package/dist/server/google-auth-plugin.d.ts.map +1 -1
  407. package/dist/server/google-auth-plugin.js +4 -3
  408. package/dist/server/google-auth-plugin.js.map +1 -1
  409. package/dist/server/google-oauth.d.ts +72 -0
  410. package/dist/server/google-oauth.d.ts.map +1 -0
  411. package/dist/server/google-oauth.js +187 -0
  412. package/dist/server/google-oauth.js.map +1 -0
  413. package/dist/server/index.d.ts +10 -2
  414. package/dist/server/index.d.ts.map +1 -1
  415. package/dist/server/index.js +9 -1
  416. package/dist/server/index.js.map +1 -1
  417. package/dist/server/oauth-helpers.d.ts +16 -0
  418. package/dist/server/oauth-helpers.d.ts.map +1 -0
  419. package/dist/server/oauth-helpers.js +25 -0
  420. package/dist/server/oauth-helpers.js.map +1 -0
  421. package/dist/server/poll.d.ts +40 -0
  422. package/dist/server/poll.d.ts.map +1 -0
  423. package/dist/server/poll.js +49 -0
  424. package/dist/server/poll.js.map +1 -0
  425. package/dist/server/resources-plugin.d.ts +27 -0
  426. package/dist/server/resources-plugin.d.ts.map +1 -0
  427. package/dist/server/resources-plugin.js +74 -0
  428. package/dist/server/resources-plugin.js.map +1 -0
  429. package/dist/server/script-discovery.d.ts +6 -0
  430. package/dist/server/script-discovery.d.ts.map +1 -0
  431. package/dist/server/script-discovery.js +6 -0
  432. package/dist/server/script-discovery.js.map +1 -0
  433. package/dist/server/sse.d.ts +1 -1
  434. package/dist/server/sse.js +1 -1
  435. package/dist/settings/handlers.d.ts +3 -3
  436. package/dist/settings/handlers.d.ts.map +1 -1
  437. package/dist/settings/handlers.js +8 -6
  438. package/dist/settings/handlers.js.map +1 -1
  439. package/dist/settings/index.d.ts +1 -1
  440. package/dist/settings/index.d.ts.map +1 -1
  441. package/dist/settings/index.js.map +1 -1
  442. package/dist/settings/store.d.ts +6 -2
  443. package/dist/settings/store.d.ts.map +1 -1
  444. package/dist/settings/store.js +26 -36
  445. package/dist/settings/store.js.map +1 -1
  446. package/dist/settings/user-settings.d.ts +6 -10
  447. package/dist/settings/user-settings.d.ts.map +1 -1
  448. package/dist/settings/user-settings.js +9 -18
  449. package/dist/settings/user-settings.js.map +1 -1
  450. package/dist/tailwind.preset.d.ts +7 -6
  451. package/dist/tailwind.preset.d.ts.map +1 -1
  452. package/dist/tailwind.preset.js +18 -1
  453. package/dist/tailwind.preset.js.map +1 -1
  454. package/dist/terminal/cli-registry.d.ts +3 -1
  455. package/dist/terminal/cli-registry.d.ts.map +1 -1
  456. package/dist/terminal/cli-registry.js +10 -5
  457. package/dist/terminal/cli-registry.js.map +1 -1
  458. package/dist/terminal/pty-server.d.ts.map +1 -1
  459. package/dist/terminal/pty-server.js +65 -11
  460. package/dist/terminal/pty-server.js.map +1 -1
  461. package/dist/terminal/terminal-plugin.d.ts +2 -2
  462. package/dist/terminal/terminal-plugin.d.ts.map +1 -1
  463. package/dist/terminal/terminal-plugin.js +27 -8
  464. package/dist/terminal/terminal-plugin.js.map +1 -1
  465. package/dist/vite/client.d.ts.map +1 -1
  466. package/dist/vite/client.js +114 -8
  467. package/dist/vite/client.js.map +1 -1
  468. package/dist/vite/dev-api-server.d.ts +1 -1
  469. package/dist/vite/dev-api-server.d.ts.map +1 -1
  470. package/dist/vite/dev-api-server.js +105 -22
  471. package/dist/vite/dev-api-server.js.map +1 -1
  472. package/package.json +23 -7
  473. package/src/templates/default/.agents/skills/actions/SKILL.md +136 -0
  474. package/src/templates/default/.agents/skills/create-skill/SKILL.md +1 -1
  475. package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +1 -1
  476. package/src/templates/default/.agents/skills/files-as-database/SKILL.md +2 -2
  477. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +112 -0
  478. package/src/templates/default/AGENTS.md +56 -164
  479. package/src/templates/default/DEVELOPING.md +117 -0
  480. package/src/templates/default/{scripts → actions}/hello.ts +1 -1
  481. package/src/templates/default/actions/navigate.ts +53 -0
  482. package/src/templates/default/actions/view-screen.ts +39 -0
  483. package/src/templates/default/app/entry.server.tsx +2 -1
  484. package/src/templates/default/app/global.css +2 -2
  485. package/src/templates/default/app/root.tsx +27 -15
  486. package/src/templates/default/app/routes/_index.tsx +1 -1
  487. package/src/templates/default/package.json +4 -0
  488. package/src/templates/default/public/icon-180.svg +4 -0
  489. package/src/templates/default/public/icon-192.svg +4 -0
  490. package/src/templates/default/public/icon-512.svg +4 -0
  491. package/src/templates/default/public/manifest.json +13 -0
  492. package/src/templates/default/server/plugins/.gitkeep +0 -0
  493. package/dist/a2a/middleware.d.ts +0 -3
  494. package/dist/a2a/middleware.d.ts.map +0 -1
  495. package/dist/a2a/middleware.js +0 -36
  496. package/dist/a2a/middleware.js.map +0 -1
  497. package/dist/client/use-file-watcher.d.ts +0 -23
  498. package/dist/client/use-file-watcher.d.ts.map +0 -1
  499. package/dist/client/use-file-watcher.js +0 -50
  500. package/dist/client/use-file-watcher.js.map +0 -1
  501. package/src/templates/default/.agents/skills/scripts/SKILL.md +0 -121
  502. package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +0 -80
  503. package/src/templates/default/server/plugins/agent-chat.ts +0 -1
  504. package/src/templates/default/server/plugins/auth.ts +0 -1
  505. package/src/templates/default/server/plugins/file-sync.ts +0 -1
  506. package/src/templates/default/server/plugins/terminal.ts +0 -1
  507. package/src/templates/default/server/routes/api/events.get.ts +0 -3
  508. package/src/templates/default/server/routes/api/file-sync/status.get.ts +0 -4
  509. /package/src/templates/default/{scripts → actions}/run.ts +0 -0
@@ -1,55 +1,298 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState, useRef, useEffect, useCallback, useMemo, forwardRef, useImperativeHandle, } from "react";
3
- import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
3
+ import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useAui, useComposer, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
4
+ import { SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, CompositeAttachmentAdapter, } from "@assistant-ui/react";
5
+ import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown";
6
+ import ReactMarkdown from "react-markdown";
4
7
  import { createAgentChatAdapter } from "./agent-chat-adapter.js";
8
+ import { readSSEStreamRaw } from "./sse-event-processor.js";
5
9
  import { cn } from "./utils.js";
6
- // ─── Icons ──────────────────────────────────────────────────────────────────
7
- function SparklesIcon({ className }) {
8
- return (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("path", { d: "M12 3l1.912 5.813a2 2 0 0 0 1.275 1.275L21 12l-5.813 1.912a2 2 0 0 0-1.275 1.275L12 21l-1.912-5.813a2 2 0 0 0-1.275-1.275L3 12l5.813-1.912a2 2 0 0 0 1.275-1.275L12 3z" }) }));
10
+ import { TiptapComposer, } from "./composer/TiptapComposer.js";
11
+ import { IconSparkles, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, } from "@tabler/icons-react";
12
+ // ─── Markdown Text ──────────────────────────────────────────────────────────
13
+ const markdownStyles = `
14
+ .agent-markdown > :first-child { margin-top: 0; }
15
+ .agent-markdown > :last-child { margin-bottom: 0; }
16
+ .agent-markdown p { margin: 0.5em 0; }
17
+ .agent-markdown ul, .agent-markdown ol { margin: 0.5em 0; padding-left: 1.5em; }
18
+ .agent-markdown li { margin: 0.2em 0; }
19
+ .agent-markdown li > p { margin: 0; }
20
+ .agent-markdown h1 { font-size: 1.25em; font-weight: 600; margin: 0.75em 0 0.25em; }
21
+ .agent-markdown h2 { font-size: 1.125em; font-weight: 600; margin: 0.75em 0 0.25em; }
22
+ .agent-markdown h3 { font-size: 1em; font-weight: 600; margin: 0.75em 0 0.25em; }
23
+ .agent-markdown strong { font-weight: 600; }
24
+ .agent-markdown em { font-style: italic; }
25
+ .agent-markdown code { font-size: 0.875em; padding: 0.15em 0.35em; border-radius: 0.25em; background: var(--color-muted, hsl(0 0% 15%)); }
26
+ .agent-markdown pre { margin: 0.5em 0; padding: 0.75em 1em; border-radius: 0.375em; background: var(--color-muted, hsl(0 0% 15%)); overflow-x: auto; }
27
+ .agent-markdown pre code { padding: 0; background: transparent; font-size: 0.8125em; }
28
+ .agent-markdown hr { border: none; border-top: 1px solid var(--color-border, hsl(0 0% 20%)); margin: 0.75em 0; }
29
+ .agent-markdown a { text-decoration: underline; text-underline-offset: 2px; }
30
+ .agent-markdown blockquote { border-left: 2px solid var(--color-border, hsl(0 0% 20%)); padding-left: 0.75em; margin: 0.5em 0; opacity: 0.8; }
31
+ .agent-markdown table { border-collapse: collapse; margin: 0.5em 0; font-size: 0.875em; }
32
+ .agent-markdown th, .agent-markdown td { border: 1px solid var(--color-border, hsl(0 0% 20%)); padding: 0.35em 0.65em; text-align: left; }
33
+ .agent-markdown th { font-weight: 600; background: var(--color-muted, hsl(0 0% 15%)); }
34
+ `;
35
+ let stylesInjected = false;
36
+ function injectMarkdownStyles() {
37
+ if (stylesInjected || typeof document === "undefined")
38
+ return;
39
+ stylesInjected = true;
40
+ const style = document.createElement("style");
41
+ style.textContent = markdownStyles;
42
+ document.head.appendChild(style);
9
43
  }
10
- function SendIcon({ className }) {
11
- return (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("path", { d: "M5 12h14M12 5l7 7-7 7" }) }));
12
- }
13
- function StopIcon({ className }) {
14
- return (_jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", className: className, children: _jsx("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }));
15
- }
16
- function CheckIcon({ className }) {
17
- return (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("path", { d: "M20 6L9 17l-5-5" }) }));
44
+ function MarkdownText() {
45
+ useEffect(() => {
46
+ injectMarkdownStyles();
47
+ }, []);
48
+ return (_jsx(MarkdownTextPrimitive, { smooth: true, className: "agent-markdown break-words" }));
18
49
  }
19
- function ChevronDownIcon({ className }) {
20
- return (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("path", { d: "m6 9 6 6 6-6" }) }));
50
+ // ─── Composer Attachment Preview ─────────────────────────────────────────────
51
+ function getImageAttachmentSrc(attachment) {
52
+ if (attachment.type !== "image")
53
+ return null;
54
+ if ("file" in attachment && attachment.file) {
55
+ return URL.createObjectURL(attachment.file);
56
+ }
57
+ const imagePart = attachment.content?.find((part) => part.type === "image");
58
+ return imagePart && "image" in imagePart ? imagePart.image : null;
21
59
  }
22
- function ArrowDownIcon({ className }) {
23
- return (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("path", { d: "M12 5v14M19 12l-7 7-7-7" }) }));
60
+ function ComposerAttachmentPreviewCard({ attachment, onRemove, }) {
61
+ const [imageSrc, setImageSrc] = useState(null);
62
+ useEffect(() => {
63
+ const nextSrc = getImageAttachmentSrc(attachment);
64
+ setImageSrc(nextSrc);
65
+ return () => {
66
+ if (nextSrc?.startsWith("blob:")) {
67
+ URL.revokeObjectURL(nextSrc);
68
+ }
69
+ };
70
+ }, [attachment]);
71
+ const isImage = !!imageSrc;
72
+ return (_jsxs("div", { className: cn("group relative overflow-hidden border border-border/70 bg-muted/50 text-foreground", isImage
73
+ ? "h-20 w-20 rounded-xl shadow-[0_12px_30px_-18px_rgba(0,0,0,0.7)]"
74
+ : "inline-flex max-w-[220px] items-center gap-2 rounded-lg px-2.5 py-2 text-xs"), children: [isImage ? (_jsxs(_Fragment, { children: [_jsx("img", { src: imageSrc, alt: attachment.name, className: "h-full w-full object-cover" }), _jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/80 via-black/30 to-transparent px-2 py-1.5", children: _jsx("div", { className: "truncate text-[10px] font-medium text-white/95", children: attachment.name }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-background text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: attachment.name.split(".").pop() || "file" }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate font-medium", children: attachment.name }), _jsx("div", { className: "text-[11px] text-muted-foreground", children: attachment.contentType || attachment.type })] })] })), _jsx("button", { type: "button", onClick: () => onRemove(attachment.id), className: cn("absolute flex h-6 w-6 items-center justify-center rounded-full border border-border/60 bg-background/95 text-muted-foreground shadow-sm transition hover:text-foreground", isImage
75
+ ? "right-1.5 top-1.5 opacity-100 md:opacity-0 md:group-hover:opacity-100"
76
+ : "right-1.5 top-1.5"), "aria-label": `Remove ${attachment.name}`, children: _jsx(IconX, { className: "h-3 w-3" }) })] }));
24
77
  }
25
- function CopyIcon({ className }) {
26
- return (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", className: className, children: [_jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), _jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] }));
78
+ function ComposerAttachmentPreviewStrip() {
79
+ const attachments = useComposer((state) => state.attachments);
80
+ const aui = useAui();
81
+ const handleRemove = useCallback((id) => {
82
+ void aui.composer().attachment({ id }).remove();
83
+ }, [aui]);
84
+ if (attachments.length === 0)
85
+ return null;
86
+ return (_jsx("div", { className: "flex flex-wrap gap-2 px-2 pt-2", children: attachments.map((attachment) => (_jsx(ComposerAttachmentPreviewCard, { attachment: attachment, onRemove: handleRemove }, attachment.id))) }));
27
87
  }
28
88
  // ─── Tool Call Fallback ─────────────────────────────────────────────────────
29
- function ToolCallFallback({ toolName, args, result, }) {
30
- const [expanded, setExpanded] = useState(false);
89
+ function ToolCallFallback({ toolName, args, argsText, result, }) {
90
+ const streamRef = useRef(null);
91
+ const thread = useThread();
92
+ const isRunning = result === undefined && thread.isRunning;
93
+ const isAgentCall = toolName.startsWith("agent:");
94
+ // Agent calls default to expanded; regular tools default to collapsed
95
+ const [expanded, setExpanded] = useState(isAgentCall);
96
+ const agentName = isAgentCall ? toolName.slice(6) : null;
97
+ const isAgentError = isAgentCall && result === "Error calling agent";
98
+ // For agent calls, argsText holds the streaming response text
99
+ const agentStreamText = isAgentCall ? (argsText ?? "") : "";
100
+ const hasStreamText = agentStreamText.length > 0;
101
+ const argsStr = isAgentCall
102
+ ? ""
103
+ : Object.entries(args)
104
+ .map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`)
105
+ .join(", ");
106
+ const displayName = isAgentCall
107
+ ? isRunning
108
+ ? `Asking ${agentName}...`
109
+ : isAgentError
110
+ ? `Error asking ${agentName}`
111
+ : `Asked ${agentName}`
112
+ : toolName;
113
+ // Agent calls expand only when there's text to show, toggleable when done
114
+ const canExpand = isAgentCall ? hasStreamText : result !== undefined;
115
+ const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
116
+ // Auto-scroll streaming text to bottom as new content arrives
117
+ useEffect(() => {
118
+ if (isAgentCall && isRunning && streamRef.current) {
119
+ streamRef.current.scrollTop = streamRef.current.scrollHeight;
120
+ }
121
+ }, [agentStreamText, isAgentCall, isRunning]);
122
+ return (_jsxs("div", { className: "my-1 overflow-hidden", children: [_jsxs("button", { onClick: () => canExpand && setExpanded(!isExpanded), className: cn("flex items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-mono w-full text-left overflow-hidden", isRunning
123
+ ? "bg-muted text-muted-foreground"
124
+ : "bg-muted text-muted-foreground hover:bg-accent"), children: [_jsx("span", { className: "shrink-0", children: isRunning ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "h-3 w-3 text-destructive" })) : result !== undefined ? (_jsx(IconCheck, { className: "h-3 w-3 text-emerald-500" })) : (_jsx(IconSquareFilled, { className: "h-3 w-3 text-muted-foreground" })) }), _jsxs("span", { className: "truncate min-w-0", children: [_jsx("span", { className: "font-medium", children: displayName }), argsStr && _jsxs("span", { className: "opacity-60 ml-1", children: ["(", argsStr, ")"] })] }), canExpand && !isRunning && (_jsx(IconChevronDown, { className: cn("ml-auto h-3 w-3 shrink-0 opacity-40", isExpanded && "rotate-180") }))] }), isExpanded && isAgentCall && hasStreamText && (_jsx("div", { ref: streamRef, className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground break-words max-h-48 overflow-y-auto agent-markdown prose prose-sm prose-invert max-w-none", children: _jsx(ReactMarkdown, { children: agentStreamText }) })), isExpanded && !isAgentCall && result !== undefined && (_jsx("div", { className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs font-mono text-muted-foreground whitespace-pre-wrap break-all max-h-48 overflow-y-auto", children: typeof result === "string"
125
+ ? result
126
+ : JSON.stringify(result, null, 2) }))] }));
127
+ }
128
+ // ─── Reconnect Stream Message ───────────────────────────────────────────────
129
+ // Renders the agent's in-progress response during reconnection (outside
130
+ // assistant-ui's runtime). Uses the same visual styling as normal messages.
131
+ function ReconnectStreamToolCall({ toolName, argsText, args, result, }) {
132
+ const streamRef = useRef(null);
31
133
  const isRunning = result === undefined;
32
- const argsStr = Object.entries(args)
33
- .map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`)
34
- .join(", ");
35
- return (_jsxs("div", { className: "my-1", children: [_jsxs("button", { onClick: () => setExpanded(!expanded), className: cn("flex items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-mono w-full text-left", isRunning
36
- ? "bg-amber-500/10 text-amber-400"
37
- : "bg-muted text-muted-foreground hover:bg-accent"), children: [_jsx("span", { className: "shrink-0", children: isRunning ? (_jsx("svg", { className: "h-3 w-3 animate-spin", viewBox: "0 0 24 24", fill: "none", children: _jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "3", strokeDasharray: "31 62" }) })) : (_jsx(CheckIcon, { className: "h-3 w-3 text-emerald-500" })) }), _jsxs("span", { className: "truncate", children: [_jsx("span", { className: "font-medium", children: toolName }), argsStr && _jsxs("span", { className: "opacity-60 ml-1", children: ["(", argsStr, ")"] })] }), !isRunning && (_jsx(ChevronDownIcon, { className: cn("ml-auto h-3 w-3 shrink-0 opacity-40", expanded && "rotate-180") }))] }), expanded && result !== undefined && (_jsx("div", { className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs font-mono text-muted-foreground whitespace-pre-wrap break-all max-h-48 overflow-y-auto", children: typeof result === "string"
134
+ const isAgentCall = toolName.startsWith("agent:");
135
+ const [expanded, setExpanded] = useState(isAgentCall);
136
+ const agentName = isAgentCall ? toolName.slice(6) : null;
137
+ const isAgentError = isAgentCall && result === "Error calling agent";
138
+ const agentStreamText = isAgentCall ? (argsText ?? "") : "";
139
+ const hasStreamText = agentStreamText.length > 0;
140
+ const argsStr = isAgentCall
141
+ ? ""
142
+ : Object.entries(args)
143
+ .map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`)
144
+ .join(", ");
145
+ const displayName = isAgentCall
146
+ ? isRunning
147
+ ? `Asking ${agentName}...`
148
+ : isAgentError
149
+ ? `Error asking ${agentName}`
150
+ : `Asked ${agentName}`
151
+ : toolName;
152
+ const canExpand = isAgentCall ? hasStreamText : result !== undefined;
153
+ const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
154
+ useEffect(() => {
155
+ if (isAgentCall && isRunning && streamRef.current) {
156
+ streamRef.current.scrollTop = streamRef.current.scrollHeight;
157
+ }
158
+ }, [agentStreamText, isAgentCall, isRunning]);
159
+ return (_jsxs("div", { className: "my-1 overflow-hidden", children: [_jsxs("button", { onClick: () => canExpand && setExpanded(!isExpanded), className: cn("flex items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-mono w-full text-left overflow-hidden", isRunning
160
+ ? "bg-muted text-muted-foreground"
161
+ : "bg-muted text-muted-foreground hover:bg-accent"), children: [_jsx("span", { className: "shrink-0", children: isRunning ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "h-3 w-3 text-destructive" })) : (_jsx(IconCheck, { className: "h-3 w-3 text-emerald-500" })) }), _jsxs("span", { className: "truncate min-w-0", children: [_jsx("span", { className: "font-medium", children: displayName }), argsStr && _jsxs("span", { className: "opacity-60 ml-1", children: ["(", argsStr, ")"] })] }), canExpand && !isRunning && (_jsx(IconChevronDown, { className: cn("ml-auto h-3 w-3 shrink-0 opacity-40", isExpanded && "rotate-180") }))] }), isExpanded && isAgentCall && hasStreamText && (_jsx("div", { ref: streamRef, className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground break-words max-h-48 overflow-y-auto agent-markdown prose prose-sm prose-invert max-w-none", children: _jsx(ReactMarkdown, { children: agentStreamText }) })), isExpanded && !isAgentCall && result !== undefined && (_jsx("div", { className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs font-mono text-muted-foreground whitespace-pre-wrap break-all max-h-48 overflow-y-auto", children: typeof result === "string"
38
162
  ? result
39
163
  : JSON.stringify(result, null, 2) }))] }));
40
164
  }
165
+ function ReconnectStreamMessage({ content }) {
166
+ const endRef = useRef(null);
167
+ useEffect(() => {
168
+ endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
169
+ }, [content]);
170
+ return (_jsx("div", { className: "flex justify-start px-4 py-2", children: _jsxs("div", { className: "max-w-[85%] space-y-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [_jsx(IconSparkles, { className: "h-3.5 w-3.5 text-muted-foreground" }), _jsx("span", { className: "text-[10px] text-muted-foreground font-medium uppercase tracking-wide", children: "Agent" })] }), content.map((part, i) => {
171
+ if (part.type === "text") {
172
+ return (_jsx("div", { className: "text-sm leading-relaxed whitespace-pre-wrap break-words", children: part.text }, `reconnect-text-${i}`));
173
+ }
174
+ if (part.type === "tool-call") {
175
+ return (_jsx(ReconnectStreamToolCall, { toolName: part.toolName, argsText: part.argsText, args: part.args, result: part.result }, `reconnect-tool-${i}`));
176
+ }
177
+ return null;
178
+ }), _jsx("div", { ref: endRef })] }) }));
179
+ }
41
180
  // ─── Message Components ─────────────────────────────────────────────────────
181
+ const mentionIconProps = {
182
+ size: 14,
183
+ className: "shrink-0 text-muted-foreground",
184
+ };
185
+ function MentionChipIcon({ icon }) {
186
+ switch (icon) {
187
+ case "folder":
188
+ return _jsx(IconFolder, { ...mentionIconProps });
189
+ case "document":
190
+ return _jsx(IconFileText, { ...mentionIconProps });
191
+ case "form":
192
+ return _jsx(IconCheckbox, { ...mentionIconProps });
193
+ case "email":
194
+ return _jsx(IconMail, { ...mentionIconProps });
195
+ case "user":
196
+ return _jsx(IconUser, { ...mentionIconProps });
197
+ case "deck":
198
+ return _jsx(IconPresentation, { ...mentionIconProps });
199
+ case "agent":
200
+ return _jsx(IconMessageChatbot, { ...mentionIconProps });
201
+ case "file":
202
+ return _jsx(IconFile, { ...mentionIconProps });
203
+ default:
204
+ return _jsx(IconStack2, { ...mentionIconProps });
205
+ }
206
+ }
207
+ // Matches rich mention format: @[label|icon] or plain @word
208
+ const richMentionPattern = /@\[([^\]|]+)\|([^\]]+)\]/g;
209
+ const plainMentionPattern = /((?:^|(?<=\s))@(\w+))/g;
210
+ function UserMessageText({ text }) {
211
+ const parts = [];
212
+ let lastIndex = 0;
213
+ let match;
214
+ let hasRichMentions = false;
215
+ // First try rich mentions (@[label|icon])
216
+ richMentionPattern.lastIndex = 0;
217
+ while ((match = richMentionPattern.exec(text)) !== null) {
218
+ hasRichMentions = true;
219
+ const matchStart = match.index;
220
+ if (matchStart > lastIndex) {
221
+ parts.push(text.slice(lastIndex, matchStart));
222
+ }
223
+ const label = match[1];
224
+ const icon = match[2];
225
+ parts.push(_jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-input bg-muted/50 px-1.5 py-0.5 text-xs font-medium text-foreground align-middle mx-0.5 max-w-[200px] select-all", "data-mention-label": label, children: [_jsx(MentionChipIcon, { icon: icon }), _jsx("span", { className: "truncate", children: label })] }, matchStart));
226
+ lastIndex = matchStart + match[0].length;
227
+ }
228
+ if (hasRichMentions) {
229
+ if (lastIndex < text.length) {
230
+ parts.push(text.slice(lastIndex));
231
+ }
232
+ return _jsx(_Fragment, { children: parts });
233
+ }
234
+ // Fallback: plain @word mentions (for older messages)
235
+ plainMentionPattern.lastIndex = 0;
236
+ while ((match = plainMentionPattern.exec(text)) !== null) {
237
+ const matchStart = match.index;
238
+ if (matchStart > lastIndex) {
239
+ parts.push(text.slice(lastIndex, matchStart));
240
+ }
241
+ const mentionName = match[2];
242
+ parts.push(_jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-input bg-muted/50 px-1.5 py-0.5 text-xs font-medium text-foreground align-middle mx-0.5 select-all", "data-mention-label": mentionName, children: ["@", mentionName] }, matchStart));
243
+ lastIndex = matchStart + match[0].length;
244
+ }
245
+ if (lastIndex < text.length) {
246
+ parts.push(text.slice(lastIndex));
247
+ }
248
+ return _jsx(_Fragment, { children: parts.length > 0 ? parts : text });
249
+ }
42
250
  function UserMessage() {
43
- return (_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "max-w-[85%] rounded-lg bg-accent text-foreground px-3 py-2 text-sm leading-relaxed whitespace-pre-wrap break-words", children: _jsx(MessagePrimitive.Parts, { components: {
44
- Text: ({ text }) => _jsx(_Fragment, { children: text }),
45
- } }) }) }));
251
+ const [expanded, setExpanded] = useState(false);
252
+ const [isExpandable, setIsExpandable] = useState(false);
253
+ const contentRef = useRef(null);
254
+ useEffect(() => {
255
+ const el = contentRef.current;
256
+ if (!el)
257
+ return;
258
+ const measure = () => {
259
+ setIsExpandable(el.scrollHeight > 200);
260
+ };
261
+ measure();
262
+ const observer = new ResizeObserver(measure);
263
+ observer.observe(el);
264
+ return () => observer.disconnect();
265
+ }, []);
266
+ return (_jsx("div", { className: "flex justify-end", style: { contentVisibility: "auto" }, children: _jsxs("div", { className: "max-w-[85%]", children: [_jsxs("div", { className: "relative rounded-lg bg-accent px-3 py-2 text-sm leading-relaxed text-foreground", onCopy: (e) => {
267
+ const selection = window.getSelection();
268
+ if (!selection || selection.rangeCount === 0)
269
+ return;
270
+ const fragment = selection.getRangeAt(0).cloneContents();
271
+ const mentions = fragment.querySelectorAll("[data-mention-label]");
272
+ if (mentions.length === 0)
273
+ return;
274
+ e.preventDefault();
275
+ mentions.forEach((el) => {
276
+ el.textContent = `@${el.getAttribute("data-mention-label")}`;
277
+ });
278
+ const div = document.createElement("div");
279
+ div.appendChild(fragment);
280
+ e.clipboardData.setData("text/plain", div.textContent || "");
281
+ }, children: [_jsx("div", { ref: contentRef, className: cn("whitespace-pre-wrap break-words", !expanded && isExpandable && "max-h-[200px] overflow-hidden"), children: _jsx(MessagePrimitive.Parts, { components: {
282
+ Text: UserMessageText,
283
+ } }) }), !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"] }))] }) }));
46
284
  }
47
285
  function AssistantMessage() {
48
286
  const [copied, setCopied] = useState(false);
49
287
  const messageRuntime = useMessageRuntime();
288
+ const thread = useThread();
289
+ const msg = messageRuntime.getState();
290
+ const isLast = thread.messages.length > 0 &&
291
+ thread.messages[thread.messages.length - 1].id === msg.id;
292
+ const isComplete = !isLast || !thread.isRunning;
50
293
  const handleCopy = useCallback(() => {
51
- const msg = messageRuntime.getState();
52
- const text = msg.content
294
+ const m = messageRuntime.getState();
295
+ const text = m.content
53
296
  .filter((p) => p.type === "text")
54
297
  .map((p) => p.text)
55
298
  .join("\n");
@@ -57,16 +300,23 @@ function AssistantMessage() {
57
300
  setCopied(true);
58
301
  setTimeout(() => setCopied(false), 2000);
59
302
  }, [messageRuntime]);
60
- return (_jsxs("div", { className: "group relative", children: [_jsx("div", { className: "max-w-[95%] text-sm leading-relaxed text-foreground", children: _jsx(MessagePrimitive.Parts, { components: {
61
- Text: ({ text }) => (_jsx("div", { className: "whitespace-pre-wrap break-words", children: text })),
303
+ 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: {
304
+ Text: MarkdownText,
62
305
  tools: {
63
306
  Fallback: ToolCallFallback,
64
307
  },
65
- } }) }), _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-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: copied ? (_jsx(CheckIcon, { className: "h-3.5 w-3.5" })) : (_jsx(CopyIcon, { className: "h-3.5 w-3.5" })) }) })] }));
308
+ } }) }), 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" })) }) }))] }));
66
309
  }
67
310
  // ─── Thinking Indicator ─────────────────────────────────────────────────────
68
311
  function ThinkingIndicator() {
69
- return (_jsxs("div", { className: "flex items-center gap-1.5 text-muted-foreground py-2", children: [_jsx("div", { className: "flex gap-1", children: [0, 1, 2].map((i) => (_jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current opacity-40 animate-bounce", style: { animationDelay: `${i * 0.15}s` } }, i))) }), _jsx("span", { className: "text-xs", children: "Thinking..." })] }));
312
+ const [dots, setDots] = useState(1);
313
+ useEffect(() => {
314
+ const interval = setInterval(() => {
315
+ setDots((d) => (d % 3) + 1);
316
+ }, 400);
317
+ return () => clearInterval(interval);
318
+ }, []);
319
+ return (_jsx("div", { className: "flex items-center text-muted-foreground", children: _jsxs("span", { className: "text-xs", children: ["Thinking", ".".repeat(dots)] }) }));
70
320
  }
71
321
  // ─── API Key Setup Card ─────────────────────────────────────────────────────
72
322
  function ApiKeySetupCard({ apiUrl }) {
@@ -100,9 +350,9 @@ function ApiKeySetupCard({ apiUrl }) {
100
350
  }
101
351
  };
102
352
  if (saved) {
103
- 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(CheckIcon, { className: "h-4 w-4" }), "API key saved. Reloading..."] }) }));
353
+ 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..."] }) }));
104
354
  }
105
- 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(SparklesIcon, { 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: "Add an Anthropic API key to enable the agent" })] })] }), _jsxs("div", { className: "space-y-3", children: [_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) => {
355
+ 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(IconSparkles, { 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: "Add an Anthropic API key to enable the agent" })] })] }), _jsxs("div", { className: "space-y-3", children: [_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) => {
106
356
  setApiKey(e.target.value);
107
357
  setError(null);
108
358
  }, onKeyDown: (e) => {
@@ -110,56 +360,388 @@ function ApiKeySetupCard({ apiUrl }) {
110
360
  handleSave();
111
361
  }, 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" })] })] }));
112
362
  }
113
- // ─── Main Component ─────────────────────────────────────────────────────────
114
- // ─── Terminal Icon ──────────────────────────────────────────────────────────
115
- function TerminalIcon({ className }) {
116
- return (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", className: className, children: [_jsx("polyline", { points: "4 17 10 11 4 5" }), _jsx("line", { x1: "12", y1: "19", x2: "20", y2: "19" })] }));
363
+ export const CHAT_STORAGE_PREFIX = "agent-chat:";
364
+ /** Remove persisted chat for a given tabId (or "default"). */
365
+ export function clearChatStorage(tabId) {
366
+ try {
367
+ sessionStorage.removeItem(`${CHAT_STORAGE_PREFIX}${tabId || "default"}`);
368
+ }
369
+ catch { }
117
370
  }
118
- const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, showHeader = true, showDevHint = true, onSwitchToCli, className, apiUrl = "/api/agent-chat", }, ref) {
371
+ // Re-export for backwards compatibility
372
+ import { extractThreadMeta } from "../agent/thread-data-builder.js";
373
+ export { extractThreadMeta };
374
+ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, showHeader = true, onSwitchToCli, className, apiUrl, tabId, threadId, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, isNewThread, }, ref) {
119
375
  const scrollRef = useRef(null);
120
376
  const thread = useThread();
121
377
  const threadRuntime = useThreadRuntime();
122
378
  const isRunning = thread.isRunning;
123
379
  const messages = thread.messages;
124
380
  const [missingApiKey, setMissingApiKey] = useState(false);
381
+ const [queuedMessages, setQueuedMessages] = useState([]);
382
+ const [showContinue, setShowContinue] = useState(false);
383
+ const [isReconnecting, setIsReconnecting] = useState(false);
384
+ const [reconnectContent, setReconnectContent] = useState([]);
385
+ const wasRunningRef = useRef(false);
386
+ const tiptapRef = useRef(null);
387
+ // ─── Chat persistence ──────────────────────────────────────────────
388
+ const hasRestoredRef = useRef(false);
389
+ const [isRestoring, setIsRestoring] = useState(!!threadId && !isNewThread);
390
+ const onSaveThreadRef = useRef(onSaveThread);
391
+ onSaveThreadRef.current = onSaveThread;
392
+ const onGenerateTitleRef = useRef(onGenerateTitle);
393
+ onGenerateTitleRef.current = onGenerateTitle;
394
+ const titleGeneratedRef = useRef(false);
395
+ // Restore messages from server on mount (when threadId is set)
396
+ useEffect(() => {
397
+ if (hasRestoredRef.current)
398
+ return;
399
+ hasRestoredRef.current = true;
400
+ if (threadId) {
401
+ // Load from server
402
+ (async () => {
403
+ try {
404
+ const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}`);
405
+ if (!res.ok)
406
+ return;
407
+ const data = await res.json();
408
+ if (data.threadData) {
409
+ const repo = typeof data.threadData === "string"
410
+ ? JSON.parse(data.threadData)
411
+ : data.threadData;
412
+ if (repo?.messages?.length > 0) {
413
+ titleGeneratedRef.current = true; // Don't re-generate for restored threads
414
+ threadRuntime.import(repo);
415
+ }
416
+ }
417
+ // Also skip title generation if thread already has a title
418
+ if (data.title) {
419
+ titleGeneratedRef.current = true;
420
+ }
421
+ // Check if there's an active run for this thread (e.g. after hot reload)
422
+ try {
423
+ const runRes = await fetch(`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`);
424
+ if (runRes.ok) {
425
+ const runInfo = await runRes.json();
426
+ // Agent is still running — subscribe to live SSE stream
427
+ setIsReconnecting(true);
428
+ setReconnectContent([]);
429
+ const streamReconnect = async () => {
430
+ try {
431
+ const sseRes = await fetch(`${apiUrl}/runs/${encodeURIComponent(runInfo.runId)}/events?after=0`);
432
+ if (sseRes.ok && sseRes.body) {
433
+ const content = [];
434
+ const toolCallCounter = { value: 0 };
435
+ // Throttle React state updates via requestAnimationFrame
436
+ let rafPending = false;
437
+ let latestSnapshot = [];
438
+ const scheduleUpdate = (snapshot) => {
439
+ latestSnapshot = snapshot;
440
+ if (!rafPending) {
441
+ rafPending = true;
442
+ requestAnimationFrame(() => {
443
+ rafPending = false;
444
+ setReconnectContent(latestSnapshot);
445
+ });
446
+ }
447
+ };
448
+ await readSSEStreamRaw(sseRes.body, content, toolCallCounter, tabId, scheduleUpdate);
449
+ // Final update with complete content
450
+ setReconnectContent([...content]);
451
+ }
452
+ }
453
+ catch {
454
+ // Stream error — fall through to re-fetch
455
+ }
456
+ // Run finished — re-fetch thread data from server
457
+ // (server now persists assistant response on completion)
458
+ try {
459
+ const refreshRes = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}`);
460
+ if (refreshRes.ok) {
461
+ const refreshData = await refreshRes.json();
462
+ if (refreshData.threadData) {
463
+ const repo = typeof refreshData.threadData === "string"
464
+ ? JSON.parse(refreshData.threadData)
465
+ : refreshData.threadData;
466
+ if (repo?.messages?.length > 0) {
467
+ threadRuntime.import(repo);
468
+ }
469
+ }
470
+ }
471
+ }
472
+ catch { }
473
+ setReconnectContent([]);
474
+ setIsReconnecting(false);
475
+ };
476
+ streamReconnect();
477
+ }
478
+ }
479
+ catch {
480
+ // No active run — nothing to reconnect to
481
+ }
482
+ }
483
+ catch {
484
+ // Start fresh
485
+ }
486
+ finally {
487
+ setIsRestoring(false);
488
+ }
489
+ })();
490
+ }
491
+ else {
492
+ // Legacy: restore from sessionStorage
493
+ const storageKey = `${CHAT_STORAGE_PREFIX}${tabId || "default"}`;
494
+ try {
495
+ const saved = sessionStorage.getItem(storageKey);
496
+ if (saved) {
497
+ const repo = JSON.parse(saved);
498
+ if (repo?.messages?.length > 0) {
499
+ threadRuntime.import(repo);
500
+ }
501
+ }
502
+ }
503
+ catch { }
504
+ setIsRestoring(false);
505
+ }
506
+ }, [threadId, tabId, apiUrl, threadRuntime]);
507
+ // Generate a title when the first user message is sent
508
+ useEffect(() => {
509
+ if (!hasRestoredRef.current)
510
+ return;
511
+ if (titleGeneratedRef.current)
512
+ return;
513
+ if (messages.length === 0)
514
+ return;
515
+ const firstUserMsg = messages.find((m) => m.role === "user");
516
+ if (!firstUserMsg)
517
+ return;
518
+ // Extract text from the first user message
519
+ const text = "content" in firstUserMsg
520
+ ? Array.isArray(firstUserMsg.content)
521
+ ? firstUserMsg.content
522
+ .filter((p) => p.type === "text")
523
+ .map((p) => p.text)
524
+ .join(" ")
525
+ : typeof firstUserMsg.content === "string"
526
+ ? firstUserMsg.content
527
+ : ""
528
+ : "";
529
+ if (!text.trim())
530
+ return;
531
+ titleGeneratedRef.current = true;
532
+ onGenerateTitleRef.current?.(text.trim());
533
+ }, [messages]);
534
+ // Save title/preview eagerly when messages change (even while agent is running)
535
+ // so that the history popover shows meaningful labels immediately.
536
+ const savedTitleRef = useRef("");
537
+ useEffect(() => {
538
+ if (!hasRestoredRef.current)
539
+ return;
540
+ if (messages.length === 0)
541
+ return;
542
+ if (!threadId || !onSaveThreadRef.current)
543
+ return;
544
+ const repo = threadRuntime.export();
545
+ const { title, preview } = extractThreadMeta(repo);
546
+ // Save full thread data while running so hot reloads don't lose messages
547
+ if (isRunning && title && title !== savedTitleRef.current) {
548
+ savedTitleRef.current = title;
549
+ onSaveThreadRef.current({
550
+ threadData: JSON.stringify(repo),
551
+ title,
552
+ preview,
553
+ messageCount: messages.length,
554
+ });
555
+ }
556
+ }, [messages, isRunning, threadId, threadRuntime]);
557
+ // Persist full thread data after each completed response
558
+ useEffect(() => {
559
+ if (!hasRestoredRef.current)
560
+ return;
561
+ if (isRunning)
562
+ return;
563
+ if (messages.length === 0)
564
+ return;
565
+ const repo = threadRuntime.export();
566
+ if (threadId && onSaveThreadRef.current) {
567
+ // Save to server via the hook callback
568
+ const { title, preview } = extractThreadMeta(repo);
569
+ savedTitleRef.current = title;
570
+ onSaveThreadRef.current({
571
+ threadData: JSON.stringify(repo),
572
+ title,
573
+ preview,
574
+ messageCount: messages.length,
575
+ });
576
+ }
577
+ else {
578
+ // Legacy: save to sessionStorage
579
+ const storageKey = `${CHAT_STORAGE_PREFIX}${tabId || "default"}`;
580
+ try {
581
+ sessionStorage.setItem(storageKey, JSON.stringify(repo));
582
+ }
583
+ catch { }
584
+ }
585
+ }, [messages, isRunning, threadId, tabId, threadRuntime]);
586
+ useEffect(() => {
587
+ onMessageCountChange?.(messages.length);
588
+ }, [messages.length, onMessageCountChange]);
125
589
  // Listen for missing API key events from the adapter
126
590
  useEffect(() => {
127
591
  const handler = () => setMissingApiKey(true);
128
592
  window.addEventListener("agent-chat:missing-api-key", handler);
129
593
  return () => window.removeEventListener("agent-chat:missing-api-key", handler);
130
594
  }, []);
595
+ // Listen for loop-limit events from the adapter
596
+ useEffect(() => {
597
+ const handler = (e) => {
598
+ const detail = e.detail;
599
+ if (!tabId || detail?.tabId === tabId) {
600
+ setShowContinue(true);
601
+ }
602
+ };
603
+ window.addEventListener("agent-chat:loop-limit", handler);
604
+ return () => window.removeEventListener("agent-chat:loop-limit", handler);
605
+ }, [tabId]);
606
+ // Auto-dequeue: when agent finishes running, send the next queued message
607
+ useEffect(() => {
608
+ if (wasRunningRef.current && !isRunning && queuedMessages.length > 0) {
609
+ const [next, ...rest] = queuedMessages;
610
+ setQueuedMessages(rest);
611
+ // Small delay to let the runtime settle after completion
612
+ setTimeout(() => {
613
+ const content = [{ type: "text", text: next.text }];
614
+ if (next.images) {
615
+ for (const img of next.images) {
616
+ content.push({ type: "image", image: img });
617
+ }
618
+ }
619
+ threadRuntime.append({
620
+ role: "user",
621
+ content,
622
+ ...(next.references && next.references.length > 0
623
+ ? { runConfig: { custom: { references: next.references } } }
624
+ : {}),
625
+ });
626
+ }, 100);
627
+ }
628
+ wasRunningRef.current = isRunning;
629
+ }, [isRunning, queuedMessages, threadRuntime]);
630
+ const addToQueue = useCallback((text, images, references) => {
631
+ setShowContinue(false);
632
+ if (isRunning) {
633
+ setQueuedMessages((prev) => [...prev, { text, images, references }]);
634
+ }
635
+ else {
636
+ const content = [{ type: "text", text }];
637
+ if (images) {
638
+ for (const img of images) {
639
+ content.push({ type: "image", image: img });
640
+ }
641
+ }
642
+ threadRuntime.append({ role: "user", content });
643
+ }
644
+ }, [isRunning, threadRuntime]);
131
645
  // Expose imperative handle
132
646
  useImperativeHandle(ref, () => ({
133
647
  sendMessage(text) {
134
- threadRuntime.append({
135
- role: "user",
136
- content: [{ type: "text", text }],
137
- });
648
+ addToQueue(text);
649
+ },
650
+ queueMessage(text) {
651
+ addToQueue(text);
138
652
  },
139
653
  isRunning() {
140
654
  return thread.isRunning;
141
655
  },
142
- }), [threadRuntime, thread.isRunning]);
143
- // Auto-scroll on new messages
656
+ focusComposer() {
657
+ tiptapRef.current?.focus();
658
+ },
659
+ }), [addToQueue, thread.isRunning]);
660
+ // Track whether user has scrolled away from bottom
661
+ const isNearBottomRef = useRef(true);
662
+ const [showScrollToBottom, setShowScrollToBottom] = useState(false);
144
663
  useEffect(() => {
664
+ const el = scrollRef.current;
665
+ if (!el)
666
+ return;
667
+ function onScroll() {
668
+ if (!el)
669
+ return;
670
+ const threshold = 40;
671
+ const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < threshold;
672
+ isNearBottomRef.current = nearBottom;
673
+ setShowScrollToBottom(!nearBottom && messages.length > 0);
674
+ }
675
+ el.addEventListener("scroll", onScroll, { passive: true });
676
+ return () => el.removeEventListener("scroll", onScroll);
677
+ }, [messages.length]);
678
+ const scrollToBottom = useCallback(() => {
145
679
  const el = scrollRef.current;
146
680
  if (el) {
147
681
  el.scrollTop = el.scrollHeight;
682
+ isNearBottomRef.current = true;
683
+ setShowScrollToBottom(false);
684
+ }
685
+ }, []);
686
+ // Scroll to bottom when a restored thread finishes loading
687
+ const wasRestoringRef = useRef(isRestoring);
688
+ useEffect(() => {
689
+ if (wasRestoringRef.current && !isRestoring) {
690
+ requestAnimationFrame(() => {
691
+ scrollToBottom();
692
+ });
693
+ }
694
+ wasRestoringRef.current = isRestoring;
695
+ }, [isRestoring, scrollToBottom]);
696
+ // Auto-scroll on new messages or queued messages (only if near bottom)
697
+ useEffect(() => {
698
+ const el = scrollRef.current;
699
+ if (el && isNearBottomRef.current) {
700
+ el.scrollTop = el.scrollHeight;
148
701
  }
149
- }, [messages, isRunning]);
150
- return (_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" }), _jsxs("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(TerminalIcon, { className: "h-3.5 w-3.5" }), "CLI"] })), messages.length > 0 && (_jsx("button", { onClick: () => window.location.reload(), className: "text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", children: "Clear" }))] })] })), _jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto min-h-0", children: missingApiKey ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(ApiKeySetupCard, { apiUrl: apiUrl }) })) : messages.length === 0 ? (_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(SparklesIcon, { 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: () => {
702
+ }, [messages, queuedMessages]);
703
+ // Continuous auto-scroll while streaming (only if near bottom)
704
+ useEffect(() => {
705
+ if (!isRunning)
706
+ return;
707
+ const el = scrollRef.current;
708
+ if (!el)
709
+ return;
710
+ const interval = setInterval(() => {
711
+ if (isNearBottomRef.current) {
712
+ el.scrollTop = el.scrollHeight;
713
+ }
714
+ }, 100);
715
+ return () => clearInterval(interval);
716
+ }, [isRunning]);
717
+ return (_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: missingApiKey ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(ApiKeySetupCard, { 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(IconSparkles, { 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: () => {
151
718
  threadRuntime.append({
152
719
  role: "user",
153
720
  content: [{ type: "text", text: suggestion }],
154
721
  });
155
- }, 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))) })), showDevHint && onSwitchToCli && (_jsxs("p", { className: "text-xs text-muted-foreground/60 text-center max-w-[260px] mt-2", children: ["In dev mode you can also use the", " ", _jsx("button", { onClick: onSwitchToCli, className: "underline hover:text-muted-foreground", children: "CLI terminal" }), " ", "for full Claude Code capabilities."] }))] })) : (_jsxs("div", { className: "flex flex-col gap-4 px-4 py-4", children: [_jsx(ThreadPrimitive.Messages, { components: {
722
+ }, 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: "flex flex-col gap-4 px-4 py-4", children: [_jsx(ThreadPrimitive.Messages, { components: {
156
723
  UserMessage,
157
724
  AssistantMessage,
158
- } }), isRunning && _jsx(ThinkingIndicator, {})] })) }), _jsx("div", { className: "shrink-0 border-t border-border px-3 py-3", children: _jsxs(ComposerPrimitive.Root, { className: "flex items-center gap-2 rounded-lg border border-input bg-background px-3 py-2 focus-within:ring-1 focus-within:ring-ring", children: [_jsx(ComposerPrimitive.Input, { placeholder: "Message agent...", submitMode: "enter", cancelOnEscape: true, className: "flex-1 resize-none bg-transparent text-sm text-foreground placeholder:text-muted-foreground outline-none leading-relaxed min-h-[24px] max-h-[120px]", rows: 1 }), isRunning ? (_jsx(ComposerPrimitive.Cancel, { asChild: true, children: _jsx("button", { className: "shrink-0 flex h-8 w-8 items-center justify-center rounded-md bg-destructive text-destructive-foreground hover:opacity-90", children: _jsx(StopIcon, { className: "h-3.5 w-3.5" }) }) })) : (_jsx(ComposerPrimitive.Send, { asChild: true, children: _jsx("button", { className: "shrink-0 flex h-8 w-8 items-center justify-center rounded-md bg-primary text-primary-foreground hover:opacity-90 disabled:opacity-30 disabled:cursor-not-allowed", children: _jsx(SendIcon, { className: "h-3.5 w-3.5" }) }) }))] }) })] }));
725
+ } }), showContinue && !isRunning && (_jsx("div", { className: "flex justify-center py-2", children: _jsx("button", { type: "button", onClick: () => {
726
+ setShowContinue(false);
727
+ addToQueue("Continue from where you left off.");
728
+ }, className: "rounded-lg border border-border bg-background px-4 py-2 text-sm font-medium text-foreground hover:bg-accent", children: "Continue" }) })), isRunning && _jsx(ThinkingIndicator, {}), isReconnecting && !isRunning && reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), isReconnecting && !isRunning && reconnectContent.length === 0 && (_jsx(ThinkingIndicator, {})), queuedMessages.map((msg, i) => (_jsx("div", { className: "flex justify-end", children: _jsxs("div", { className: "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"] }), msg.text, 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))) }))] }) }, `queued-${i}`)))] })) }), 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: "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
729
+ ? queuedMessages.length > 0
730
+ ? `${queuedMessages.length} queued — type another...`
731
+ : "Queue a message..."
732
+ : undefined, onSubmit: isRunning
733
+ ? (text, references) => addToQueue(text, undefined, references.length > 0 ? references : undefined)
734
+ : undefined, actionButton: isRunning ? (_jsx("button", { onClick: () => threadRuntime.cancelRun(), className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-primary text-primary-foreground hover:opacity-90", title: "Stop generating", children: _jsx(IconPlayerStop, { className: "h-3.5 w-3.5" }) })) : undefined })] }) })] }));
159
735
  });
160
- export const AssistantChat = forwardRef(function AssistantChat({ apiUrl, tabId, ...props }, ref) {
161
- const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId }), [apiUrl, tabId]);
162
- const runtime = useLocalRuntime(adapter);
163
- return (_jsx(AssistantRuntimeProvider, { runtime: runtime, children: _jsx(ThreadPrimitive.Root, { className: "flex flex-1 flex-col h-full min-h-0", children: _jsx(AssistantChatInner, { ref: ref, ...props, apiUrl: apiUrl }) }) }));
736
+ export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = "/_agent-native/agent-chat", tabId, threadId, ...props }, ref) {
737
+ const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId, threadId }), [apiUrl, tabId, threadId]);
738
+ const attachmentAdapter = useMemo(() => new CompositeAttachmentAdapter([
739
+ new SimpleImageAttachmentAdapter(),
740
+ new SimpleTextAttachmentAdapter(),
741
+ ]), []);
742
+ const runtime = useLocalRuntime(adapter, {
743
+ adapters: { attachments: attachmentAdapter },
744
+ });
745
+ return (_jsx(AssistantRuntimeProvider, { runtime: runtime, children: _jsx(ThreadPrimitive.Root, { className: "flex flex-1 flex-col h-full min-h-0 overflow-x-hidden", children: _jsx(AssistantChatInner, { ref: ref, ...props, apiUrl: apiUrl, tabId: tabId, threadId: threadId }) }) }));
164
746
  });
165
747
  //# sourceMappingURL=AssistantChat.js.map