@agent-native/core 0.7.1 → 0.7.2

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 (242) hide show
  1. package/dist/action.d.ts +8 -0
  2. package/dist/action.d.ts.map +1 -1
  3. package/dist/action.js +18 -0
  4. package/dist/action.js.map +1 -1
  5. package/dist/agent/production-agent.d.ts +9 -0
  6. package/dist/agent/production-agent.d.ts.map +1 -1
  7. package/dist/agent/production-agent.js +148 -36
  8. package/dist/agent/production-agent.js.map +1 -1
  9. package/dist/agent/run-manager.d.ts.map +1 -1
  10. package/dist/agent/run-manager.js +20 -1
  11. package/dist/agent/run-manager.js.map +1 -1
  12. package/dist/agent/run-store.d.ts +14 -0
  13. package/dist/agent/run-store.d.ts.map +1 -1
  14. package/dist/agent/run-store.js +63 -6
  15. package/dist/agent/run-store.js.map +1 -1
  16. package/dist/agent/types.d.ts +2 -0
  17. package/dist/agent/types.d.ts.map +1 -1
  18. package/dist/cli/create.js +1 -1
  19. package/dist/cli/create.js.map +1 -1
  20. package/dist/cli/setup-agents.d.ts.map +1 -1
  21. package/dist/cli/setup-agents.js +0 -2
  22. package/dist/cli/setup-agents.js.map +1 -1
  23. package/dist/cli/templates-meta.d.ts +52 -0
  24. package/dist/cli/templates-meta.d.ts.map +1 -0
  25. package/dist/cli/templates-meta.js +165 -0
  26. package/dist/cli/templates-meta.js.map +1 -0
  27. package/dist/client/AgentPanel.d.ts +5 -1
  28. package/dist/client/AgentPanel.d.ts.map +1 -1
  29. package/dist/client/AgentPanel.js +279 -30
  30. package/dist/client/AgentPanel.js.map +1 -1
  31. package/dist/client/AssistantChat.d.ts +2 -1
  32. package/dist/client/AssistantChat.d.ts.map +1 -1
  33. package/dist/client/AssistantChat.js +172 -40
  34. package/dist/client/AssistantChat.js.map +1 -1
  35. package/dist/client/ConnectBuilderCard.d.ts +21 -0
  36. package/dist/client/ConnectBuilderCard.d.ts.map +1 -0
  37. package/dist/client/ConnectBuilderCard.js +196 -0
  38. package/dist/client/ConnectBuilderCard.js.map +1 -0
  39. package/dist/client/FeedbackButton.d.ts +15 -0
  40. package/dist/client/FeedbackButton.d.ts.map +1 -0
  41. package/dist/client/FeedbackButton.js +72 -0
  42. package/dist/client/FeedbackButton.js.map +1 -0
  43. package/dist/client/IframeEmbed.d.ts +17 -0
  44. package/dist/client/IframeEmbed.d.ts.map +1 -0
  45. package/dist/client/IframeEmbed.js +108 -0
  46. package/dist/client/IframeEmbed.js.map +1 -0
  47. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  48. package/dist/client/MultiTabAssistantChat.js +34 -7
  49. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  50. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  51. package/dist/client/agent-chat-adapter.js +34 -15
  52. package/dist/client/agent-chat-adapter.js.map +1 -1
  53. package/dist/client/agent-chat.d.ts +6 -0
  54. package/dist/client/agent-chat.d.ts.map +1 -1
  55. package/dist/client/agent-chat.js +7 -0
  56. package/dist/client/agent-chat.js.map +1 -1
  57. package/dist/client/composer/MentionPopover.d.ts.map +1 -1
  58. package/dist/client/composer/MentionPopover.js +27 -24
  59. package/dist/client/composer/MentionPopover.js.map +1 -1
  60. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  61. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  62. package/dist/client/composer/TiptapComposer.js +21 -4
  63. package/dist/client/composer/TiptapComposer.js.map +1 -1
  64. package/dist/client/embed.d.ts +28 -0
  65. package/dist/client/embed.d.ts.map +1 -0
  66. package/dist/client/embed.js +50 -0
  67. package/dist/client/embed.js.map +1 -0
  68. package/dist/client/index.d.ts +4 -1
  69. package/dist/client/index.d.ts.map +1 -1
  70. package/dist/client/index.js +4 -1
  71. package/dist/client/index.js.map +1 -1
  72. package/dist/client/integrations/IntegrationsPanel.js +2 -2
  73. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  74. package/dist/client/onboarding/OnboardingBanner.js +2 -2
  75. package/dist/client/onboarding/OnboardingBanner.js.map +1 -1
  76. package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -1
  77. package/dist/client/onboarding/OnboardingPanel.js +139 -52
  78. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  79. package/dist/client/onboarding/SetupButton.d.ts.map +1 -1
  80. package/dist/client/onboarding/SetupButton.js +13 -3
  81. package/dist/client/onboarding/SetupButton.js.map +1 -1
  82. package/dist/client/org/TeamPage.d.ts.map +1 -1
  83. package/dist/client/org/TeamPage.js +12 -7
  84. package/dist/client/org/TeamPage.js.map +1 -1
  85. package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
  86. package/dist/client/resources/ResourceEditor.js +57 -2
  87. package/dist/client/resources/ResourceEditor.js.map +1 -1
  88. package/dist/client/resources/ResourceTree.d.ts +5 -1
  89. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  90. package/dist/client/resources/ResourceTree.js +17 -10
  91. package/dist/client/resources/ResourceTree.js.map +1 -1
  92. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  93. package/dist/client/resources/ResourcesPanel.js +12 -10
  94. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  95. package/dist/client/settings/AgentsSection.d.ts.map +1 -1
  96. package/dist/client/settings/AgentsSection.js +6 -3
  97. package/dist/client/settings/AgentsSection.js.map +1 -1
  98. package/dist/client/settings/ComingSoonSection.js +1 -1
  99. package/dist/client/settings/ComingSoonSection.js.map +1 -1
  100. package/dist/client/settings/LLMSection.d.ts.map +1 -1
  101. package/dist/client/settings/LLMSection.js +1 -1
  102. package/dist/client/settings/LLMSection.js.map +1 -1
  103. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  104. package/dist/client/settings/SettingsPanel.js +16 -23
  105. package/dist/client/settings/SettingsPanel.js.map +1 -1
  106. package/dist/client/settings/SettingsSection.js +2 -2
  107. package/dist/client/settings/SettingsSection.js.map +1 -1
  108. package/dist/client/settings/UsageSection.d.ts +2 -0
  109. package/dist/client/settings/UsageSection.d.ts.map +1 -0
  110. package/dist/client/settings/UsageSection.js +70 -0
  111. package/dist/client/settings/UsageSection.js.map +1 -0
  112. package/dist/client/use-action.d.ts.map +1 -1
  113. package/dist/client/use-action.js +67 -4
  114. package/dist/client/use-action.js.map +1 -1
  115. package/dist/client/use-db-sync.d.ts +25 -2
  116. package/dist/client/use-db-sync.d.ts.map +1 -1
  117. package/dist/client/use-db-sync.js +62 -1
  118. package/dist/client/use-db-sync.js.map +1 -1
  119. package/dist/client/use-dev-mode.d.ts.map +1 -1
  120. package/dist/client/use-dev-mode.js +16 -1
  121. package/dist/client/use-dev-mode.js.map +1 -1
  122. package/dist/db/client.d.ts +12 -0
  123. package/dist/db/client.d.ts.map +1 -1
  124. package/dist/db/client.js +89 -2
  125. package/dist/db/client.js.map +1 -1
  126. package/dist/db/create-get-db.d.ts +11 -0
  127. package/dist/db/create-get-db.d.ts.map +1 -1
  128. package/dist/db/create-get-db.js +47 -3
  129. package/dist/db/create-get-db.js.map +1 -1
  130. package/dist/db/migrations.d.ts.map +1 -1
  131. package/dist/db/migrations.js +62 -5
  132. package/dist/db/migrations.js.map +1 -1
  133. package/dist/index.d.ts +1 -0
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +2 -0
  136. package/dist/index.js.map +1 -1
  137. package/dist/jobs/scheduler.d.ts.map +1 -1
  138. package/dist/jobs/scheduler.js +7 -2
  139. package/dist/jobs/scheduler.js.map +1 -1
  140. package/dist/oauth-tokens/google-refresh.d.ts +31 -0
  141. package/dist/oauth-tokens/google-refresh.d.ts.map +1 -0
  142. package/dist/oauth-tokens/google-refresh.js +115 -0
  143. package/dist/oauth-tokens/google-refresh.js.map +1 -0
  144. package/dist/oauth-tokens/index.d.ts +1 -0
  145. package/dist/oauth-tokens/index.d.ts.map +1 -1
  146. package/dist/oauth-tokens/index.js +1 -0
  147. package/dist/oauth-tokens/index.js.map +1 -1
  148. package/dist/onboarding/default-steps.d.ts.map +1 -1
  149. package/dist/onboarding/default-steps.js +57 -18
  150. package/dist/onboarding/default-steps.js.map +1 -1
  151. package/dist/org/context.js +1 -1
  152. package/dist/org/handlers.d.ts.map +1 -1
  153. package/dist/org/handlers.js +35 -10
  154. package/dist/org/handlers.js.map +1 -1
  155. package/dist/org/plugin.d.ts.map +1 -1
  156. package/dist/org/plugin.js +37 -22
  157. package/dist/org/plugin.js.map +1 -1
  158. package/dist/resources/handlers.js +1 -1
  159. package/dist/resources/handlers.js.map +1 -1
  160. package/dist/resources/metadata.d.ts.map +1 -1
  161. package/dist/resources/metadata.js +2 -2
  162. package/dist/resources/metadata.js.map +1 -1
  163. package/dist/resources/store.d.ts.map +1 -1
  164. package/dist/resources/store.js +27 -1
  165. package/dist/resources/store.js.map +1 -1
  166. package/dist/scripts/db/patch.d.ts.map +1 -1
  167. package/dist/scripts/db/patch.js +273 -11
  168. package/dist/scripts/db/patch.js.map +1 -1
  169. package/dist/server/action-discovery.d.ts.map +1 -1
  170. package/dist/server/action-discovery.js +2 -0
  171. package/dist/server/action-discovery.js.map +1 -1
  172. package/dist/server/action-routes.d.ts.map +1 -1
  173. package/dist/server/action-routes.js +26 -0
  174. package/dist/server/action-routes.js.map +1 -1
  175. package/dist/server/agent-chat-plugin.d.ts +12 -0
  176. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  177. package/dist/server/agent-chat-plugin.js +495 -48
  178. package/dist/server/agent-chat-plugin.js.map +1 -1
  179. package/dist/server/agent-discovery.js +2 -2
  180. package/dist/server/agent-discovery.js.map +1 -1
  181. package/dist/server/agent-teams.d.ts.map +1 -1
  182. package/dist/server/agent-teams.js +21 -58
  183. package/dist/server/agent-teams.js.map +1 -1
  184. package/dist/server/auth.d.ts +6 -0
  185. package/dist/server/auth.d.ts.map +1 -1
  186. package/dist/server/auth.js +284 -41
  187. package/dist/server/auth.js.map +1 -1
  188. package/dist/server/better-auth-instance.d.ts +1 -1
  189. package/dist/server/better-auth-instance.d.ts.map +1 -1
  190. package/dist/server/better-auth-instance.js +70 -4
  191. package/dist/server/better-auth-instance.js.map +1 -1
  192. package/dist/server/builder-browser.d.ts +21 -0
  193. package/dist/server/builder-browser.d.ts.map +1 -1
  194. package/dist/server/builder-browser.js +67 -4
  195. package/dist/server/builder-browser.js.map +1 -1
  196. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  197. package/dist/server/core-routes-plugin.js +122 -4
  198. package/dist/server/core-routes-plugin.js.map +1 -1
  199. package/dist/server/desktop-sso.d.ts +30 -0
  200. package/dist/server/desktop-sso.d.ts.map +1 -0
  201. package/dist/server/desktop-sso.js +74 -0
  202. package/dist/server/desktop-sso.js.map +1 -0
  203. package/dist/server/email.d.ts +23 -0
  204. package/dist/server/email.d.ts.map +1 -0
  205. package/dist/server/email.js +105 -0
  206. package/dist/server/email.js.map +1 -0
  207. package/dist/server/framework-request-handler.d.ts.map +1 -1
  208. package/dist/server/framework-request-handler.js +29 -0
  209. package/dist/server/framework-request-handler.js.map +1 -1
  210. package/dist/server/google-oauth.d.ts.map +1 -1
  211. package/dist/server/google-oauth.js +19 -3
  212. package/dist/server/google-oauth.js.map +1 -1
  213. package/dist/server/local-migration.d.ts +9 -0
  214. package/dist/server/local-migration.d.ts.map +1 -1
  215. package/dist/server/local-migration.js +44 -14
  216. package/dist/server/local-migration.js.map +1 -1
  217. package/dist/server/oauth-helpers.d.ts +2 -0
  218. package/dist/server/oauth-helpers.d.ts.map +1 -1
  219. package/dist/server/oauth-helpers.js +2 -0
  220. package/dist/server/oauth-helpers.js.map +1 -1
  221. package/dist/server/onboarding-html.d.ts +6 -0
  222. package/dist/server/onboarding-html.d.ts.map +1 -1
  223. package/dist/server/onboarding-html.js +229 -25
  224. package/dist/server/onboarding-html.js.map +1 -1
  225. package/dist/server/poll.d.ts.map +1 -1
  226. package/dist/server/poll.js +48 -0
  227. package/dist/server/poll.js.map +1 -1
  228. package/dist/templates/default/.agents/skills/inline-embeds/SKILL.md +88 -0
  229. package/dist/usage/store.d.ts +74 -12
  230. package/dist/usage/store.d.ts.map +1 -1
  231. package/dist/usage/store.js +210 -44
  232. package/dist/usage/store.js.map +1 -1
  233. package/dist/vite/client.d.ts.map +1 -1
  234. package/dist/vite/client.js +55 -0
  235. package/dist/vite/client.js.map +1 -1
  236. package/docs/content/deployment.md +59 -2
  237. package/docs/content/resources.md +9 -9
  238. package/docs/content/workspace-management.md +2 -2
  239. package/package.json +3 -3
  240. package/src/templates/default/.agents/skills/inline-embeds/SKILL.md +88 -0
  241. /package/dist/templates/workspace-core/{skills → .agents/skills}/company-policies/SKILL.md +0 -0
  242. /package/src/templates/workspace-core/{skills → .agents/skills}/company-policies/SKILL.md +0 -0
