@agent-native/dispatch 0.6.1 → 0.8.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 (341) hide show
  1. package/README.md +38 -1
  2. package/dist/actions/apply-dream-proposal.d.ts +3 -0
  3. package/dist/actions/apply-dream-proposal.d.ts.map +1 -0
  4. package/dist/actions/apply-dream-proposal.js +11 -0
  5. package/dist/actions/apply-dream-proposal.js.map +1 -0
  6. package/dist/actions/create-dream-report.d.ts +3 -0
  7. package/dist/actions/create-dream-report.d.ts.map +1 -0
  8. package/dist/actions/create-dream-report.js +67 -0
  9. package/dist/actions/create-dream-report.js.map +1 -0
  10. package/dist/actions/create-pylon-ticket.d.ts +3 -0
  11. package/dist/actions/create-pylon-ticket.d.ts.map +1 -0
  12. package/dist/actions/create-pylon-ticket.js +94 -0
  13. package/dist/actions/create-pylon-ticket.js.map +1 -0
  14. package/dist/actions/create-vault-grant.js +1 -1
  15. package/dist/actions/create-vault-grant.js.map +1 -1
  16. package/dist/actions/create-vault-secret.d.ts.map +1 -1
  17. package/dist/actions/create-vault-secret.js +4 -3
  18. package/dist/actions/create-vault-secret.js.map +1 -1
  19. package/dist/actions/create-workspace-resource.js +3 -3
  20. package/dist/actions/create-workspace-resource.js.map +1 -1
  21. package/dist/actions/delete-workspace-resource.js +1 -1
  22. package/dist/actions/delete-workspace-resource.js.map +1 -1
  23. package/dist/actions/ensure-dream-job.d.ts +3 -0
  24. package/dist/actions/ensure-dream-job.d.ts.map +1 -0
  25. package/dist/actions/ensure-dream-job.js +73 -0
  26. package/dist/actions/ensure-dream-job.js.map +1 -0
  27. package/dist/actions/get-dream-settings.d.ts +3 -0
  28. package/dist/actions/get-dream-settings.d.ts.map +1 -0
  29. package/dist/actions/get-dream-settings.js +11 -0
  30. package/dist/actions/get-dream-settings.js.map +1 -0
  31. package/dist/actions/get-dream.d.ts +3 -0
  32. package/dist/actions/get-dream.d.ts.map +1 -0
  33. package/dist/actions/get-dream.js +13 -0
  34. package/dist/actions/get-dream.js.map +1 -0
  35. package/dist/actions/get-vault-access-settings.d.ts +3 -0
  36. package/dist/actions/get-vault-access-settings.d.ts.map +1 -0
  37. package/dist/actions/get-vault-access-settings.js +10 -0
  38. package/dist/actions/get-vault-access-settings.js.map +1 -0
  39. package/dist/actions/get-workspace-resource-effective-context.d.ts +3 -0
  40. package/dist/actions/get-workspace-resource-effective-context.d.ts.map +1 -0
  41. package/dist/actions/get-workspace-resource-effective-context.js +27 -0
  42. package/dist/actions/get-workspace-resource-effective-context.js.map +1 -0
  43. package/dist/actions/grant-vault-secrets-to-app.js +1 -1
  44. package/dist/actions/grant-vault-secrets-to-app.js.map +1 -1
  45. package/dist/actions/index.d.ts.map +1 -1
  46. package/dist/actions/index.js +38 -4
  47. package/dist/actions/index.js.map +1 -1
  48. package/dist/actions/list-dream-candidates.d.ts +3 -0
  49. package/dist/actions/list-dream-candidates.d.ts.map +1 -0
  50. package/dist/actions/list-dream-candidates.js +68 -0
  51. package/dist/actions/list-dream-candidates.js.map +1 -0
  52. package/dist/actions/list-dreams.d.ts +3 -0
  53. package/dist/actions/list-dreams.d.ts.map +1 -0
  54. package/dist/actions/list-dreams.js +17 -0
  55. package/dist/actions/list-dreams.js.map +1 -0
  56. package/dist/actions/list-integrations-catalog.js +1 -1
  57. package/dist/actions/list-integrations-catalog.js.map +1 -1
  58. package/dist/actions/list-vault-grants.js +1 -1
  59. package/dist/actions/list-vault-grants.js.map +1 -1
  60. package/dist/actions/list-workspace-apps.d.ts.map +1 -1
  61. package/dist/actions/list-workspace-apps.js +5 -1
  62. package/dist/actions/list-workspace-apps.js.map +1 -1
  63. package/dist/actions/list-workspace-resources-for-app.d.ts +3 -0
  64. package/dist/actions/list-workspace-resources-for-app.d.ts.map +1 -0
  65. package/dist/actions/list-workspace-resources-for-app.js +12 -0
  66. package/dist/actions/list-workspace-resources-for-app.js.map +1 -0
  67. package/dist/actions/list-workspace-resources.js +1 -1
  68. package/dist/actions/list-workspace-resources.js.map +1 -1
  69. package/dist/actions/navigate.d.ts +1 -0
  70. package/dist/actions/navigate.d.ts.map +1 -1
  71. package/dist/actions/navigate.js +2 -1
  72. package/dist/actions/navigate.js.map +1 -1
  73. package/dist/actions/preview-dream-proposal.d.ts +3 -0
  74. package/dist/actions/preview-dream-proposal.d.ts.map +1 -0
  75. package/dist/actions/preview-dream-proposal.js +13 -0
  76. package/dist/actions/preview-dream-proposal.js.map +1 -0
  77. package/dist/actions/preview-workspace-resource-change.d.ts +3 -0
  78. package/dist/actions/preview-workspace-resource-change.d.ts.map +1 -0
  79. package/dist/actions/preview-workspace-resource-change.js +24 -0
  80. package/dist/actions/preview-workspace-resource-change.js.map +1 -0
  81. package/dist/actions/reject-dream-proposal.d.ts +3 -0
  82. package/dist/actions/reject-dream-proposal.d.ts.map +1 -0
  83. package/dist/actions/reject-dream-proposal.js +12 -0
  84. package/dist/actions/reject-dream-proposal.js.map +1 -0
  85. package/dist/actions/restore-starter-workspace-resources.d.ts +3 -0
  86. package/dist/actions/restore-starter-workspace-resources.d.ts.map +1 -0
  87. package/dist/actions/restore-starter-workspace-resources.js +14 -0
  88. package/dist/actions/restore-starter-workspace-resources.js.map +1 -0
  89. package/dist/actions/send-code-agent-remote-command.d.ts +3 -0
  90. package/dist/actions/send-code-agent-remote-command.d.ts.map +1 -0
  91. package/dist/actions/send-code-agent-remote-command.js +53 -0
  92. package/dist/actions/send-code-agent-remote-command.js.map +1 -0
  93. package/dist/actions/set-dream-settings.d.ts +3 -0
  94. package/dist/actions/set-dream-settings.d.ts.map +1 -0
  95. package/dist/actions/set-dream-settings.js +41 -0
  96. package/dist/actions/set-dream-settings.js.map +1 -0
  97. package/dist/actions/set-vault-access-settings.d.ts +3 -0
  98. package/dist/actions/set-vault-access-settings.d.ts.map +1 -0
  99. package/dist/actions/set-vault-access-settings.js +13 -0
  100. package/dist/actions/set-vault-access-settings.js.map +1 -0
  101. package/dist/actions/start-workspace-app-creation.d.ts.map +1 -1
  102. package/dist/actions/start-workspace-app-creation.js +6 -0
  103. package/dist/actions/start-workspace-app-creation.js.map +1 -1
  104. package/dist/actions/sync-vault-to-app.js +1 -1
  105. package/dist/actions/sync-vault-to-app.js.map +1 -1
  106. package/dist/actions/update-workspace-app-metadata.d.ts +3 -0
  107. package/dist/actions/update-workspace-app-metadata.d.ts.map +1 -0
  108. package/dist/actions/update-workspace-app-metadata.js +30 -0
  109. package/dist/actions/update-workspace-app-metadata.js.map +1 -0
  110. package/dist/actions/update-workspace-resource.js +1 -1
  111. package/dist/actions/update-workspace-resource.js.map +1 -1
  112. package/dist/actions/view-screen.d.ts.map +1 -1
  113. package/dist/actions/view-screen.js +77 -4
  114. package/dist/actions/view-screen.js.map +1 -1
  115. package/dist/components/app-keys-popover.js +16 -5
  116. package/dist/components/app-keys-popover.js.map +1 -1
  117. package/dist/components/approval-value-block.d.ts +7 -0
  118. package/dist/components/approval-value-block.d.ts.map +1 -0
  119. package/dist/components/approval-value-block.js +22 -0
  120. package/dist/components/approval-value-block.js.map +1 -0
  121. package/dist/components/create-app-popover.d.ts.map +1 -1
  122. package/dist/components/create-app-popover.js +41 -16
  123. package/dist/components/create-app-popover.js.map +1 -1
  124. package/dist/components/dispatch-shell.d.ts +4 -4
  125. package/dist/components/dispatch-shell.d.ts.map +1 -1
  126. package/dist/components/dispatch-shell.js +6 -6
  127. package/dist/components/dispatch-shell.js.map +1 -1
  128. package/dist/components/layout/Layout.d.ts.map +1 -1
  129. package/dist/components/layout/Layout.js +18 -4
  130. package/dist/components/layout/Layout.js.map +1 -1
  131. package/dist/components/messaging-setup-panel.d.ts.map +1 -1
  132. package/dist/components/messaging-setup-panel.js +2 -2
  133. package/dist/components/messaging-setup-panel.js.map +1 -1
  134. package/dist/components/ui/chart.d.ts +1 -1
  135. package/dist/components/workspace-app-card.d.ts.map +1 -1
  136. package/dist/components/workspace-app-card.js +63 -3
  137. package/dist/components/workspace-app-card.js.map +1 -1
  138. package/dist/components/workspace-resource-effective-stack.d.ts +11 -0
  139. package/dist/components/workspace-resource-effective-stack.d.ts.map +1 -0
  140. package/dist/components/workspace-resource-effective-stack.js +59 -0
  141. package/dist/components/workspace-resource-effective-stack.js.map +1 -0
  142. package/dist/components/workspace-resource-impact-preview.d.ts +9 -0
  143. package/dist/components/workspace-resource-impact-preview.d.ts.map +1 -0
  144. package/dist/components/workspace-resource-impact-preview.js +39 -0
  145. package/dist/components/workspace-resource-impact-preview.js.map +1 -0
  146. package/dist/db/migrations.d.ts.map +1 -1
  147. package/dist/db/migrations.js +59 -0
  148. package/dist/db/migrations.js.map +1 -1
  149. package/dist/db/schema.d.ts +714 -0
  150. package/dist/db/schema.d.ts.map +1 -1
  151. package/dist/db/schema.js +44 -2
  152. package/dist/db/schema.js.map +1 -1
  153. package/dist/hooks/use-navigation-state.d.ts +3 -0
  154. package/dist/hooks/use-navigation-state.d.ts.map +1 -1
  155. package/dist/hooks/use-navigation-state.js +35 -8
  156. package/dist/hooks/use-navigation-state.js.map +1 -1
  157. package/dist/lib/catch-all-target.d.ts +2 -0
  158. package/dist/lib/catch-all-target.d.ts.map +1 -0
  159. package/dist/lib/catch-all-target.js +95 -0
  160. package/dist/lib/catch-all-target.js.map +1 -0
  161. package/dist/lib/utils.d.ts +2 -1
  162. package/dist/lib/utils.d.ts.map +1 -1
  163. package/dist/lib/utils.js +5 -1
  164. package/dist/lib/utils.js.map +1 -1
  165. package/dist/lib/workspace-apps.d.ts +9 -0
  166. package/dist/lib/workspace-apps.d.ts.map +1 -1
  167. package/dist/lib/workspace-apps.js.map +1 -1
  168. package/dist/routes/index.d.ts.map +1 -1
  169. package/dist/routes/index.js +1 -0
  170. package/dist/routes/index.js.map +1 -1
  171. package/dist/routes/pages/$appId.d.ts +2 -2
  172. package/dist/routes/pages/$appId.d.ts.map +1 -1
  173. package/dist/routes/pages/$appId.js +17 -8
  174. package/dist/routes/pages/$appId.js.map +1 -1
  175. package/dist/routes/pages/approval.d.ts.map +1 -1
  176. package/dist/routes/pages/approval.js +4 -1
  177. package/dist/routes/pages/approval.js.map +1 -1
  178. package/dist/routes/pages/approvals.js +1 -1
  179. package/dist/routes/pages/approvals.js.map +1 -1
  180. package/dist/routes/pages/dream-settings.d.ts +34 -0
  181. package/dist/routes/pages/dream-settings.d.ts.map +1 -0
  182. package/dist/routes/pages/dream-settings.js +68 -0
  183. package/dist/routes/pages/dream-settings.js.map +1 -0
  184. package/dist/routes/pages/dreams.d.ts +5 -0
  185. package/dist/routes/pages/dreams.d.ts.map +1 -0
  186. package/dist/routes/pages/dreams.js +435 -0
  187. package/dist/routes/pages/dreams.js.map +1 -0
  188. package/dist/routes/pages/integrations.d.ts.map +1 -1
  189. package/dist/routes/pages/integrations.js +20 -15
  190. package/dist/routes/pages/integrations.js.map +1 -1
  191. package/dist/routes/pages/new-app.js +1 -1
  192. package/dist/routes/pages/new-app.js.map +1 -1
  193. package/dist/routes/pages/overview.d.ts.map +1 -1
  194. package/dist/routes/pages/overview.js +5 -1
  195. package/dist/routes/pages/overview.js.map +1 -1
  196. package/dist/routes/pages/vault.d.ts.map +1 -1
  197. package/dist/routes/pages/vault.js +23 -5
  198. package/dist/routes/pages/vault.js.map +1 -1
  199. package/dist/routes/pages/workspace.d.ts.map +1 -1
  200. package/dist/routes/pages/workspace.js +187 -35
  201. package/dist/routes/pages/workspace.js.map +1 -1
  202. package/dist/server/lib/app-creation-store.d.ts +13 -0
  203. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  204. package/dist/server/lib/app-creation-store.js +298 -11
  205. package/dist/server/lib/app-creation-store.js.map +1 -1
  206. package/dist/server/lib/dispatch-integrations.d.ts +1 -1
  207. package/dist/server/lib/dispatch-integrations.d.ts.map +1 -1
  208. package/dist/server/lib/dispatch-integrations.js +9 -4
  209. package/dist/server/lib/dispatch-integrations.js.map +1 -1
  210. package/dist/server/lib/dispatch-remote-commands.d.ts +83 -0
  211. package/dist/server/lib/dispatch-remote-commands.d.ts.map +1 -0
  212. package/dist/server/lib/dispatch-remote-commands.js +256 -0
  213. package/dist/server/lib/dispatch-remote-commands.js.map +1 -0
  214. package/dist/server/lib/dispatch-store.d.ts +26 -0
  215. package/dist/server/lib/dispatch-store.d.ts.map +1 -1
  216. package/dist/server/lib/dispatch-store.js +17 -1
  217. package/dist/server/lib/dispatch-store.js.map +1 -1
  218. package/dist/server/lib/dreams-store.d.ts +398 -0
  219. package/dist/server/lib/dreams-store.d.ts.map +1 -0
  220. package/dist/server/lib/dreams-store.js +2330 -0
  221. package/dist/server/lib/dreams-store.js.map +1 -0
  222. package/dist/server/lib/env-config.d.ts.map +1 -1
  223. package/dist/server/lib/env-config.js +5 -0
  224. package/dist/server/lib/env-config.js.map +1 -1
  225. package/dist/server/lib/onboarding-steps.d.ts +12 -0
  226. package/dist/server/lib/onboarding-steps.d.ts.map +1 -0
  227. package/dist/server/lib/onboarding-steps.js +47 -0
  228. package/dist/server/lib/onboarding-steps.js.map +1 -0
  229. package/dist/server/lib/thread-debug-store.d.ts +2 -2
  230. package/dist/server/lib/vault-store.d.ts +55 -0
  231. package/dist/server/lib/vault-store.d.ts.map +1 -1
  232. package/dist/server/lib/vault-store.js +210 -41
  233. package/dist/server/lib/vault-store.js.map +1 -1
  234. package/dist/server/lib/workspace-resources-store.d.ts +181 -17
  235. package/dist/server/lib/workspace-resources-store.d.ts.map +1 -1
  236. package/dist/server/lib/workspace-resources-store.js +737 -108
  237. package/dist/server/lib/workspace-resources-store.js.map +1 -1
  238. package/dist/server/plugins/agent-chat.d.ts.map +1 -1
  239. package/dist/server/plugins/agent-chat.js +2 -1
  240. package/dist/server/plugins/agent-chat.js.map +1 -1
  241. package/dist/server/plugins/core-routes.d.ts.map +1 -1
  242. package/dist/server/plugins/core-routes.js +4 -0
  243. package/dist/server/plugins/core-routes.js.map +1 -1
  244. package/dist/server/plugins/integrations.js +2 -2
  245. package/dist/server/plugins/integrations.js.map +1 -1
  246. package/package.json +15 -11
  247. package/src/actions/apply-dream-proposal.ts +12 -0
  248. package/src/actions/create-dream-report.ts +76 -0
  249. package/src/actions/create-pylon-ticket.ts +109 -0
  250. package/src/actions/create-vault-grant.ts +1 -1
  251. package/src/actions/create-vault-secret.ts +4 -3
  252. package/src/actions/create-workspace-resource.ts +3 -3
  253. package/src/actions/delete-workspace-resource.ts +1 -1
  254. package/src/actions/ensure-dream-job.ts +76 -0
  255. package/src/actions/get-dream-settings.ts +12 -0
  256. package/src/actions/get-dream.ts +14 -0
  257. package/src/actions/get-vault-access-settings.ts +11 -0
  258. package/src/actions/get-workspace-resource-effective-context.ts +34 -0
  259. package/src/actions/grant-vault-secrets-to-app.ts +1 -1
  260. package/src/actions/index.spec.ts +26 -0
  261. package/src/actions/index.ts +39 -4
  262. package/src/actions/list-dream-candidates.ts +77 -0
  263. package/src/actions/list-dreams.ts +17 -0
  264. package/src/actions/list-integrations-catalog.ts +1 -1
  265. package/src/actions/list-vault-grants.ts +1 -1
  266. package/src/actions/list-workspace-apps.ts +5 -1
  267. package/src/actions/list-workspace-resources-for-app.ts +13 -0
  268. package/src/actions/list-workspace-resources.ts +1 -1
  269. package/src/actions/navigate.ts +2 -1
  270. package/src/actions/preview-dream-proposal.ts +14 -0
  271. package/src/actions/preview-workspace-resource-change.ts +25 -0
  272. package/src/actions/reject-dream-proposal.ts +12 -0
  273. package/src/actions/restore-starter-workspace-resources.ts +17 -0
  274. package/src/actions/send-code-agent-remote-command.ts +59 -0
  275. package/src/actions/set-dream-settings.spec.ts +81 -0
  276. package/src/actions/set-dream-settings.ts +44 -0
  277. package/src/actions/set-vault-access-settings.ts +16 -0
  278. package/src/actions/start-workspace-app-creation.ts +8 -0
  279. package/src/actions/sync-vault-to-app.ts +1 -1
  280. package/src/actions/update-workspace-app-metadata.ts +32 -0
  281. package/src/actions/update-workspace-resource.ts +1 -1
  282. package/src/actions/view-screen.ts +94 -3
  283. package/src/components/app-keys-popover.tsx +23 -7
  284. package/src/components/approval-value-block.spec.tsx +59 -0
  285. package/src/components/approval-value-block.tsx +33 -0
  286. package/src/components/create-app-popover.tsx +50 -16
  287. package/src/components/dispatch-shell.tsx +16 -15
  288. package/src/components/layout/Layout.tsx +19 -5
  289. package/src/components/messaging-setup-panel.tsx +54 -39
  290. package/src/components/workspace-app-card.tsx +268 -1
  291. package/src/components/workspace-resource-effective-stack.spec.tsx +125 -0
  292. package/src/components/workspace-resource-effective-stack.tsx +141 -0
  293. package/src/components/workspace-resource-impact-preview.spec.tsx +147 -0
  294. package/src/components/workspace-resource-impact-preview.tsx +116 -0
  295. package/src/db/migrations.ts +59 -0
  296. package/src/db/schema.ts +46 -2
  297. package/src/hooks/use-navigation-state.ts +34 -9
  298. package/src/lib/catch-all-target.spec.ts +218 -0
  299. package/src/lib/catch-all-target.ts +99 -0
  300. package/src/lib/utils.ts +6 -1
  301. package/src/lib/workspace-apps.ts +9 -0
  302. package/src/routes/index.ts +1 -0
  303. package/src/routes/pages/$appId.tsx +21 -8
  304. package/src/routes/pages/approval.tsx +14 -1
  305. package/src/routes/pages/approvals.tsx +1 -1
  306. package/src/routes/pages/dream-settings.spec.ts +130 -0
  307. package/src/routes/pages/dream-settings.ts +103 -0
  308. package/src/routes/pages/dreams.tsx +1828 -0
  309. package/src/routes/pages/integrations.tsx +57 -18
  310. package/src/routes/pages/new-app.tsx +1 -1
  311. package/src/routes/pages/overview.tsx +11 -3
  312. package/src/routes/pages/vault.tsx +76 -9
  313. package/src/routes/pages/workspace.tsx +577 -97
  314. package/src/server/lib/app-creation-store.spec.ts +61 -2
  315. package/src/server/lib/app-creation-store.ts +389 -13
  316. package/src/server/lib/dispatch-integrations.ts +10 -3
  317. package/src/server/lib/dispatch-remote-commands.spec.ts +167 -0
  318. package/src/server/lib/dispatch-remote-commands.ts +375 -0
  319. package/src/server/lib/dispatch-store.ts +37 -1
  320. package/src/server/lib/dreams-store.spec.ts +1492 -0
  321. package/src/server/lib/dreams-store.ts +3168 -0
  322. package/src/server/lib/env-config.ts +5 -0
  323. package/src/server/lib/onboarding-steps.ts +49 -0
  324. package/src/server/lib/vault-store.spec.ts +69 -0
  325. package/src/server/lib/vault-store.ts +266 -49
  326. package/src/server/lib/workspace-resource-approval-lifecycle.spec.ts +236 -0
  327. package/src/server/lib/workspace-resources-store.spec.ts +1106 -0
  328. package/src/server/lib/workspace-resources-store.ts +1001 -134
  329. package/src/server/plugins/agent-chat.ts +2 -1
  330. package/src/server/plugins/core-routes.ts +5 -0
  331. package/src/server/plugins/integrations.ts +2 -2
  332. package/dist/actions/sync-workspace-resources-to-all.d.ts +0 -3
  333. package/dist/actions/sync-workspace-resources-to-all.d.ts.map +0 -1
  334. package/dist/actions/sync-workspace-resources-to-all.js +0 -9
  335. package/dist/actions/sync-workspace-resources-to-all.js.map +0 -1
  336. package/dist/actions/sync-workspace-resources-to-app.d.ts +0 -3
  337. package/dist/actions/sync-workspace-resources-to-app.d.ts.map +0 -1
  338. package/dist/actions/sync-workspace-resources-to-app.js +0 -11
  339. package/dist/actions/sync-workspace-resources-to-app.js.map +0 -1
  340. package/src/actions/sync-workspace-resources-to-all.ts +0 -10
  341. package/src/actions/sync-workspace-resources-to-app.ts +0 -12
