@agent-native/core 0.9.1 → 0.11.0

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 (288) hide show
  1. package/README.md +4 -4
  2. package/dist/a2a/caller-auth.d.ts +12 -0
  3. package/dist/a2a/caller-auth.d.ts.map +1 -0
  4. package/dist/a2a/caller-auth.js +54 -0
  5. package/dist/a2a/caller-auth.js.map +1 -0
  6. package/dist/action.d.ts +17 -0
  7. package/dist/action.d.ts.map +1 -1
  8. package/dist/action.js +22 -0
  9. package/dist/action.js.map +1 -1
  10. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  11. package/dist/agent/engine/builder-engine.js +5 -4
  12. package/dist/agent/engine/builder-engine.js.map +1 -1
  13. package/dist/agent/engine/registry.d.ts +6 -3
  14. package/dist/agent/engine/registry.d.ts.map +1 -1
  15. package/dist/agent/engine/registry.js +8 -17
  16. package/dist/agent/engine/registry.js.map +1 -1
  17. package/dist/agent/production-agent.d.ts +1 -1
  18. package/dist/agent/production-agent.d.ts.map +1 -1
  19. package/dist/agent/production-agent.js +60 -30
  20. package/dist/agent/production-agent.js.map +1 -1
  21. package/dist/agent/run-manager.d.ts.map +1 -1
  22. package/dist/agent/run-manager.js +12 -3
  23. package/dist/agent/run-manager.js.map +1 -1
  24. package/dist/agent/thread-data-builder.d.ts +12 -0
  25. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  26. package/dist/agent/thread-data-builder.js +96 -0
  27. package/dist/agent/thread-data-builder.js.map +1 -1
  28. package/dist/cli/create.d.ts.map +1 -1
  29. package/dist/cli/create.js +16 -10
  30. package/dist/cli/create.js.map +1 -1
  31. package/dist/client/AgentPanel.d.ts.map +1 -1
  32. package/dist/client/AgentPanel.js +8 -22
  33. package/dist/client/AgentPanel.js.map +1 -1
  34. package/dist/client/AssistantChat.d.ts.map +1 -1
  35. package/dist/client/AssistantChat.js +130 -34
  36. package/dist/client/AssistantChat.js.map +1 -1
  37. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  38. package/dist/client/agent-chat-adapter.js +21 -7
  39. package/dist/client/agent-chat-adapter.js.map +1 -1
  40. package/dist/client/agent-sidebar-state.d.ts +3 -0
  41. package/dist/client/agent-sidebar-state.d.ts.map +1 -0
  42. package/dist/client/agent-sidebar-state.js +24 -0
  43. package/dist/client/agent-sidebar-state.js.map +1 -0
  44. package/dist/client/analytics.d.ts +25 -0
  45. package/dist/client/analytics.d.ts.map +1 -1
  46. package/dist/client/analytics.js +40 -0
  47. package/dist/client/analytics.js.map +1 -1
  48. package/dist/client/components/ui/dropdown-menu.d.ts +28 -0
  49. package/dist/client/components/ui/dropdown-menu.d.ts.map +1 -0
  50. package/dist/client/components/ui/dropdown-menu.js +34 -0
  51. package/dist/client/components/ui/dropdown-menu.js.map +1 -0
  52. package/dist/client/components/ui/tooltip.d.ts +2 -1
  53. package/dist/client/components/ui/tooltip.d.ts.map +1 -1
  54. package/dist/client/components/ui/tooltip.js +9 -2
  55. package/dist/client/components/ui/tooltip.js.map +1 -1
  56. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  57. package/dist/client/composer/ComposerPlusMenu.js +41 -8
  58. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  59. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  60. package/dist/client/composer/PromptComposer.js +30 -0
  61. package/dist/client/composer/PromptComposer.js.map +1 -1
  62. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  63. package/dist/client/composer/TiptapComposer.js +27 -2
  64. package/dist/client/composer/TiptapComposer.js.map +1 -1
  65. package/dist/client/dev-overlay/DevOverlay.d.ts.map +1 -1
  66. package/dist/client/dev-overlay/DevOverlay.js +4 -4
  67. package/dist/client/dev-overlay/DevOverlay.js.map +1 -1
  68. package/dist/client/error-format.d.ts.map +1 -1
  69. package/dist/client/error-format.js +6 -0
  70. package/dist/client/error-format.js.map +1 -1
  71. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  72. package/dist/client/extensions/EmbeddedExtension.js +16 -4
  73. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  74. package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -1
  75. package/dist/client/extensions/ExtensionEditor.js +6 -6
  76. package/dist/client/extensions/ExtensionEditor.js.map +1 -1
  77. package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -1
  78. package/dist/client/extensions/ExtensionSlot.js +15 -2
  79. package/dist/client/extensions/ExtensionSlot.js.map +1 -1
  80. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  81. package/dist/client/extensions/ExtensionViewer.js +41 -19
  82. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  83. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  84. package/dist/client/extensions/ExtensionsListPage.js +2 -2
  85. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  86. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  87. package/dist/client/extensions/ExtensionsSidebarSection.js +52 -63
  88. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  89. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -1
  90. package/dist/client/extensions/iframe-bridge.js +5 -8
  91. package/dist/client/extensions/iframe-bridge.js.map +1 -1
  92. package/dist/client/index.d.ts +1 -1
  93. package/dist/client/index.d.ts.map +1 -1
  94. package/dist/client/index.js +1 -1
  95. package/dist/client/index.js.map +1 -1
  96. package/dist/client/notifications/NotificationsBell.d.ts.map +1 -1
  97. package/dist/client/notifications/NotificationsBell.js +42 -6
  98. package/dist/client/notifications/NotificationsBell.js.map +1 -1
  99. package/dist/client/org/InvitationBanner.d.ts.map +1 -1
  100. package/dist/client/org/InvitationBanner.js +5 -5
  101. package/dist/client/org/InvitationBanner.js.map +1 -1
  102. package/dist/client/org/OrgSwitcher.d.ts +7 -1
  103. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  104. package/dist/client/org/OrgSwitcher.js +8 -3
  105. package/dist/client/org/OrgSwitcher.js.map +1 -1
  106. package/dist/client/org/TeamPage.d.ts.map +1 -1
  107. package/dist/client/org/TeamPage.js +156 -22
  108. package/dist/client/org/TeamPage.js.map +1 -1
  109. package/dist/client/org/hooks.d.ts +29 -1
  110. package/dist/client/org/hooks.d.ts.map +1 -1
  111. package/dist/client/org/hooks.js +39 -2
  112. package/dist/client/org/hooks.js.map +1 -1
  113. package/dist/client/org/index.d.ts +2 -1
  114. package/dist/client/org/index.d.ts.map +1 -1
  115. package/dist/client/org/index.js +1 -1
  116. package/dist/client/org/index.js.map +1 -1
  117. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  118. package/dist/client/resources/ResourceTree.js +11 -3
  119. package/dist/client/resources/ResourceTree.js.map +1 -1
  120. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  121. package/dist/client/resources/ResourcesPanel.js +62 -12
  122. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  123. package/dist/client/resources/use-mcp-servers.d.ts +2 -0
  124. package/dist/client/resources/use-mcp-servers.d.ts.map +1 -1
  125. package/dist/client/resources/use-mcp-servers.js +59 -3
  126. package/dist/client/resources/use-mcp-servers.js.map +1 -1
  127. package/dist/client/settings/SecretsSection.d.ts.map +1 -1
  128. package/dist/client/settings/SecretsSection.js +9 -0
  129. package/dist/client/settings/SecretsSection.js.map +1 -1
  130. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  131. package/dist/client/settings/SettingsPanel.js +50 -12
  132. package/dist/client/settings/SettingsPanel.js.map +1 -1
  133. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  134. package/dist/client/settings/VoiceTranscriptionSection.js +13 -30
  135. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  136. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  137. package/dist/client/settings/useBuilderStatus.js +27 -1
  138. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  139. package/dist/client/sharing/ShareButton.d.ts +4 -0
  140. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  141. package/dist/client/sharing/ShareButton.js +5 -1
  142. package/dist/client/sharing/ShareButton.js.map +1 -1
  143. package/dist/client/sse-event-processor.d.ts +1 -1
  144. package/dist/client/sse-event-processor.d.ts.map +1 -1
  145. package/dist/client/sse-event-processor.js +14 -7
  146. package/dist/client/sse-event-processor.js.map +1 -1
  147. package/dist/client/use-db-sync.d.ts.map +1 -1
  148. package/dist/client/use-db-sync.js +100 -19
  149. package/dist/client/use-db-sync.js.map +1 -1
  150. package/dist/deploy/build.d.ts.map +1 -1
  151. package/dist/deploy/build.js +25 -49
  152. package/dist/deploy/build.js.map +1 -1
  153. package/dist/deploy/route-discovery.d.ts.map +1 -1
  154. package/dist/deploy/route-discovery.js +1 -0
  155. package/dist/deploy/route-discovery.js.map +1 -1
  156. package/dist/deploy/workspace-core.d.ts +1 -1
  157. package/dist/deploy/workspace-core.d.ts.map +1 -1
  158. package/dist/deploy/workspace-core.js +1 -0
  159. package/dist/deploy/workspace-core.js.map +1 -1
  160. package/dist/extensions/actions.d.ts.map +1 -1
  161. package/dist/extensions/actions.js +17 -3
  162. package/dist/extensions/actions.js.map +1 -1
  163. package/dist/extensions/routes.js +1 -1
  164. package/dist/extensions/routes.js.map +1 -1
  165. package/dist/extensions/schema.d.ts +14 -14
  166. package/dist/extensions/schema.d.ts.map +1 -1
  167. package/dist/extensions/schema.js +4 -4
  168. package/dist/extensions/schema.js.map +1 -1
  169. package/dist/extensions/store.d.ts.map +1 -1
  170. package/dist/extensions/store.js +23 -0
  171. package/dist/extensions/store.js.map +1 -1
  172. package/dist/extensions/theme.d.ts +8 -1
  173. package/dist/extensions/theme.d.ts.map +1 -1
  174. package/dist/extensions/theme.js +43 -34
  175. package/dist/extensions/theme.js.map +1 -1
  176. package/dist/index.browser.d.ts +1 -1
  177. package/dist/index.browser.d.ts.map +1 -1
  178. package/dist/index.browser.js +1 -1
  179. package/dist/index.browser.js.map +1 -1
  180. package/dist/index.d.ts +1 -1
  181. package/dist/index.d.ts.map +1 -1
  182. package/dist/index.js +1 -1
  183. package/dist/index.js.map +1 -1
  184. package/dist/mcp-client/routes.d.ts +1 -0
  185. package/dist/mcp-client/routes.d.ts.map +1 -1
  186. package/dist/mcp-client/routes.js +28 -1
  187. package/dist/mcp-client/routes.js.map +1 -1
  188. package/dist/org/accept-pending.d.ts.map +1 -1
  189. package/dist/org/accept-pending.js +5 -3
  190. package/dist/org/accept-pending.js.map +1 -1
  191. package/dist/org/free-email-providers.d.ts +18 -0
  192. package/dist/org/free-email-providers.d.ts.map +1 -0
  193. package/dist/org/free-email-providers.js +124 -0
  194. package/dist/org/free-email-providers.js.map +1 -0
  195. package/dist/org/handlers.d.ts +29 -5
  196. package/dist/org/handlers.d.ts.map +1 -1
  197. package/dist/org/handlers.js +178 -37
  198. package/dist/org/handlers.js.map +1 -1
  199. package/dist/org/index.d.ts +2 -1
  200. package/dist/org/index.d.ts.map +1 -1
  201. package/dist/org/index.js +2 -1
  202. package/dist/org/index.js.map +1 -1
  203. package/dist/org/migrations.d.ts.map +1 -1
  204. package/dist/org/migrations.js +4 -0
  205. package/dist/org/migrations.js.map +1 -1
  206. package/dist/org/plugin.d.ts.map +1 -1
  207. package/dist/org/plugin.js +13 -4
  208. package/dist/org/plugin.js.map +1 -1
  209. package/dist/org/schema.d.ts +19 -0
  210. package/dist/org/schema.d.ts.map +1 -1
  211. package/dist/org/schema.js +1 -0
  212. package/dist/org/schema.js.map +1 -1
  213. package/dist/org/types.d.ts +1 -0
  214. package/dist/org/types.d.ts.map +1 -1
  215. package/dist/org/types.js.map +1 -1
  216. package/dist/resources/metadata.d.ts +1 -0
  217. package/dist/resources/metadata.d.ts.map +1 -1
  218. package/dist/resources/metadata.js +13 -3
  219. package/dist/resources/metadata.js.map +1 -1
  220. package/dist/resources/store.d.ts.map +1 -1
  221. package/dist/resources/store.js +44 -6
  222. package/dist/resources/store.js.map +1 -1
  223. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  224. package/dist/server/agent-chat-plugin.js +115 -113
  225. package/dist/server/agent-chat-plugin.js.map +1 -1
  226. package/dist/server/auth.d.ts.map +1 -1
  227. package/dist/server/auth.js +33 -0
  228. package/dist/server/auth.js.map +1 -1
  229. package/dist/server/builder-browser.d.ts.map +1 -1
  230. package/dist/server/builder-browser.js +169 -68
  231. package/dist/server/builder-browser.js.map +1 -1
  232. package/dist/server/credential-provider.d.ts +2 -2
  233. package/dist/server/credential-provider.d.ts.map +1 -1
  234. package/dist/server/credential-provider.js +31 -12
  235. package/dist/server/credential-provider.js.map +1 -1
  236. package/dist/server/framework-request-handler.d.ts.map +1 -1
  237. package/dist/server/framework-request-handler.js +31 -0
  238. package/dist/server/framework-request-handler.js.map +1 -1
  239. package/dist/server/google-oauth.d.ts.map +1 -1
  240. package/dist/server/google-oauth.js +10 -3
  241. package/dist/server/google-oauth.js.map +1 -1
  242. package/dist/server/google-realtime-session.d.ts.map +1 -1
  243. package/dist/server/google-realtime-session.js +19 -6
  244. package/dist/server/google-realtime-session.js.map +1 -1
  245. package/dist/server/index.d.ts +2 -0
  246. package/dist/server/index.d.ts.map +1 -1
  247. package/dist/server/index.js +2 -0
  248. package/dist/server/index.js.map +1 -1
  249. package/dist/server/onboarding-html.d.ts.map +1 -1
  250. package/dist/server/onboarding-html.js +45 -6
  251. package/dist/server/onboarding-html.js.map +1 -1
  252. package/dist/server/request-context.d.ts +17 -0
  253. package/dist/server/request-context.d.ts.map +1 -1
  254. package/dist/server/request-context.js +40 -1
  255. package/dist/server/request-context.js.map +1 -1
  256. package/dist/server/sentry-plugin.d.ts +11 -0
  257. package/dist/server/sentry-plugin.d.ts.map +1 -0
  258. package/dist/server/sentry-plugin.js +116 -0
  259. package/dist/server/sentry-plugin.js.map +1 -0
  260. package/dist/server/sentry.d.ts +92 -0
  261. package/dist/server/sentry.d.ts.map +1 -0
  262. package/dist/server/sentry.js +287 -0
  263. package/dist/server/sentry.js.map +1 -0
  264. package/dist/server/transcribe-voice.d.ts +2 -4
  265. package/dist/server/transcribe-voice.d.ts.map +1 -1
  266. package/dist/server/transcribe-voice.js +4 -16
  267. package/dist/server/transcribe-voice.js.map +1 -1
  268. package/dist/server/voice-providers-status.d.ts.map +1 -1
  269. package/dist/server/voice-providers-status.js +19 -35
  270. package/dist/server/voice-providers-status.js.map +1 -1
  271. package/dist/styles/agent-native.css +15 -0
  272. package/docs/content/cloneable-saas.md +7 -9
  273. package/docs/content/deployment.md +6 -2
  274. package/docs/content/dispatch.md +1 -1
  275. package/docs/content/extensions.md +177 -142
  276. package/docs/content/faq.md +2 -2
  277. package/docs/content/getting-started.md +13 -11
  278. package/docs/content/multi-app-workspace.md +2 -2
  279. package/docs/content/observability.md +47 -0
  280. package/docs/content/pure-agent-apps.md +1 -1
  281. package/docs/content/template-clips.md +3 -3
  282. package/docs/content/template-design.md +3 -3
  283. package/docs/content/template-dispatch.md +1 -1
  284. package/docs/content/template-forms.md +1 -1
  285. package/docs/content/template-mail.md +1 -1
  286. package/docs/content/what-is-agent-native.md +4 -4
  287. package/docs/content/workspace.md +1 -1
  288. package/package.json +2 -1