@@ -1,8 +1,9 @@
1
1
  import React from "react";
2
- export declare function BuilderCtaCard({ reason, usageCents, limitCents, }: {
2
+ export declare function BuilderCtaCard({ reason, usageCents, limitCents, apiUrl, }: {
3
3
  reason: "usage_limit" | "code_changes" | "cli_tab";
4
4
  usageCents?: number;
5
5
  limitCents?: number;
6
+ apiUrl?: string;
6
7
  }): import("react/jsx-runtime").JSX.Element;
7
8
  export interface AssistantChatHandle {
8
9
  /** Programmatically send a message into this chat */
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAwzBf,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,UAAU,EACV,UAAU,GACX,EAAE;IACD,MAAM,EAAE,aAAa,GAAG,cAAc,GAAG,SAAS,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,2CA+DA;AAID,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,6DAA6D;IAC7D,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,4CAA4C;IAC5C,SAAS,IAAI,OAAO,CAAC;IACrB,+BAA+B;IAC/B,aAAa,IAAI,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wGAAwG;IACxG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;KACtB,KACE,IAAI,CAAC;IACV,+DAA+D;IAC/D,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,8DAA8D;IAC9D,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,+FAA+F;IAC/F,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAEjD,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,QAI9C;AAoBD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AA60B7B,eAAO,MAAM,aAAa,gGAoCxB,CAAC"}
1
+ {"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAy5Bf,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,UAAU,EACV,UAAU,EACV,MAAoC,GACrC,EAAE;IACD,MAAM,EAAE,aAAa,GAAG,cAAc,GAAG,SAAS,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,2CAyJA;AAID,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,6DAA6D;IAC7D,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,4CAA4C;IAC5C,SAAS,IAAI,OAAO,CAAC;IACrB,+BAA+B;IAC/B,aAAa,IAAI,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wGAAwG;IACxG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;KACtB,KACE,IAAI,CAAC;IACV,+DAA+D;IAC/D,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,8DAA8D;IAC9D,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,+FAA+F;IAC/F,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAEjD,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,QAI9C;AAoBD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAo5B7B,eAAO,MAAM,aAAa,gGAoCxB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useRef, useEffect, useCallback, useMemo, forwardRef, useImperativeHandle, } from "react";
2
+ import React, { useState, useRef, useEffect, useCallback, useMemo, forwardRef, useImperativeHandle, } from "react";
3
3
  import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useAui, useComposer, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
4
4
  import { SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, CompositeAttachmentAdapter, } from "@assistant-ui/react";
5
5
  import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown";
@@ -9,8 +9,10 @@ import { createAgentChatAdapter } from "./agent-chat-adapter.js";
9
9
  import { readSSEStreamRaw } from "./sse-event-processor.js";
10
10
  import { cn } from "./utils.js";
11
11
  import { AgentTaskCard } from "./AgentTaskCard.js";
12
+ import { ConnectBuilderCard } from "./ConnectBuilderCard.js";
13
+ import { IframeEmbed, parseEmbedBody } from "./IframeEmbed.js";
12
14
  import { TiptapComposer, } from "./composer/TiptapComposer.js";
13
- import { IconSparkles, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, IconLock, } from "@tabler/icons-react";
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";
14
16
  // ─── Markdown Text ──────────────────────────────────────────────────────────
15
17
  const markdownStyles = `
16
18
  .agent-markdown > :first-child { margin-top: 0; }
@@ -43,11 +45,37 @@ function injectMarkdownStyles() {
43
45
  style.textContent = markdownStyles;
44
46
  document.head.appendChild(style);
45
47
  }
48
+ function extractCodeText(child) {
49
+ if (typeof child === "string")
50
+ return child;
51
+ if (Array.isArray(child))
52
+ return child.map(extractCodeText).join("");
53
+ if (React.isValidElement(child)) {
54
+ const props = child.props;
55
+ return extractCodeText(props.children);
56
+ }
57
+ return "";
58
+ }
59
+ const markdownComponents = {
60
+ pre(props) {
61
+ const { children, ...rest } = props;
62
+ if (React.isValidElement(children)) {
63
+ const childProps = children.props;
64
+ const className = childProps.className || "";
65
+ if (/\blanguage-embed\b/.test(className)) {
66
+ const body = extractCodeText(childProps.children);
67
+ const parsed = parseEmbedBody(body);
68
+ return (_jsx(IframeEmbed, { ...parsed }));
69
+ }
70
+ }
71
+ return _jsx("pre", { ...rest, children: children });
72
+ },
73
+ };
46
74
  function MarkdownText() {
47
75
  useEffect(() => {
48
76
  injectMarkdownStyles();
49
77
  }, []);
50
- return (_jsx(MarkdownTextPrimitive, { smooth: true, className: "agent-markdown break-words", remarkPlugins: [remarkGfm] }));
78
+ return (_jsx(MarkdownTextPrimitive, { smooth: true, className: "agent-markdown break-words", remarkPlugins: [remarkGfm], components: markdownComponents }));
51
79
  }
52
80
  // ─── Composer Attachment Preview ─────────────────────────────────────────────
53
81
  function getImageAttachmentSrc(attachment) {
@@ -106,6 +134,18 @@ function ToolCallDisplay({ toolName, argsText, args, result, isRunning, }) {
106
134
  streamRef.current.scrollTop = streamRef.current.scrollHeight;
107
135
  }
108
136
  }, [agentStreamText, isAgentCall, isRunning]);
137
+ // Render connect-builder as ConnectBuilderCard once the result is available
138
+ if (toolName === "connect-builder" && result) {
139
+ try {
140
+ const parsed = JSON.parse(result);
141
+ if (parsed?.kind === "connect-builder-card") {
142
+ return (_jsx(ConnectBuilderCard, { configured: !!parsed.configured, builderEnabled: !!parsed.builderEnabled, connectUrl: parsed.connectUrl || "", orgName: parsed.orgName ?? null, prompt: typeof parsed.prompt === "string" ? parsed.prompt : "" }));
143
+ }
144
+ }
145
+ catch {
146
+ // fall through to default pill rendering
147
+ }
148
+ }
109
149
  // Render spawn-task as AgentTaskCard once the result is available
110
150
  if (toolName === "spawn-task" && result) {
111
151
  try {
@@ -146,7 +186,7 @@ function ToolCallDisplay({ toolName, argsText, args, result, isRunning, }) {
146
186
  const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
147
187
  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
148
188
  ? "bg-muted text-muted-foreground"
149
- : "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, { remarkPlugins: [remarkGfm], 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"
189
+ : "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, { remarkPlugins: [remarkGfm], components: markdownComponents, 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"
150
190
  ? result
151
191
  : JSON.stringify(result, null, 2) }))] }));
152
192
  }
@@ -169,7 +209,7 @@ function ReconnectStreamMessage({ content }) {
169
209
  }, [content]);
170
210
  return (_jsx("div", { className: "flex justify-start", children: _jsxs("div", { className: "max-w-[95%] text-sm leading-relaxed text-foreground space-y-1", children: [content.map((part, i) => {
171
211
  if (part.type === "text") {
172
- return (_jsx("div", { className: "agent-markdown break-words", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: part.text }) }, `reconnect-text-${i}`));
212
+ return (_jsx("div", { className: "agent-markdown break-words", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: part.text }) }, `reconnect-text-${i}`));
173
213
  }
174
214
  if (part.type === "tool-call") {
175
215
  return (_jsx(ToolCallDisplay, { toolName: part.toolName, argsText: part.argsText, args: part.args, result: part.result, isRunning: part.result === undefined }, `reconnect-tool-${i}`));
@@ -254,13 +294,22 @@ function UserMessageText({ text }) {
254
294
  function UserMessageAttachments() {
255
295
  const messageRuntime = useMessageRuntime();
256
296
  const msg = messageRuntime.getState();
257
- // Content parts may include image/file types from attachments
258
- const parts = msg.content;
259
- const images = parts.filter((p) => p.type === "image" && p.image);
260
- const files = parts.filter((p) => p.type === "file");
261
- if (images.length === 0 && files.length === 0)
297
+ // assistant-ui stores user attachments on msg.attachments (separate from content).
298
+ // Each attachment has: { id, type, name, contentType?, content: MessagePart[] }.
299
+ // Image adapters put a {type:"image", image:"data:..."} part in content; text
300
+ // adapters put a {type:"text", text:"<attachment>..."} part. Fall back to a
301
+ // file chip when there's no inline image.
302
+ const attachments = msg
303
+ .attachments;
304
+ if (!attachments || attachments.length === 0)
262
305
  return null;
263
- return (_jsxs("div", { className: "flex flex-wrap justify-end gap-1.5 mb-1.5", children: [images.map((img, i) => (_jsx("div", { className: "h-16 w-16 overflow-hidden rounded-lg border border-border/70 bg-muted/50", children: _jsx("img", { src: img.image, alt: "attachment", className: "h-full w-full object-cover" }) }, i))), files.map((file, i) => (_jsxs("div", { className: "flex items-center gap-1.5 rounded-lg border border-border/70 bg-muted/50 px-2 py-1.5 text-xs text-muted-foreground", children: [_jsx(IconFile, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "truncate max-w-[120px]", children: file.name || "file" })] }, `f-${i}`)))] }));
306
+ return (_jsx("div", { className: "flex flex-wrap justify-end gap-1.5 mb-1.5", children: attachments.map((att) => {
307
+ const imagePart = att.content?.find((p) => p.type === "image" && "image" in p && !!p.image);
308
+ if (imagePart) {
309
+ return (_jsx("div", { className: "h-16 w-16 overflow-hidden rounded-lg border border-border/70 bg-muted/50", title: att.name, children: _jsx("img", { src: imagePart.image, alt: att.name, className: "h-full w-full object-cover" }) }, att.id));
310
+ }
311
+ return (_jsxs("div", { className: "flex items-center gap-1.5 rounded-lg border border-border/70 bg-muted/50 px-2 py-1.5 text-xs text-muted-foreground", title: att.name, children: [_jsx(IconFile, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "truncate max-w-[120px]", children: att.name || "file" })] }, att.id));
312
+ }) }));
264
313
  }
265
314
  function UserMessage() {
266
315
  const [expanded, setExpanded] = useState(false);
@@ -367,7 +416,7 @@ function ApiKeySetupCard({ apiUrl }) {
367
416
  if (saved) {
368
417
  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..."] }) }));
369
418
  }
370
- 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) => {
419
+ 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) => {
371
420
  setApiKey(e.target.value);
372
421
  setError(null);
373
422
  }, onKeyDown: (e) => {
@@ -376,22 +425,60 @@ function ApiKeySetupCard({ apiUrl }) {
376
425
  }, 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" })] })] }));
377
426
  }
378
427
  // ─── Builder.io CTA Card (usage limit / code changes / CLI) ─────────────────
379
- export function BuilderCtaCard({ reason, usageCents, limitCents, }) {
428
+ export function BuilderCtaCard({ reason, usageCents, limitCents, apiUrl = "/_agent-native/agent-chat", }) {
380
429
  const appName = typeof window !== "undefined"
381
430
  ? window.location.hostname.split(".")[0]
382
431
  : "app";
383
432
  const cloneCommand = `npx agent-native create ${appName}`;
433
+ const [apiKey, setApiKey] = useState("");
434
+ const [saving, setSaving] = useState(false);
435
+ const [saved, setSaved] = useState(false);
436
+ const [error, setError] = useState(null);
437
+ const handleSave = async () => {
438
+ if (!apiKey.trim())
439
+ return;
440
+ setSaving(true);
441
+ setError(null);
442
+ try {
443
+ const res = await fetch(`${apiUrl}/save-key`, {
444
+ method: "POST",
445
+ headers: { "Content-Type": "application/json" },
446
+ body: JSON.stringify({ key: apiKey.trim() }),
447
+ });
448
+ if (!res.ok) {
449
+ const data = await res.json().catch(() => ({}));
450
+ throw new Error(data.error || "Failed to save");
451
+ }
452
+ setSaved(true);
453
+ setTimeout(() => window.location.reload(), 1000);
454
+ }
455
+ catch (err) {
456
+ setError(err instanceof Error ? err.message : "Failed to save");
457
+ }
458
+ finally {
459
+ setSaving(false);
460
+ }
461
+ };
384
462
  const title = reason === "usage_limit"
385
463
  ? "Free usage limit reached"
386
464
  : reason === "code_changes"
387
465
  ? "Code changes require a local setup"
388
466
  : "Get full access";
389
467
  const description = reason === "usage_limit"
390
- ? `You've used $${((usageCents ?? 0) / 100).toFixed(2)} of your $${((limitCents ?? 100) / 100).toFixed(2)} free tier. Connect to Builder.io for unlimited usage, or clone this app to run it locally with your own API key.`
468
+ ? null
391
469
  : reason === "code_changes"
392
- ? "This app is running in hosted mode. To make code changes, connect to Builder.io or clone and run locally."
393
- : "This hosted app has limited AI features. Connect to Builder.io for the full experience, or clone and run locally with your own API key.";
394
- 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: title }), _jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: description })] })] }), _jsxs("div", { className: "space-y-2.5", children: [_jsx("a", { href: "https://www.builder.io/m/agent-native", target: "_blank", rel: "noopener noreferrer", className: "flex w-full items-center justify-center rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:opacity-90", children: "Connect to Builder.io" }), _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 })] })] })] }));
470
+ ? "This app is running in hosted mode. To make code changes, add your own Anthropic API key or clone and run locally."
471
+ : "This hosted app has limited AI features. Add your own Anthropic API key for the full experience, or clone and run locally.";
472
+ if (saved) {
473
+ 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..."] }) }));
474
+ }
475
+ 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-4", 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: title }), description && (_jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: description }))] })] }), _jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "rounded-md bg-muted/50 px-3 py-2.5 text-xs text-muted-foreground leading-relaxed", children: _jsxs("p", { children: ["Paste an Anthropic API key (", _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" }), ") to skip the free-tier limit."] }) }), _jsx("input", { type: "password", value: apiKey, onChange: (e) => {
476
+ setApiKey(e.target.value);
477
+ setError(null);
478
+ }, onKeyDown: (e) => {
479
+ if (e.key === "Enter")
480
+ handleSave();
481
+ }, 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" })] }) })] })] }));
395
482
  }
396
483
  export const CHAT_STORAGE_PREFIX = "agent-chat:";
397
484
  /** Remove persisted chat for a given tabId (or "default"). */
@@ -438,18 +525,17 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
438
525
  const [reconnectFrozen, setReconnectFrozen] = useState(false);
439
526
  const reconnectRunIdRef = useRef(null);
440
527
  const reconnectAbortRef = useRef(null);
441
- // Nuclear stop: user clicked stop but runtime hasn't cleared yet.
442
- // This ONLY affects UI display (button + thinking indicator). Submission
443
- // and queue gating still use the real `isRunning` so we never overlap a
444
- // new run on top of one that's still cancelling on the server.
528
+ // Nuclear stop: user clicked stop. Clears the stop button/indicator AND
529
+ // lets new submissions go through immediately prevents the "stuck
530
+ // queueing forever" state where isReconnecting or isRuntimeRunning gets
531
+ // wedged (e.g. after a tab refresh + stop during reconnect).
445
532
  const [forceStopped, setForceStopped] = useState(false);
446
533
  // Real running state — drives submission/queue gating. Treat reconnecting
447
- // to an active run the same as running.
448
- const isRunning = isRuntimeRunning || isReconnecting;
534
+ // to an active run the same as running, UNLESS the user has explicitly
535
+ // clicked stop (forceStopped).
536
+ const isRunning = !forceStopped && (isRuntimeRunning || isReconnecting);
449
537
  // UI-only running state — drives the stop button and thinking indicator.
450
- // forceStopped lets us flip the indicator off immediately even if the
451
- // underlying runtime or reconnect state hasn't caught up yet.
452
- const showRunningInUI = !forceStopped && isRunning;
538
+ const showRunningInUI = isRunning;
453
539
  const wasRunningRef = useRef(false);
454
540
  const tiptapRef = useRef(null);
455
541
  // ─── Chat persistence ──────────────────────────────────────────────
@@ -524,6 +610,38 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
524
610
  // can abort it even if clicked before the function body runs.
525
611
  const abortCtrl = new AbortController();
526
612
  reconnectAbortRef.current = abortCtrl;
613
+ // Watchdog: poll /runs/active to detect when the run is no
614
+ // longer running server-side. If the SSE stream hangs (e.g.
615
+ // because the agent process died but its SQL run row is still
616
+ // marked "running", or the stream just never emits `done`),
617
+ // this aborts the fetch so we fall through to thread refresh
618
+ // instead of showing "Thinking..." forever.
619
+ const watchdog = setInterval(async () => {
620
+ try {
621
+ const res = await fetch(`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`);
622
+ if (!res.ok) {
623
+ abortCtrl.abort();
624
+ clearInterval(watchdog);
625
+ return;
626
+ }
627
+ const info = await res.json();
628
+ if (info.status !== "running") {
629
+ abortCtrl.abort();
630
+ clearInterval(watchdog);
631
+ }
632
+ }
633
+ catch {
634
+ // Network blip — keep polling
635
+ }
636
+ }, 3000);
637
+ // Hard cap: no single reconnect should wedge the UI for
638
+ // more than 2 minutes. Even if the watchdog is fooled and
639
+ // the SSE stream never closes, this guarantees "Thinking..."
640
+ // eventually clears.
641
+ const maxReconnectTimer = setTimeout(() => {
642
+ abortCtrl.abort();
643
+ clearInterval(watchdog);
644
+ }, 2 * 60 * 1000);
527
645
  const streamReconnect = async () => {
528
646
  try {
529
647
  const sseRes = await fetch(`${apiUrl}/runs/${encodeURIComponent(runInfo.runId)}/events?after=0`, { signal: abortCtrl.signal });
@@ -551,6 +669,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
551
669
  catch {
552
670
  // Stream error or abort — fall through to re-fetch
553
671
  }
672
+ finally {
673
+ clearInterval(watchdog);
674
+ clearTimeout(maxReconnectTimer);
675
+ }
554
676
  // Poll for thread data — server's updateThreadData may not have
555
677
  // committed yet when the SSE `done` event fires, so retry until
556
678
  // an assistant message appears (up to ~5 s) before clearing.
@@ -811,7 +933,17 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
811
933
  const addToQueue = useCallback((text, images, references) => {
812
934
  setShowContinue(false);
813
935
  if (isRunning) {
814
- setQueuedMessages((prev) => [...prev, { text, images, references }]);
936
+ setQueuedMessages((prev) => [
937
+ ...prev,
938
+ {
939
+ id: typeof crypto !== "undefined" && crypto.randomUUID
940
+ ? crypto.randomUUID()
941
+ : `q-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
942
+ text,
943
+ images,
944
+ references,
945
+ },
946
+ ]);
815
947
  }
816
948
  else {
817
949
  const content = [{ type: "text", text }];
@@ -908,44 +1040,44 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
908
1040
  }, 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: () => {
909
1041
  setAuthError(null);
910
1042
  window.location.reload();
911
- }, 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 }) })) : 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: () => {
1043
+ }, 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: () => {
912
1044
  threadRuntime.append({
913
1045
  role: "user",
914
1046
  content: [{ type: "text", text: suggestion }],
915
1047
  });
916
- }, 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: {
1048
+ }, 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: {
917
1049
  UserMessage,
918
1050
  AssistantMessage,
919
1051
  } }), showContinue && !showRunningInUI && (_jsx("div", { className: "flex justify-center py-2", children: _jsx("button", { type: "button", onClick: () => {
920
1052
  setShowContinue(false);
921
1053
  addToQueue("Continue from where you left off.");
922
1054
  }, 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) &&
923
- reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), showRunningInUI && _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
1055
+ reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), showRunningInUI && _jsx(ThinkingIndicator, {}), queuedMessages.map((msg) => {
1056
+ const displayText = msg.text
1057
+ .replace(/<context>[\s\S]*?<\/context>\n?/g, "")
1058
+ .trim();
1059
+ 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));
1060
+ })] })) }), 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
924
1061
  ? queuedMessages.length > 0
925
1062
  ? `${queuedMessages.length} queued — type another...`
926
1063
  : "Queue a message..."
927
1064
  : undefined, onSubmit: isRunning
928
1065
  ? (text, references) => addToQueue(text, undefined, references.length > 0 ? references : undefined)
929
- : undefined, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, actionButton: showRunningInUI ? (_jsx("button", { onClick: () => {
930
- // Immediately force the indicator off belt-and-suspenders
931
- // so the UI is never stuck even if the runtime or reconnect
932
- // state takes time (or fails) to clear on its own.
1066
+ : undefined, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, extraActionButton: showRunningInUI ? (_jsx("button", { type: "button", onClick: () => {
1067
+ // Nuclear stop: flip forceStopped so isRunning is false
1068
+ // immediately. This unblocks submission even if the
1069
+ // runtime or reconnect state is stuck.
933
1070
  setForceStopped(true);
934
1071
  if (isReconnecting) {
935
- // Abort the server-side run (fire-and-forget)
936
1072
  if (reconnectRunIdRef.current) {
937
1073
  fetch(`${apiUrl}/runs/${encodeURIComponent(reconnectRunIdRef.current)}/abort`, { method: "POST" });
938
1074
  }
939
- // Abort the client-side SSE stream
940
1075
  reconnectAbortRef.current?.abort();
941
1076
  reconnectAbortRef.current = null;
942
1077
  reconnectRunIdRef.current = null;
943
1078
  setIsReconnecting(false);
944
- // Keep reconnectContent visible (frozen) — don't wipe it
945
1079
  setReconnectFrozen(reconnectContent.length > 0);
946
1080
  }
947
- // Always try to cancel the runtime run too (handles the
948
- // normal non-reconnect path and is a no-op if not running)
949
1081
  threadRuntime.cancelRun();
950
1082
  window.dispatchEvent(new CustomEvent("builder.chatRunning", {
951
1083
  detail: {
@@ -953,7 +1085,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
953
1085
  tabId: tabId || threadId,
954
1086
  },
955
1087
  }));
956
- }, 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 })] }) })] }));
1088
+ }, 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 })] }) })] }));
957
1089
  });
958
1090
  export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = "/_agent-native/agent-chat", tabId, threadId, ...props }, ref) {
959
1091
  const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId, threadId }), [apiUrl, tabId, threadId]);