@@ -3,14 +3,15 @@ import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { getSetting, putSetting } from "@agent-native/core/settings";
6
+ import { assertValidWorkspaceAppId } from "@agent-native/core/shared";
6
7
  import { getBuilderBranchProjectId, getRequestContext, isIntegrationCallerRequest, resolveBuilderBranchProjectId, resolveBuilderCredentials, runBuilderAgent, } from "@agent-native/core/server";
7
8
  import { getDbExec } from "@agent-native/core/db";
8
- import { assertValidWorkspaceAppId } from "@agent-native/core/shared";
9
9
  import { currentOrgId, currentOwnerEmail, recordAudit, resolveLinkedOwner, } from "./dispatch-store.js";
10
10
  import { identityKeyForIncoming } from "./dispatch-integrations.js";
11
11
  import { createRequest, listSecrets } from "./vault-store.js";
12
12
  import { grantWorkspaceResourcesToApp, listWorkspaceResourceOptions, } from "./workspace-resources-store.js";
13
13
  const SETTINGS_KEY = "dispatch-app-creation-settings";
14
+ const WORKSPACE_APP_METADATA_SETTINGS_KEY = "workspace-app-metadata";
14
15
  const WORKSPACE_APPS_ENV_KEY = "AGENT_NATIVE_WORKSPACE_APPS_JSON";