@@ -8,6 +8,7 @@ import { TiptapComposer } from "./TiptapComposer.js";
8
8
  import { useChatModels } from "../use-chat-models.js";
9
9
  import { isPastedTextAttachmentName } from "./pasted-text.js";
10
10
  import { PastedTextChip } from "./PastedTextChip.js";
11
+ const MAX_INLINE_TEXT_FILE_CHARS = 60_000;
11
12
  // Minimal pass-through adapter. PromptComposer always submits through
12
13
  // onSubmitOverride, so the runtime never actually calls this — but
13
14
  // `useLocalRuntime` needs *something* shaped like a ChatModelAdapter.
@@ -44,6 +45,27 @@ class BinaryDocumentAttachmentAdapter {
44
45
  /* noop */
45
46
  }
46
47
  }
48
+ function isInlineableTextFile(file) {
49
+ if (file.type.startsWith("text/"))
50
+ return true;
51
+ if (file.type === "application/json")
52
+ return true;
53
+ return /\.(txt|md|markdown|csv|json|yaml|yml)$/i.test(file.name);
54
+ }
55
+ function formatInlineTextFile(name, text) {
56
+ const truncated = text.length > MAX_INLINE_TEXT_FILE_CHARS;
57
+ const body = truncated ? text.slice(0, MAX_INLINE_TEXT_FILE_CHARS) : text;
58
+ return [
59
+ `<uploaded-text-file name="${name}">`,
60
+ body,
61
+ truncated
62
+ ? `[Truncated after ${MAX_INLINE_TEXT_FILE_CHARS} characters.]`
63
+ : "",
64
+ "</uploaded-text-file>",
65
+ ]
66
+ .filter(Boolean)
67
+ .join("\n");
68
+ }
47
69
  function getImageSrc(attachment) {
48
70
  if (attachment.type !== "image")
49
71
  return null;
@@ -116,6 +138,14 @@ function PromptComposerInner({ onSubmit, placeholder, disabled, autoFocus, class
116
138
  }
117
139
  }
118
140
  else {
141
+ if (isInlineableTextFile(file)) {
142
+ try {
143
+ pastedTextBlocks.push(formatInlineTextFile(file.name, await file.text()));
144
+ }
145
+ catch {
146
+ // Keep the upload path fallback below.
147
+ }
148
+ }
119
149
  files.push(file);
120
150
  }
121
151
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PromptComposer.js","sourceRoot":"","sources":["../../../src/client/composer/PromptComposer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, type Ref } from \"react\";\nimport {\n AssistantRuntimeProvider,\n ComposerPrimitive,\n ThreadPrimitive,\n useAui,\n useComposer,\n useLocalRuntime,\n} from \"@assistant-ui/react\";\nimport type {\n Attachment,\n AttachmentAdapter,\n ChatModelAdapter,\n CompleteAttachment,\n PendingAttachment,\n} from \"@assistant-ui/react\";\nimport {\n CompositeAttachmentAdapter,\n SimpleImageAttachmentAdapter,\n SimpleTextAttachmentAdapter,\n} from \"@assistant-ui/react\";\nimport { IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { TiptapComposer, type TiptapComposerHandle } from \"./TiptapComposer.js\";\nimport type { Reference } from \"./types.js\";\nimport { useChatModels } from \"../use-chat-models.js\";\nimport { isPastedTextAttachmentName } from \"./pasted-text.js\";\nimport { PastedTextChip } from \"./PastedTextChip.js\";\n\n/**\n * Files the user attached via the \"+\" button in PromptComposer. The host owns\n * what to do with them — typically POST to a per-app upload endpoint and pass\n * the resulting URLs/paths into the prompt that gets sent to the agent.\n */\nexport type PromptComposerFile = File;\n\nexport interface PromptComposerProps {\n /** Called when the user submits the composer. */\n onSubmit: (\n text: string,\n files: PromptComposerFile[],\n references: Reference[],\n ) => void;\n placeholder?: string;\n disabled?: boolean;\n autoFocus?: boolean;\n className?: string;\n /** Forwarded to TiptapComposer for draft persistence. */\n draftScope?: string;\n /** Show the model selector (default: true). */\n showModelSelector?: boolean;\n /** Show the voice dictation button (default: true). */\n voiceEnabled?: boolean;\n /** Show file upload controls and pass submitted files to onSubmit (default: true). */\n attachmentsEnabled?: boolean;\n /** Called whenever the plain editor text changes. */\n onTextChange?: (text: string) => void;\n /** Imperative handle for focusing the composer. */\n composerRef?: Ref<TiptapComposerHandle>;\n}\n\n// Minimal pass-through adapter. PromptComposer always submits through\n// onSubmitOverride, so the runtime never actually calls this — but\n// `useLocalRuntime` needs *something* shaped like a ChatModelAdapter.\nconst NOOP_ADAPTER: ChatModelAdapter = {\n async *run() {\n return;\n },\n};\n\n/**\n * Local clone of AssistantChat's BinaryDocumentAttachmentAdapter so PDFs and\n * PPTX files can be attached without dragging the whole assistant chat module\n * into bundles that just want a prompt popover.\n */\nclass BinaryDocumentAttachmentAdapter implements AttachmentAdapter {\n public accept =\n \"application/pdf,application/vnd.openxmlformats-officedocument.presentationml.presentation,.pdf,.pptx\";\n\n public async add(state: { file: File }): Promise<PendingAttachment> {\n return {\n id: state.file.name,\n type: \"document\",\n name: state.file.name,\n contentType: state.file.type || \"application/octet-stream\",\n file: state.file,\n status: { type: \"requires-action\", reason: \"composer-send\" },\n };\n }\n\n public async send(\n attachment: PendingAttachment,\n ): Promise<CompleteAttachment> {\n return {\n ...attachment,\n status: { type: \"complete\" },\n content: [],\n };\n }\n\n public async remove() {\n /* noop */\n }\n}\n\nfunction getImageSrc(attachment: Attachment): string | null {\n if (attachment.type !== \"image\") return null;\n if (\"file\" in attachment && attachment.file) {\n return URL.createObjectURL(attachment.file);\n }\n const imagePart = attachment.content?.find((part) => part.type === \"image\");\n return imagePart && \"image\" in imagePart ? imagePart.image : null;\n}\n\nfunction AttachmentChip({\n attachment,\n onRemove,\n}: {\n attachment: Attachment;\n onRemove: (id: string) => void;\n}) {\n const src = useMemo(() => getImageSrc(attachment), [attachment]);\n useEffect(\n () => () => {\n if (src?.startsWith(\"blob:\")) URL.revokeObjectURL(src);\n },\n [src],\n );\n\n if (isPastedTextAttachmentName(attachment.name)) {\n return <PastedTextChip attachment={attachment} onRemove={onRemove} />;\n }\n\n if (src) {\n return (\n <div className=\"group relative h-16 w-16 overflow-hidden rounded-lg border border-border/70 bg-muted/50\">\n <img\n src={src}\n alt={attachment.name}\n className=\"h-full w-full object-cover\"\n />\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n aria-label={`Remove ${attachment.name}`}\n className=\"absolute right-1 top-1 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border/60 bg-background/90 text-muted-foreground hover:text-foreground\"\n >\n <IconX className=\"h-3 w-3\" />\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"group relative inline-flex max-w-[200px] items-center gap-2 rounded-md border border-border/70 bg-muted/50 px-2 py-1.5 text-xs\">\n <div className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded bg-background text-[9px] font-semibold uppercase text-muted-foreground\">\n {attachment.name.split(\".\").pop() || \"file\"}\n </div>\n <span className=\"min-w-0 truncate font-medium\">{attachment.name}</span>\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n aria-label={`Remove ${attachment.name}`}\n className=\"flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded text-muted-foreground hover:text-foreground\"\n >\n <IconX className=\"h-3 w-3\" />\n </button>\n </div>\n );\n}\n\nfunction PromptAttachmentStrip() {\n const attachments = useComposer((state) => state.attachments);\n const aui = useAui();\n\n const handleRemove = useCallback(\n (id: string) => {\n void aui.composer().attachment({ id }).remove();\n },\n [aui],\n );\n\n if (attachments.length === 0) return null;\n return (\n <div className=\"flex flex-wrap gap-2 px-2 pt-2\">\n {attachments.map((attachment) => (\n <AttachmentChip\n key={attachment.id}\n attachment={attachment}\n onRemove={handleRemove}\n />\n ))}\n </div>\n );\n}\n\nfunction PromptComposerInner({\n onSubmit,\n placeholder,\n disabled,\n autoFocus,\n className,\n draftScope,\n showModelSelector = true,\n voiceEnabled = true,\n attachmentsEnabled = true,\n onTextChange,\n composerRef,\n}: PromptComposerProps) {\n const localRef = useRef<TiptapComposerHandle>(null);\n const handleRef = composerRef ?? localRef;\n const models = useChatModels();\n\n useEffect(() => {\n if (!autoFocus) return;\n const id = window.setTimeout(() => {\n const target =\n typeof handleRef === \"object\" && handleRef && \"current\" in handleRef\n ? handleRef.current\n : null;\n target?.focus();\n }, 50);\n return () => window.clearTimeout(id);\n }, [autoFocus, handleRef]);\n\n const handleSubmit = useCallback(\n async (\n text: string,\n references: Reference[],\n attachments?: ReadonlyArray<unknown>,\n ) => {\n // PromptComposer hosts (NewWorkspaceAppFlow, create-extension, create-deck,\n // …) submit a single string prompt — they don't run the assistant-ui\n // attachment send pipeline. TiptapComposer auto-converts large pastes\n // into a \"Pasted text\" chip, which would otherwise disappear into an\n // unprocessed File. Inline the chip body back into the prompt text so\n // newlines and full content survive the round-trip.\n const files: File[] = [];\n const pastedTextBlocks: string[] = [];\n for (const att of attachments ?? []) {\n const a = att as Attachment;\n if (\"file\" in a && a.file instanceof File) {\n const file = a.file;\n if (isPastedTextAttachmentName(file.name)) {\n try {\n pastedTextBlocks.push(await file.text());\n } catch {\n // If we can't read it, fall back to surfacing it as a regular\n // attachment file rather than silently losing it.\n files.push(file);\n }\n } else {\n files.push(file);\n }\n }\n }\n const finalText = pastedTextBlocks.length\n ? [text.trim(), ...pastedTextBlocks].filter(Boolean).join(\"\\n\\n\")\n : text;\n onSubmit(finalText, files, references);\n },\n [onSubmit],\n );\n\n return (\n <div\n className={cn(\n \"agent-composer-area flex flex-col rounded-lg border border-input bg-background focus-within:ring-1 focus-within:ring-ring\",\n className,\n )}\n >\n <ComposerPrimitive.Root className=\"flex flex-col\">\n <PromptAttachmentStrip />\n <TiptapComposer\n focusRef={handleRef}\n disabled={disabled}\n placeholder={placeholder}\n onSubmit={handleSubmit}\n plusMenuMode={attachmentsEnabled ? \"upload-only\" : \"hidden\"}\n voiceEnabled={voiceEnabled}\n onTextChange={onTextChange}\n draftScope={draftScope}\n selectedModel={showModelSelector ? models.selectedModel : undefined}\n selectedEffort={showModelSelector ? models.selectedEffort : undefined}\n availableModels={\n showModelSelector ? models.availableModels : undefined\n }\n onModelChange={showModelSelector ? models.onModelChange : undefined}\n onEffortChange={showModelSelector ? models.onEffortChange : undefined}\n />\n </ComposerPrimitive.Root>\n </div>\n );\n}\n\n/**\n * Standalone composer that mirrors the agent sidebar's input experience —\n * voice dictation, file upload, model selector, submit-on-Enter — for use in\n * popovers and inline prompt forms (create tool, create deck, create dashboard,\n * the Dispatch new-app flow, etc.).\n *\n * The host owns submission: when the user presses Enter or clicks submit,\n * `onSubmit(text, files, references)` is called. PromptComposer runs its own\n * minimal assistant-ui runtime so it can be dropped into any subtree without\n * needing the outer chat to be mounted.\n */\nexport function PromptComposer(props: PromptComposerProps) {\n const attachmentAdapter = useMemo(\n () =>\n new CompositeAttachmentAdapter([\n new SimpleImageAttachmentAdapter(),\n new BinaryDocumentAttachmentAdapter(),\n new SimpleTextAttachmentAdapter(),\n ]),\n [],\n );\n const runtime = useLocalRuntime(NOOP_ADAPTER, {\n adapters: { attachments: attachmentAdapter },\n });\n\n return (\n <AssistantRuntimeProvider runtime={runtime}>\n <ThreadPrimitive.Root className=\"contents\">\n <PromptComposerInner {...props} />\n </ThreadPrimitive.Root>\n </AssistantRuntimeProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"PromptComposer.js","sourceRoot":"","sources":["../../../src/client/composer/PromptComposer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, type Ref } from \"react\";\nimport {\n AssistantRuntimeProvider,\n ComposerPrimitive,\n ThreadPrimitive,\n useAui,\n useComposer,\n useLocalRuntime,\n} from \"@assistant-ui/react\";\nimport type {\n Attachment,\n AttachmentAdapter,\n ChatModelAdapter,\n CompleteAttachment,\n PendingAttachment,\n} from \"@assistant-ui/react\";\nimport {\n CompositeAttachmentAdapter,\n SimpleImageAttachmentAdapter,\n SimpleTextAttachmentAdapter,\n} from \"@assistant-ui/react\";\nimport { IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { TiptapComposer, type TiptapComposerHandle } from \"./TiptapComposer.js\";\nimport type { Reference } from \"./types.js\";\nimport { useChatModels } from \"../use-chat-models.js\";\nimport { isPastedTextAttachmentName } from \"./pasted-text.js\";\nimport { PastedTextChip } from \"./PastedTextChip.js\";\n\nconst MAX_INLINE_TEXT_FILE_CHARS = 60_000;\n\n/**\n * Files the user attached via the \"+\" button in PromptComposer. The host owns\n * what to do with them — typically POST to a per-app upload endpoint and pass\n * the resulting URLs/paths into the prompt that gets sent to the agent.\n */\nexport type PromptComposerFile = File;\n\nexport interface PromptComposerProps {\n /** Called when the user submits the composer. */\n onSubmit: (\n text: string,\n files: PromptComposerFile[],\n references: Reference[],\n ) => void;\n placeholder?: string;\n disabled?: boolean;\n autoFocus?: boolean;\n className?: string;\n /** Forwarded to TiptapComposer for draft persistence. */\n draftScope?: string;\n /** Show the model selector (default: true). */\n showModelSelector?: boolean;\n /** Show the voice dictation button (default: true). */\n voiceEnabled?: boolean;\n /** Show file upload controls and pass submitted files to onSubmit (default: true). */\n attachmentsEnabled?: boolean;\n /** Called whenever the plain editor text changes. */\n onTextChange?: (text: string) => void;\n /** Imperative handle for focusing the composer. */\n composerRef?: Ref<TiptapComposerHandle>;\n}\n\n// Minimal pass-through adapter. PromptComposer always submits through\n// onSubmitOverride, so the runtime never actually calls this — but\n// `useLocalRuntime` needs *something* shaped like a ChatModelAdapter.\nconst NOOP_ADAPTER: ChatModelAdapter = {\n async *run() {\n return;\n },\n};\n\n/**\n * Local clone of AssistantChat's BinaryDocumentAttachmentAdapter so PDFs and\n * PPTX files can be attached without dragging the whole assistant chat module\n * into bundles that just want a prompt popover.\n */\nclass BinaryDocumentAttachmentAdapter implements AttachmentAdapter {\n public accept =\n \"application/pdf,application/vnd.openxmlformats-officedocument.presentationml.presentation,.pdf,.pptx\";\n\n public async add(state: { file: File }): Promise<PendingAttachment> {\n return {\n id: state.file.name,\n type: \"document\",\n name: state.file.name,\n contentType: state.file.type || \"application/octet-stream\",\n file: state.file,\n status: { type: \"requires-action\", reason: \"composer-send\" },\n };\n }\n\n public async send(\n attachment: PendingAttachment,\n ): Promise<CompleteAttachment> {\n return {\n ...attachment,\n status: { type: \"complete\" },\n content: [],\n };\n }\n\n public async remove() {\n /* noop */\n }\n}\n\nfunction isInlineableTextFile(file: File): boolean {\n if (file.type.startsWith(\"text/\")) return true;\n if (file.type === \"application/json\") return true;\n return /\\.(txt|md|markdown|csv|json|yaml|yml)$/i.test(file.name);\n}\n\nfunction formatInlineTextFile(name: string, text: string): string {\n const truncated = text.length > MAX_INLINE_TEXT_FILE_CHARS;\n const body = truncated ? text.slice(0, MAX_INLINE_TEXT_FILE_CHARS) : text;\n return [\n `<uploaded-text-file name=\"${name}\">`,\n body,\n truncated\n ? `[Truncated after ${MAX_INLINE_TEXT_FILE_CHARS} characters.]`\n : \"\",\n \"</uploaded-text-file>\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction getImageSrc(attachment: Attachment): string | null {\n if (attachment.type !== \"image\") return null;\n if (\"file\" in attachment && attachment.file) {\n return URL.createObjectURL(attachment.file);\n }\n const imagePart = attachment.content?.find((part) => part.type === \"image\");\n return imagePart && \"image\" in imagePart ? imagePart.image : null;\n}\n\nfunction AttachmentChip({\n attachment,\n onRemove,\n}: {\n attachment: Attachment;\n onRemove: (id: string) => void;\n}) {\n const src = useMemo(() => getImageSrc(attachment), [attachment]);\n useEffect(\n () => () => {\n if (src?.startsWith(\"blob:\")) URL.revokeObjectURL(src);\n },\n [src],\n );\n\n if (isPastedTextAttachmentName(attachment.name)) {\n return <PastedTextChip attachment={attachment} onRemove={onRemove} />;\n }\n\n if (src) {\n return (\n <div className=\"group relative h-16 w-16 overflow-hidden rounded-lg border border-border/70 bg-muted/50\">\n <img\n src={src}\n alt={attachment.name}\n className=\"h-full w-full object-cover\"\n />\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n aria-label={`Remove ${attachment.name}`}\n className=\"absolute right-1 top-1 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border/60 bg-background/90 text-muted-foreground hover:text-foreground\"\n >\n <IconX className=\"h-3 w-3\" />\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"group relative inline-flex max-w-[200px] items-center gap-2 rounded-md border border-border/70 bg-muted/50 px-2 py-1.5 text-xs\">\n <div className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded bg-background text-[9px] font-semibold uppercase text-muted-foreground\">\n {attachment.name.split(\".\").pop() || \"file\"}\n </div>\n <span className=\"min-w-0 truncate font-medium\">{attachment.name}</span>\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n aria-label={`Remove ${attachment.name}`}\n className=\"flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded text-muted-foreground hover:text-foreground\"\n >\n <IconX className=\"h-3 w-3\" />\n </button>\n </div>\n );\n}\n\nfunction PromptAttachmentStrip() {\n const attachments = useComposer((state) => state.attachments);\n const aui = useAui();\n\n const handleRemove = useCallback(\n (id: string) => {\n void aui.composer().attachment({ id }).remove();\n },\n [aui],\n );\n\n if (attachments.length === 0) return null;\n return (\n <div className=\"flex flex-wrap gap-2 px-2 pt-2\">\n {attachments.map((attachment) => (\n <AttachmentChip\n key={attachment.id}\n attachment={attachment}\n onRemove={handleRemove}\n />\n ))}\n </div>\n );\n}\n\nfunction PromptComposerInner({\n onSubmit,\n placeholder,\n disabled,\n autoFocus,\n className,\n draftScope,\n showModelSelector = true,\n voiceEnabled = true,\n attachmentsEnabled = true,\n onTextChange,\n composerRef,\n}: PromptComposerProps) {\n const localRef = useRef<TiptapComposerHandle>(null);\n const handleRef = composerRef ?? localRef;\n const models = useChatModels();\n\n useEffect(() => {\n if (!autoFocus) return;\n const id = window.setTimeout(() => {\n const target =\n typeof handleRef === \"object\" && handleRef && \"current\" in handleRef\n ? handleRef.current\n : null;\n target?.focus();\n }, 50);\n return () => window.clearTimeout(id);\n }, [autoFocus, handleRef]);\n\n const handleSubmit = useCallback(\n async (\n text: string,\n references: Reference[],\n attachments?: ReadonlyArray<unknown>,\n ) => {\n // PromptComposer hosts (NewWorkspaceAppFlow, create-extension, create-deck,\n // …) submit a single string prompt — they don't run the assistant-ui\n // attachment send pipeline. TiptapComposer auto-converts large pastes\n // into a \"Pasted text\" chip, which would otherwise disappear into an\n // unprocessed File. Inline the chip body back into the prompt text so\n // newlines and full content survive the round-trip.\n const files: File[] = [];\n const pastedTextBlocks: string[] = [];\n for (const att of attachments ?? []) {\n const a = att as Attachment;\n if (\"file\" in a && a.file instanceof File) {\n const file = a.file;\n if (isPastedTextAttachmentName(file.name)) {\n try {\n pastedTextBlocks.push(await file.text());\n } catch {\n // If we can't read it, fall back to surfacing it as a regular\n // attachment file rather than silently losing it.\n files.push(file);\n }\n } else {\n if (isInlineableTextFile(file)) {\n try {\n pastedTextBlocks.push(\n formatInlineTextFile(file.name, await file.text()),\n );\n } catch {\n // Keep the upload path fallback below.\n }\n }\n files.push(file);\n }\n }\n }\n const finalText = pastedTextBlocks.length\n ? [text.trim(), ...pastedTextBlocks].filter(Boolean).join(\"\\n\\n\")\n : text;\n onSubmit(finalText, files, references);\n },\n [onSubmit],\n );\n\n return (\n <div\n className={cn(\n \"agent-composer-area flex flex-col rounded-lg border border-input bg-background focus-within:ring-1 focus-within:ring-ring\",\n className,\n )}\n >\n <ComposerPrimitive.Root className=\"flex flex-col\">\n <PromptAttachmentStrip />\n <TiptapComposer\n focusRef={handleRef}\n disabled={disabled}\n placeholder={placeholder}\n onSubmit={handleSubmit}\n plusMenuMode={attachmentsEnabled ? \"upload-only\" : \"hidden\"}\n voiceEnabled={voiceEnabled}\n onTextChange={onTextChange}\n draftScope={draftScope}\n selectedModel={showModelSelector ? models.selectedModel : undefined}\n selectedEffort={showModelSelector ? models.selectedEffort : undefined}\n availableModels={\n showModelSelector ? models.availableModels : undefined\n }\n onModelChange={showModelSelector ? models.onModelChange : undefined}\n onEffortChange={showModelSelector ? models.onEffortChange : undefined}\n />\n </ComposerPrimitive.Root>\n </div>\n );\n}\n\n/**\n * Standalone composer that mirrors the agent sidebar's input experience —\n * voice dictation, file upload, model selector, submit-on-Enter — for use in\n * popovers and inline prompt forms (create tool, create deck, create dashboard,\n * the Dispatch new-app flow, etc.).\n *\n * The host owns submission: when the user presses Enter or clicks submit,\n * `onSubmit(text, files, references)` is called. PromptComposer runs its own\n * minimal assistant-ui runtime so it can be dropped into any subtree without\n * needing the outer chat to be mounted.\n */\nexport function PromptComposer(props: PromptComposerProps) {\n const attachmentAdapter = useMemo(\n () =>\n new CompositeAttachmentAdapter([\n new SimpleImageAttachmentAdapter(),\n new BinaryDocumentAttachmentAdapter(),\n new SimpleTextAttachmentAdapter(),\n ]),\n [],\n );\n const runtime = useLocalRuntime(NOOP_ADAPTER, {\n adapters: { attachments: attachmentAdapter },\n });\n\n return (\n <AssistantRuntimeProvider runtime={runtime}>\n <ThreadPrimitive.Root className=\"contents\">\n <PromptComposerInner {...props} />\n </ThreadPrimitive.Root>\n </AssistantRuntimeProvider>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"TiptapComposer.d.ts","sourceRoot":"","sources":["../../../src/client/composer/TiptapComposer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAgCf,OAAO,KAAK,EAGV,SAAS,EAGV,MAAM,YAAY,CAAC;AAWpB,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAO1C,MAAM,WAAW,oBAAoB;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAwHD,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjC,UAAU,mBAAmB;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CACT,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,EAAE,EACvB,WAAW,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,KACjC,IAAI,CAAC;IACV,qDAAqD;IACrD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,4FAA4F;IAC5F,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,0FAA0F;IAC1F,iBAAiB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACpC,qFAAqF;IACrF,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC5C,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,2CAA2C;IAC3C,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,uCAAuC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,kDAAkD;IAClD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC;IACjD;;;;;;;;OAQG;IACH,gCAAgC,CAAC,EAAE,OAAO,CAAC;CAC5C;AAkZD,wBAAgB,cAAc,CAAC,EAC7B,WAAgC,EAChC,QAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,YAAmB,EACnB,aAAa,EACb,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,UAAU,EACV,YAAqB,EACrB,gCAAwC,GACzC,EAAE,mBAAmB,2CAq6BrB"}
1
+ {"version":3,"file":"TiptapComposer.d.ts","sourceRoot":"","sources":["../../../src/client/composer/TiptapComposer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAgCf,OAAO,KAAK,EAGV,SAAS,EAGV,MAAM,YAAY,CAAC;AAWpB,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAO1C,MAAM,WAAW,oBAAoB;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AA0HD,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjC,UAAU,mBAAmB;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CACT,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,EAAE,EACvB,WAAW,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,KACjC,IAAI,CAAC;IACV,qDAAqD;IACrD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,4FAA4F;IAC5F,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,0FAA0F;IAC1F,iBAAiB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACpC,qFAAqF;IACrF,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC5C,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,2CAA2C;IAC3C,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,uCAAuC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,kDAAkD;IAClD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC;IACjD;;;;;;;;OAQG;IACH,gCAAgC,CAAC,EAAE,OAAO,CAAC;CAC5C;AAkZD,wBAAgB,cAAc,CAAC,EAC7B,WAAgC,EAChC,QAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,YAAmB,EACnB,aAAa,EACb,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,UAAU,EACV,YAAqB,EACrB,gCAAwC,GACzC,EAAE,mBAAmB,2CA67BrB"}
@@ -42,7 +42,7 @@ Follow the create-skill pattern to build this. Before writing:
42
42
 
43
43
  1. **Determine the skill name** — derive a hyphen-case name from the description (e.g. "code review" → "code-review")
44
44
  2. **Determine the skill type** — Pattern (architectural rule), Workflow (step-by-step), or Generator (scaffolding)
45
- 3. **Write the skill** as a personal resource at path "skills/<name>.md" using resource-write
45
+ 3. **Write the skill** as a personal resource at path "skills/<name>/SKILL.md" using resource-write
46
46
 
47
47
  The skill file MUST have YAML frontmatter with name and description (under 40 words), then markdown with:
48
48
  - Clear rule/purpose statement
@@ -95,7 +95,9 @@ Use the create-extension action with Alpine.js HTML content. The extension runs
95
95
 
96
96
  After creating the extension, navigate the user to it with set-url-path using pathname "/extensions/<id>".
97
97
 
98
- Make the extension functional and visually polished. Extensions can use extensionFetch() for external API calls, appAction()/appFetch() for app operations, extensionData for per-extension persistence, and dbQuery()/dbExec() only for existing app tables.`,
98
+ Make the extension functional and visually polished. Extensions can use extensionFetch() for external API calls, appAction()/appFetch() for app operations, extensionData for per-extension persistence, and dbQuery()/dbExec() only for existing app tables.
99
+
100
+ Prefer appAction()/appFetch() for app data. Some actions return JSON strings for CLI compatibility, so parse string results before counting rows or reading arrays. Do not guess raw SQL table names or columns for app data; use dbQuery()/dbExec() only when the table is known to exist in the current schema.`,
99
101
  },