15
16
  const WORKSPACE_APPS_MANIFEST_FILE = "workspace-apps.json";
16
17
  const WORKSPACE_APPS_GATEWAY_PATH = "/_workspace/apps";
@@ -18,6 +19,7 @@ const WORKSPACE_APPS_GATEWAY_TIMEOUT_MS = 1_000;
18
19
  const MAX_PENDING_APPS = 50;
19
20
  const AGENT_CARD_PATH = "/.well-known/agent-card.json";
20
21
  const AGENT_CARD_FETCH_TIMEOUT_MS = 1_500;
22
+ const DEFAULT_WORKSPACE_APP_AUDIENCE = "internal";
21
23
  function readJson(file) {
22
24
  try {
23
25
  return JSON.parse(fs.readFileSync(file, "utf8"));
@@ -47,18 +49,145 @@ function titleCase(value) {
47
49
  .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
48
50
  .join(" ");
49
51
  }
52
+ function normalizeWhitespace(value) {
53
+ return value.replace(/\s+/g, " ").trim();
54
+ }
55
+ function ensureSentence(value) {
56
+ if (!value)
57
+ return value;
58
+ const capitalized = value.charAt(0).toUpperCase() + value.slice(1);
59
+ return /[.!?]$/.test(capitalized) ? capitalized : `${capitalized}.`;
60
+ }
61
+ function clipSentence(value, max = 180) {
62
+ if (value.length <= max)
63
+ return value;
64
+ const clipped = value
65
+ .slice(0, max - 1)
66
+ .replace(/\s+\S*$/, "")
67
+ .trim();
68
+ return `${clipped || value.slice(0, max - 1).trim()}…`;
69
+ }
70
+ export function generateWorkspaceAppDescription(prompt, appId) {
71
+ const cleaned = normalizeWhitespace(prompt)
72
+ .replace(/^(please\s+)?(build|create|make|generate|scaffold)\s+(me\s+|us\s+)?/i, "")
73
+ .replace(/^(an?\s+)?(workspace\s+)?(agent-native\s+)?(app|tool)\s+(that|to|for)\s+/i, "")
74
+ .replace(/^(an?\s+)?(dashboard|workspace|agent)\s+(that|to|for)\s+/i, "");
75
+ if (!cleaned)
76
+ return `Workspace app for ${titleCase(appId)}.`;
77
+ return clipSentence(ensureSentence(cleaned));
78
+ }
50
79
  function scopedSettingsKey() {
51
80
  const orgId = currentOrgId();
52
81
  if (orgId)
53
82
  return `${SETTINGS_KEY}:org:${orgId}`;
54
83
  return `${SETTINGS_KEY}:user:${currentOwnerEmail()}`;
55
84
  }
85
+ function workspaceAppMetadataSettingsKey() {
86
+ const orgId = currentOrgId();
87
+ if (orgId)
88
+ return `${WORKSPACE_APP_METADATA_SETTINGS_KEY}:org:${orgId}`;
89
+ return `${WORKSPACE_APP_METADATA_SETTINGS_KEY}:user:${currentOwnerEmail()}`;
90
+ }
56
91
  async function readSettingsRecord() {
57
92
  const raw = await getSetting(scopedSettingsKey()).catch(() => null);
58
93
  return raw && typeof raw === "object" && !Array.isArray(raw)
59
94
  ? raw
60
95
  : {};
61
96
  }
97
+ function cleanOptionalText(value) {
98
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
99
+ }
100
+ function parseWorkspaceAppMetadataSettings(raw) {
101
+ const record = raw && typeof raw === "object" && !Array.isArray(raw)
102
+ ? raw
103
+ : {};
104
+ const rawApps = record.apps &&
105
+ typeof record.apps === "object" &&
106
+ !Array.isArray(record.apps)
107
+ ? record.apps
108
+ : {};
109
+ const apps = {};
110
+ for (const [id, value] of Object.entries(rawApps)) {
111
+ if (!id.trim() || !value || typeof value !== "object")
112
+ continue;
113
+ const item = value;
114
+ const override = {};
115
+ const name = cleanOptionalText(item.name);
116
+ const description = cleanOptionalText(item.description);
117
+ const sourcePrompt = cleanOptionalText(item.sourcePrompt);
118
+ const updatedAt = cleanOptionalText(item.updatedAt);
119
+ const updatedBy = cleanOptionalText(item.updatedBy);
120
+ if (name)
121
+ override.name = name;
122
+ if (description)
123
+ override.description = description;
124
+ if (item.generated === true)
125
+ override.generated = true;
126
+ if (sourcePrompt)
127
+ override.sourcePrompt = sourcePrompt;
128
+ if (updatedAt)
129
+ override.updatedAt = updatedAt;
130
+ if (updatedBy)
131
+ override.updatedBy = updatedBy;
132
+ if (Object.keys(override).length > 0)
133
+ apps[id.trim()] = override;
134
+ }
135
+ return { apps };
136
+ }
137
+ async function readWorkspaceAppMetadataSettings() {
138
+ const raw = await getSetting(workspaceAppMetadataSettingsKey()).catch(() => null);
139
+ return parseWorkspaceAppMetadataSettings(raw);
140
+ }
141
+ async function writeWorkspaceAppMetadataOverride(input) {
142
+ const key = workspaceAppMetadataSettingsKey();
143
+ const current = parseWorkspaceAppMetadataSettings(await getSetting(key).catch(() => null));
144
+ const appId = input.appId.trim();
145
+ const existing = current.apps[appId] ?? {};
146
+ const next = {
147
+ ...existing,
148
+ updatedAt: new Date().toISOString(),
149
+ };
150
+ const name = cleanOptionalText(input.name);
151
+ const description = cleanOptionalText(input.description);
152
+ const sourcePrompt = cleanOptionalText(input.sourcePrompt);
153
+ const updatedBy = cleanOptionalText(input.updatedBy);
154
+ if (name)
155
+ next.name = name;
156
+ else
157
+ delete next.name;
158
+ if (description)
159
+ next.description = description;
160
+ else
161
+ delete next.description;
162
+ if (input.generated === true)
163
+ next.generated = true;
164
+ else if (input.generated === false)
165
+ delete next.generated;
166
+ if (sourcePrompt)
167
+ next.sourcePrompt = sourcePrompt;
168
+ if (updatedBy)
169
+ next.updatedBy = updatedBy;
170
+ current.apps[appId] = next;
171
+ await putSetting(key, { apps: current.apps });
172
+ return current;
173
+ }
174
+ function applyWorkspaceAppMetadataOverride(app, settings) {
175
+ const override = settings.apps[app.id];
176
+ if (!override)
177
+ return app;
178
+ const name = cleanOptionalText(override.name);
179
+ const description = cleanOptionalText(override.description);
180
+ const generated = override.generated === true;
181
+ const shouldApplyName = !!name && !generated;
182
+ const shouldApplyDescription = !!description && (!generated || !cleanOptionalText(app.description));
183
+ if (!shouldApplyName && !shouldApplyDescription)
184
+ return app;
185
+ return {
186
+ ...app,
187
+ ...(shouldApplyName ? { name } : {}),
188
+ ...(shouldApplyDescription ? { description } : {}),
189
+ };
190
+ }
62
191
  function workspaceAppUrl(appPath) {
63
192
  const base = process.env.WORKSPACE_GATEWAY_URL ||
64
193
  process.env.APP_URL ||
@@ -88,6 +217,71 @@ function workspaceAppLink(appPath, explicitUrl) {
88
217
  return urlValue;
89
218
  }
90
219
  }
220
+ function normalizeWorkspaceAppAudience(value) {
221
+ return value === "public" ? "public" : DEFAULT_WORKSPACE_APP_AUDIENCE;
222
+ }
223
+ function normalizeWorkspaceAppPathList(value) {
224
+ let rawPaths = [];
225
+ if (Array.isArray(value)) {
226
+ rawPaths = value;
227
+ }
228
+ else if (typeof value === "string") {
229
+ const trimmed = value.trim();
230
+ if (!trimmed)
231
+ return [];
232
+ try {
233
+ const parsed = JSON.parse(trimmed);
234
+ rawPaths = Array.isArray(parsed) ? parsed : [trimmed];
235
+ }
236
+ catch {
237
+ rawPaths = trimmed.split(",");
238
+ }
239
+ }
240
+ const paths = rawPaths
241
+ .map((entry) => (typeof entry === "string" ? entry.trim() : ""))
242
+ .filter((entry) => entry.startsWith("/"))
243
+ .map((entry) => entry.length > 1 && entry.endsWith("/") ? entry.slice(0, -1) : entry);
244
+ return Array.from(new Set(paths));
245
+ }
246
+ function workspaceAppAudienceFromPackageJson(pkg) {
247
+ if (!pkg || typeof pkg !== "object" || Array.isArray(pkg))
248
+ return undefined;
249
+ const record = pkg;
250
+ const config = record["agent-native"] ?? record.agentNative;
251
+ const nested = config && typeof config === "object" && !Array.isArray(config)
252
+ ? config
253
+ : {};
254
+ const raw = nested.workspaceApp?.audience ??
255
+ nested.workspace?.audience ??
256
+ nested.audience ??
257
+ record.workspaceAppAudience;
258
+ if (raw === undefined)
259
+ return undefined;
260
+ return normalizeWorkspaceAppAudience(raw);
261
+ }
262
+ function workspaceAppRouteAccessFromPackageJson(pkg) {
263
+ if (!pkg || typeof pkg !== "object" || Array.isArray(pkg)) {
264
+ return { publicPaths: [], protectedPaths: [] };
265
+ }
266
+ const record = pkg;
267
+ const config = record["agent-native"] ?? record.agentNative;
268
+ const nested = config && typeof config === "object" && !Array.isArray(config)
269
+ ? config
270
+ : {};
271
+ return {
272
+ publicPaths: normalizeWorkspaceAppPathList(nested.workspaceApp?.publicPaths ??
273
+ nested.workspaceApp?.publicPagePaths ??
274
+ nested.workspace?.publicPaths ??
275
+ nested.publicPaths ??
276
+ record.workspaceAppPublicPaths),
277
+ protectedPaths: normalizeWorkspaceAppPathList(nested.workspaceApp?.protectedPaths ??
278
+ nested.workspaceApp?.privatePaths ??
279
+ nested.workspaceApp?.authRequiredPaths ??
280
+ nested.workspace?.protectedPaths ??
281
+ nested.protectedPaths ??
282
+ record.workspaceAppProtectedPaths),
283
+ };
284
+ }
91
285
  function parseWorkspaceAppsManifest(parsed) {
92
286
  const rawApps = Array.isArray(parsed?.apps)
93
287
  ? parsed.apps
@@ -115,6 +309,11 @@ function parseWorkspaceAppsManifest(parsed) {
115
309
  isDispatch: typeof entry.isDispatch === "boolean"
116
310
  ? entry.isDispatch
117
311
  : id === "dispatch",
312
+ audience: entry.audience === undefined
313
+ ? DEFAULT_WORKSPACE_APP_AUDIENCE
314
+ : normalizeWorkspaceAppAudience(entry.audience),
315
+ publicPaths: normalizeWorkspaceAppPathList(entry.publicPaths),
316
+ protectedPaths: normalizeWorkspaceAppPathList(entry.protectedPaths),
118
317
  status: "ready",
119
318
  };
120
319
  })
@@ -164,6 +363,9 @@ function parsePendingWorkspaceApps(value) {
164
363
  projectId: typeof record.projectId === "string" && record.projectId.trim()
165
364
  ? record.projectId.trim()
166
365
  : null,
366
+ ...(record.audience === undefined
367
+ ? {}
368
+ : { audience: normalizeWorkspaceAppAudience(record.audience) }),
167
369
  createdAt: typeof record.createdAt === "string" && record.createdAt.trim()
168
370
  ? record.createdAt.trim()
169
371
  : now,
@@ -250,6 +452,9 @@ function pendingAppToSummary(app) {
250
452
  path: app.path,
251
453
  url: app.builderUrl,
252
454
  isDispatch: false,
455
+ audience: app.audience ?? DEFAULT_WORKSPACE_APP_AUDIENCE,
456
+ publicPaths: [],
457
+ protectedPaths: [],
253
458
  status: "pending",
254
459
  statusLabel: "Building in Builder",
255
460
  builderUrl: app.builderUrl,
@@ -363,7 +568,8 @@ async function recordPendingWorkspaceApp(input) {
363
568
  const next = {
364
569
  id: input.appId,
365
570
  name: titleCase(input.appId),
366
- description: "Builder is creating this app. The workspace path becomes live after the branch is merged and deployed.",
571
+ description: input.description ||
572
+ "Builder is creating this app. The workspace path becomes live after the branch is merged and deployed.",
367
573
  path: `/${input.appId}`,
368
574
  builderUrl: input.builderUrl?.trim() || null,
369
575
  branchName: input.branchName?.trim() || null,
@@ -378,6 +584,13 @@ async function recordPendingWorkspaceApp(input) {
378
584
  ...pendingApps.filter((app) => app.id !== input.appId),
379
585
  ].slice(0, MAX_PENDING_APPS),
380
586
  });
587
+ await writeWorkspaceAppMetadataOverride({
588
+ appId: input.appId,
589
+ description: input.description,
590
+ generated: true,
591
+ sourcePrompt: input.sourcePrompt,
592
+ updatedBy: currentOwnerEmail(),
593
+ });
381
594
  await recordAudit({
382
595
  action: "workspace-app.pending",
383
596
  targetType: "workspace-app",
@@ -457,12 +670,13 @@ function readWorkspaceAppsFromFilesystem(workspaceRoot) {
457
670
  return null;
458
671
  const apps = fs
459
672
  .readdirSync(appsDir, { withFileTypes: true })
460
- .filter((entry) => entry.isDirectory())
673
+ .filter((entry) => entry.isDirectory() && !entry.name.startsWith("."))
461
674
  .map((entry) => {
462
675
  const appDir = path.join(appsDir, entry.name);
463
676
  const pkg = readJson(path.join(appDir, "package.json"));
464
677
  if (!pkg)
465
678
  return null;
679
+ const routeAccess = workspaceAppRouteAccessFromPackageJson(pkg);
466
680
  return {
467
681
  id: entry.name,
468
682
  name: pkg.displayName || titleCase(entry.name),
@@ -470,6 +684,10 @@ function readWorkspaceAppsFromFilesystem(workspaceRoot) {
470
684
  path: `/${entry.name}`,
471
685
  url: workspaceAppUrl(`/${entry.name}`),
472
686
  isDispatch: entry.name === "dispatch",
687
+ audience: workspaceAppAudienceFromPackageJson(pkg) ??
688
+ DEFAULT_WORKSPACE_APP_AUDIENCE,
689
+ publicPaths: routeAccess.publicPaths,
690
+ protectedPaths: routeAccess.protectedPaths,
473
691
  status: "ready",
474
692
  };
475
693
  })
@@ -524,15 +742,69 @@ export function getWorkspaceInfo() {
524
742
  };
525
743
  }
526
744
  async function applyArchivedAndPending(apps, options) {
527
- const [withPending, archivedIds] = await Promise.all([
745
+ const [withPending, archivedIds, metadataSettings] = await Promise.all([
528
746
  appendPendingWorkspaceApps(apps),
529
747
  listArchivedAppIds(),
748
+ readWorkspaceAppMetadataSettings(),
530
749
  ]);
531
750
  const archivedSet = new Set(archivedIds);
532
- const annotated = withPending.map((app) => archivedSet.has(app.id) ? { ...app, archived: true } : app);
751
+ const annotated = withPending.map((app) => {
752
+ const withMetadata = applyWorkspaceAppMetadataOverride(app, metadataSettings);
753
+ return archivedSet.has(app.id)
754
+ ? { ...withMetadata, archived: true }
755
+ : withMetadata;
756
+ });
533
757
  return options.includeArchived
534
- ? annotated
535
- : annotated.filter((app) => !app.archived);
758
+ ? filterAppsByAudience(annotated, options.audience)
759
+ : filterAppsByAudience(annotated.filter((app) => !app.archived), options.audience);
760
+ }
761
+ function filterAppsByAudience(apps, audience) {
762
+ if (!audience || audience === "all")
763
+ return apps;
764
+ return apps.filter((app) => (app.audience ?? DEFAULT_WORKSPACE_APP_AUDIENCE) ===
765
+ normalizeWorkspaceAppAudience(audience));
766
+ }
767
+ export async function updateWorkspaceAppMetadata(input) {
768
+ await assertCanManageAppCreationSettings();
769
+ const appId = input.appId.trim();
770
+ assertValidWorkspaceAppId(appId);
771
+ const apps = await listWorkspaceApps({
772
+ includeAgentCards: false,
773
+ includeArchived: true,
774
+ });
775
+ const app = apps.find((candidate) => candidate.id === appId);
776
+ if (!app)
777
+ throw new Error(`Workspace app "${appId}" was not found.`);
778
+ // Treat undefined/null as "field omitted, leave existing value alone"; an
779
+ // explicit empty string clears the override (the app reverts to its
780
+ // built-in name / no description). Without this, a partial update that
781
+ // only touches one field silently wipes the other.
782
+ const name = input.name == null ? app.name : input.name.trim();
783
+ const description = input.description == null
784
+ ? (app.description ?? undefined)
785
+ : input.description.trim();
786
+ await writeWorkspaceAppMetadataOverride({
787
+ appId,
788
+ name,
789
+ description,
790
+ generated: false,
791
+ updatedBy: currentOwnerEmail(),
792
+ });
793
+ await recordAudit({
794
+ action: "workspace-app.metadata-updated",
795
+ targetType: "workspace-app",
796
+ targetId: appId,
797
+ summary: `Updated workspace app details for ${name}`,
798
+ metadata: {
799
+ name,
800
+ descriptionConfigured: !!description,
801
+ },
802
+ });
803
+ const updated = (await listWorkspaceApps({
804
+ includeAgentCards: false,
805
+ includeArchived: true,
806
+ })).find((candidate) => candidate.id === appId);
807
+ return updated ?? { ...app, name, description };
536
808
  }
537
809
  export async function listWorkspaceApps(options = {}) {
538
810
  const gatewayApps = await readWorkspaceAppsFromGateway();
@@ -559,6 +831,9 @@ export async function listWorkspaceApps(options = {}) {
559
831
  path: "/dispatch",
560
832
  url: workspaceAppUrl("/dispatch"),
561
833
  isDispatch: true,
834
+ audience: DEFAULT_WORKSPACE_APP_AUDIENCE,
835
+ publicPaths: [],
836
+ protectedPaths: [],
562
837
  status: "ready",
563
838
  },
564
839
  ], options), options);
@@ -913,6 +1188,8 @@ function buildWorkspaceAppPrompt(input) {
913
1188
  const appId = slugify(input.appId || "") ||
914
1189
  slugify(input.prompt.replace(/\b(build|create|make|an?|the|app|tool)\b/gi, " ")) ||
915
1190
  "new-app";
1191
+ const appDescription = input.description?.trim() ||
1192
+ generateWorkspaceAppDescription(input.prompt, appId);
916
1193
  const selectedKeys = input.selectedKeys || [];
917
1194
  const selectedResources = input.selectedResources || [];
918
1195
  const resourceList = selectedResources.length
@@ -926,6 +1203,7 @@ function buildWorkspaceAppPrompt(input) {
926
1203
  "Create a new agent-native app in this workspace.",
927
1204
  "",
928
1205
  `App name: ${appId}`,
1206
+ `App description: ${appDescription}`,
929
1207
  `Template to start from: ${input.template || "starter"}`,
930
1208
  `User prompt: ${input.prompt.trim()}`,
931
1209
  "If the user mentions a product or company such as Granola, Loom, Superhuman, Linear, or Notion, treat it as product inspiration unless they explicitly ask to connect to that service. Do not invent or require third-party API keys like GRANOLA_API_KEY just because a product is named.",
@@ -933,6 +1211,7 @@ function buildWorkspaceAppPrompt(input) {
933
1211
  ? `Dispatch vault keys selected for this app: ${selectedKeys.join(", ")}`
934
1212
  : "Dispatch vault keys selected for this app: none",
935
1213
  `Dispatch workspace resources selected for this app:\n${resourceList}`,
1214
+ `Dispatch workspace resources with scope=all are global. After the app exists, sync workspace resources to appId "${appId}" so global skills, guardrail instructions, and reference resources reach the new app even when no per-app resources were selected.`,
936
1215
  "",
937
1216
  `Use the workspace app layout: create it under apps/${appId}, mount it at /${appId}, keep it on the shared workspace database/hosting model, and avoid table-name collisions by namespacing any new domain tables to the app.`,
938
1217
  `Important routing rule: from outside the app, link to /${appId}; inside apps/${appId}, React Router routes are app-local. Use <Link to="/review"> and navigate("/review"), not "/${appId}/review"; APP_BASE_PATH supplies the mounted prefix, and hardcoding it causes doubled URLs like /${appId}/${appId}/review.`,
@@ -943,8 +1222,8 @@ function buildWorkspaceAppPrompt(input) {
943
1222
  ? `Dispatch will create pending vault requests for the selected keys for appId "${appId}" after this app creation request is accepted. Do not grant or sync vault keys directly from the app-creation branch.`
944
1223
  : "Do not grant or request any Dispatch vault keys unless the user asks later.",
945
1224
  selectedResources.length
946
- ? `Dispatch will create workspace resource grants for the selected resources for appId "${appId}". After the app exists, sync workspace resources so the app receives those shared resources. Add a short note to apps/${appId}/AGENTS.md telling the app agent to read relevant shared resources under context/ or the selected resource paths before doing GTM/domain work.`
947
- : "Do not grant any Dispatch workspace resources unless the user asks later.",
1225
+ ? `Dispatch will create workspace resource grants for the selected resources for appId "${appId}". After the app exists, sync workspace resources so the app receives both global and selected shared resources.`
1226
+ : "Do not grant any selected-only Dispatch workspace resources unless the user asks later.",
948
1227
  "",
949
1228
  "Agent-native rules (these are the framework's contract — not optional):",
950
1229
  `- Persist ALL data in SQL via Drizzle. Add tables to apps/${appId}/server/db/schema.ts and migrations to apps/${appId}/server/plugins/db.ts. NEVER use localStorage, sessionStorage, IndexedDB, or in-memory state for anything the user expects to persist — agent and UI must read the same source of truth.`,
@@ -956,11 +1235,13 @@ function buildWorkspaceAppPrompt(input) {
956
1235
  "",
957
1236
  "Branch readiness requirements before handing off:",
958
1237
  "- The CLI auto-fills package.json name and displayName from the app id; only edit the description / scripts / dependencies if the app actually needs more than the template provides.",
1238
+ `- Save a concise, human-readable app description in apps/${appId}/package.json "description" so Dispatch, A2A discovery, and connected agents can describe what this app does. Use the description above or improve it based on the prompt.`,
959
1239
  "- Do not add or update workspace-apps.json or .agent-native/workspace-apps.json unless the app needs an explicit external URL override; the root deploy generates the workspace app registry from apps/* and deploy metadata.",
960
1240
  "- Update pnpm-lock.yaml when adding or changing dependencies so Netlify can install the branch reliably.",
961
1241
  "- Update the app manifest/package/deploy metadata needed by the existing workspace deployment model; do not leave the branch relying only on uncommitted local state.",
962
- "- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment.",
963
- "- Include a final verification note covering the registry entry, manifest/deploy metadata, and agent-card readiness.",
1242
+ "- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment. Every sibling workspace app should be usable over A2A by default through call-agent.",
1243
+ "- Give the app agent context that sibling workspace apps are available over A2A with names and descriptions from the workspace app registry; do not hardcode a stale app list.",
1244
+ "- Include a final verification note covering the registry entry, manifest/deploy metadata, relative same-origin routing, and agent-card readiness.",
964
1245
  `When it is ready, start or update the workspace dev server and navigate the user to /${appId}.`,
965
1246
  ].join("\n"),
966
1247
  };
@@ -990,6 +1271,7 @@ export async function startWorkspaceAppCreation(input) {
990
1271
  const initial = buildWorkspaceAppPrompt({
991
1272
  prompt: input.prompt,
992
1273
  appId: input.appId,
1274
+ description: input.description,
993
1275
  template: input.template,
994
1276
  });
995
1277
  assertValidWorkspaceAppId(initial.appId);
@@ -1013,11 +1295,14 @@ export async function startWorkspaceAppCreation(input) {
1013
1295
  const built = buildWorkspaceAppPrompt({
1014
1296
  prompt: input.prompt,
1015
1297
  appId: input.appId,
1298
+ description: input.description,
1016
1299
  template: input.template,
1017
1300
  selectedKeys,
1018
1301
  selectedResources,
1019
1302
  });
1020
1303
  const prompt = built.prompt;
1304
+ const appDescription = input.description?.trim() ||
1305
+ generateWorkspaceAppDescription(input.prompt, built.appId);
1021
1306
  if (isLocal) {
1022
1307
  await requestSelectedVaultKeys({
1023
1308
  appId: built.appId,
@@ -1070,6 +1355,8 @@ export async function startWorkspaceAppCreation(input) {
1070
1355
  await recordPendingWorkspaceApp({
1071
1356
  appId: built.appId,
1072
1357
  projectId: settings.builderProjectId,
1358
+ description: appDescription,
1359
+ sourcePrompt: input.prompt,
1073
1360
  branchName: result.branchName,
1074
1361
  builderUrl: result.url,
1075
1362
  });