100
102
  };
101
103
  function ComposerModeChip({ mode, onRemove, }) {
@@ -440,6 +442,29 @@ export function TiptapComposer({ placeholder = "Message agent...", disabled = fa
440
442
  }
441
443
  return false;
442
444
  },
445
+ handleDrop: (_view, event) => {
446
+ // Drag-and-drop files (decks, images, PDFs, etc.) into the composer.
447
+ // Without this, the browser navigates to the dropped file, which is
448
+ // surprising — users expect drop to attach the file like the "+" menu.
449
+ const dataTransfer = event.dataTransfer;
450
+ const droppedFiles = Array.from(dataTransfer?.files ?? []);
451
+ if (droppedFiles.length === 0)
452
+ return false;
453
+ event.preventDefault();
454
+ // Make image filenames unique so consecutive screenshots (all named
455
+ // `image.png`) don't collide on the attachment id, mirroring the
456
+ // paste handler's behavior.
457
+ const attachments = droppedFiles.map((file) => {
458
+ if (!file.type.startsWith("image/"))
459
+ return file;
460
+ const uniqueName = `${Date.now()}-${Math.random().toString(36).slice(2)}-${file.name}`;
461
+ return new File([file], uniqueName, { type: file.type });
462
+ });
463
+ void Promise.all(attachments.map((file) => composerRuntime.addAttachment(file))).catch((error) => {
464
+ console.error("Error adding dropped attachment:", error);
465
+ });
466
+ return true;
467
+ },
443
468
  handleKeyDown: (view, event) => {
444
469
  const pop = popoverStateRef.current;
445
470
  // Handle popover keyboard nav