@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
@@ -0,0 +1,167 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import type {
3
+ IncomingMessage,
4
+ PlatformAdapter,
5
+ } from "@agent-native/core/server";
6
+ import {
7
+ handleRemoteCodeCommand,
8
+ parseTelegramCodeCommand,
9
+ type RemoteCodeCommandEnvelope,
10
+ } from "./dispatch-remote-commands.js";
11
+
12
+ function telegramIncoming(text: string, rawText = text): IncomingMessage {
13
+ return {
14
+ platform: "telegram",
15
+ externalThreadId: "chat-123",
16
+ text,
17
+ senderId: "user-1",
18
+ senderName: "User One",
19
+ platformContext: { chatId: 123, messageId: 456, rawText },
20
+ timestamp: 1710000000000,
21
+ };
22
+ }
23
+
24
+ const adapter = {
25
+ platform: "telegram",
26
+ label: "Telegram",
27
+ } as PlatformAdapter;
28
+
29
+ describe("parseTelegramCodeCommand", () => {
30
+ it("parses a prompt as a create command", () => {
31
+ expect(
32
+ parseTelegramCodeCommand(
33
+ telegramIncoming(
34
+ "fix the failing tests",
35
+ "/code fix the failing tests",
36
+ ),
37
+ ),
38
+ ).toEqual({ type: "create", prompt: "fix the failing tests" });
39
+ });
40
+
41
+ it("parses run management commands", () => {
42
+ expect(
43
+ parseTelegramCodeCommand(telegramIncoming("list", "/code list")),
44
+ ).toEqual({
45
+ type: "list",
46
+ });
47
+ expect(
48
+ parseTelegramCodeCommand(telegramIncoming("status 2", "/code status 2")),
49
+ ).toEqual({ type: "status", runRef: "2" });
50
+ expect(
51
+ parseTelegramCodeCommand(
52
+ telegramIncoming(
53
+ "continue run_123 add docs",
54
+ "/code continue run_123 add docs",
55
+ ),
56
+ ),
57
+ ).toEqual({ type: "continue", runRef: "run_123", text: "add docs" });
58
+ expect(
59
+ parseTelegramCodeCommand(
60
+ telegramIncoming("approve req_1", "/code approve req_1"),
61
+ ),
62
+ ).toEqual({ type: "approve", approvalId: "req_1" });
63
+ expect(
64
+ parseTelegramCodeCommand(
65
+ telegramIncoming("deny req_1", "/code deny req_1"),
66
+ ),
67
+ ).toEqual({ type: "deny", approvalId: "req_1" });
68
+ expect(
69
+ parseTelegramCodeCommand(telegramIncoming("stop 1", "/code stop 1")),
70
+ ).toEqual({
71
+ type: "stop",
72
+ runRef: "1",
73
+ });
74
+ });
75
+
76
+ it("does not hijack Telegram messages after the adapter strips other commands", () => {
77
+ expect(
78
+ parseTelegramCodeCommand({
79
+ platform: "telegram",
80
+ text: "list",
81
+ platformContext: {},
82
+ }),
83
+ ).toBeNull();
84
+ });
85
+ });
86
+
87
+ describe("handleRemoteCodeCommand", () => {
88
+ it("routes code commands to the remote relay with owner and source context", async () => {
89
+ const relay = vi.fn(async () => ({
90
+ ok: true,
91
+ runId: "run_123",
92
+ hostOnline: true,
93
+ }));
94
+
95
+ const result = await handleRemoteCodeCommand(
96
+ telegramIncoming("ship it", "/code ship it"),
97
+ adapter,
98
+ {
99
+ resolveOwner: () => "owner@example.test",
100
+ relay,
101
+ },
102
+ );
103
+
104
+ expect(result).toEqual({
105
+ handled: true,
106
+ responseText: "Queued code run (run_123).",
107
+ });
108
+ expect(relay).toHaveBeenCalledWith({
109
+ kind: "code-agent",
110
+ ownerEmail: "owner@example.test",
111
+ command: { type: "create", prompt: "ship it" },
112
+ source: {
113
+ platform: "telegram",
114
+ externalThreadId: "chat-123",
115
+ senderId: "user-1",
116
+ senderName: "User One",
117
+ messageId: "456",
118
+ timestamp: 1710000000000,
119
+ },
120
+ } satisfies RemoteCodeCommandEnvelope);
121
+ });
122
+
123
+ it("keeps offline hosts pending without pretending the run is active", async () => {
124
+ const result = await handleRemoteCodeCommand(
125
+ telegramIncoming("fix it", "/code fix it"),
126
+ adapter,
127
+ {
128
+ resolveOwner: () => "owner@example.test",
129
+ relay: async () => ({
130
+ ok: true,
131
+ commandId: "cmd_123",
132
+ hostOnline: false,
133
+ hostStatus: "asleep",
134
+ }),
135
+ },
136
+ );
137
+
138
+ expect(result).toEqual({
139
+ handled: true,
140
+ responseText:
141
+ "Queued code run (cmd_123). Your computer looks offline or asleep, so it will pick this up when it wakes.",
142
+ });
143
+ });
144
+
145
+ it("formats recent run lists compactly", async () => {
146
+ const result = await handleRemoteCodeCommand(
147
+ telegramIncoming("list", "/code list"),
148
+ adapter,
149
+ {
150
+ resolveOwner: () => "owner@example.test",
151
+ relay: async () => ({
152
+ ok: true,
153
+ runs: [
154
+ { id: "run_a", title: "Fix auth", status: "running" },
155
+ { id: "run_b", title: "Add docs", status: "completed" },
156
+ ],
157
+ }),
158
+ },
159
+ );
160
+
161
+ expect(result).toEqual({
162
+ handled: true,
163
+ responseText:
164
+ "Recent code-agent runs:\n1. Fix auth — running (run_a)\n2. Add docs — completed (run_b)",
165
+ });
166
+ });
167
+ });
@@ -0,0 +1,375 @@
1
+ import type {
2
+ IncomingMessage,
3
+ PlatformAdapter,
4
+ } from "@agent-native/core/server";
5
+
6
+ export type RemoteCodeCommand =
7
+ | { type: "create"; prompt: string }
8
+ | { type: "list" }
9
+ | { type: "status"; runRef?: string }
10
+ | { type: "continue"; runRef: string; text: string }
11
+ | { type: "approve"; approvalId: string }
12
+ | { type: "deny"; approvalId: string }
13
+ | { type: "stop"; runRef: string }
14
+ | { type: "help"; reason?: string };
15
+
16
+ export interface RemoteCodeCommandEnvelope {
17
+ kind: "code-agent";
18
+ ownerEmail: string;
19
+ command: Exclude<RemoteCodeCommand, { type: "help" }>;
20
+ source: {
21
+ platform: string;
22
+ externalThreadId: string;
23
+ senderId?: string;
24
+ senderName?: string;
25
+ messageId?: string;
26
+ timestamp: number;
27
+ };
28
+ }
29
+
30
+ export interface RemoteCodeRunSummary {
31
+ id?: string;
32
+ runId?: string;
33
+ title?: string;
34
+ prompt?: string;
35
+ status?: string;
36
+ updatedAt?: string | number | Date;
37
+ createdAt?: string | number | Date;
38
+ }
39
+
40
+ export interface RemoteCodeCommandResult {
41
+ ok?: boolean;
42
+ status?: string;
43
+ hostOnline?: boolean;
44
+ hostStatus?: string;
45
+ commandId?: string;
46
+ requestId?: string;
47
+ runId?: string;
48
+ run?: RemoteCodeRunSummary;
49
+ runs?: RemoteCodeRunSummary[];
50
+ message?: string;
51
+ error?: string;
52
+ }
53
+
54
+ export type RemoteCodeCommandRelay = (
55
+ envelope: RemoteCodeCommandEnvelope,
56
+ ) => Promise<RemoteCodeCommandResult>;
57
+
58
+ export interface HandleRemoteCodeCommandOptions {
59
+ resolveOwner: () => Promise<string> | string;
60
+ relay?: RemoteCodeCommandRelay;
61
+ }
62
+
63
+ const CODE_COMMAND_RE = /^\/code(?:@[a-zA-Z0-9_]+)?(?:\s+|$)/i;
64
+
65
+ export function parseTelegramCodeCommand(
66
+ incoming: Pick<IncomingMessage, "platform" | "text" | "platformContext">,
67
+ ): RemoteCodeCommand | null {
68
+ if (incoming.platform !== "telegram") return null;
69
+
70
+ const rawText = rawTelegramText(incoming);
71
+ if (!rawText || !CODE_COMMAND_RE.test(rawText)) return null;
72
+
73
+ return parseCodeCommandBody(rawText.replace(CODE_COMMAND_RE, "").trim());
74
+ }
75
+
76
+ export async function handleRemoteCodeCommand(
77
+ incoming: IncomingMessage,
78
+ _adapter: PlatformAdapter,
79
+ options: HandleRemoteCodeCommandOptions,
80
+ ): Promise<{ handled: true; responseText?: string } | { handled: false }> {
81
+ const command = parseTelegramCodeCommand(incoming);
82
+ if (!command) return { handled: false };
83
+
84
+ if (command.type === "help") {
85
+ return { handled: true, responseText: formatCodeCommandHelp(command) };
86
+ }
87
+
88
+ try {
89
+ const ownerEmail = await options.resolveOwner();
90
+ const envelope = createRemoteCodeCommandEnvelope(
91
+ incoming,
92
+ ownerEmail,
93
+ command,
94
+ );
95
+ const relay = options.relay ?? enqueueRemoteCodeCommand;
96
+ const result = await relay(envelope);
97
+ return {
98
+ handled: true,
99
+ responseText: formatRemoteCodeCommandResult(command, result),
100
+ };
101
+ } catch (error) {
102
+ return {
103
+ handled: true,
104
+ responseText:
105
+ error instanceof Error
106
+ ? `I couldn't route that code command: ${error.message}`
107
+ : "I couldn't route that code command.",
108
+ };
109
+ }
110
+ }
111
+
112
+ export function createRemoteCodeCommandEnvelope(
113
+ incoming: IncomingMessage,
114
+ ownerEmail: string,
115
+ command: Exclude<RemoteCodeCommand, { type: "help" }>,
116
+ ): RemoteCodeCommandEnvelope {
117
+ return {
118
+ kind: "code-agent",
119
+ ownerEmail,
120
+ command,
121
+ source: {
122
+ platform: incoming.platform,
123
+ externalThreadId: incoming.externalThreadId,
124
+ senderId: incoming.senderId,
125
+ senderName: incoming.senderName,
126
+ messageId: contextString(incoming.platformContext.messageId),
127
+ timestamp: incoming.timestamp,
128
+ },
129
+ };
130
+ }
131
+
132
+ export async function enqueueRemoteCodeCommand(
133
+ envelope: RemoteCodeCommandEnvelope,
134
+ ): Promise<RemoteCodeCommandResult> {
135
+ const helperResult = await tryCoreRemoteCommandHelper(envelope);
136
+ if (helperResult) return helperResult;
137
+
138
+ const endpoint = `${resolveRemoteRelayBaseUrl()}/_agent-native/integrations/remote/enqueue`;
139
+ const response = await fetch(endpoint, {
140
+ method: "POST",
141
+ headers: { "Content-Type": "application/json" },
142
+ body: JSON.stringify(envelope),
143
+ });
144
+
145
+ let body: unknown = null;
146
+ try {
147
+ body = await response.json();
148
+ } catch {
149
+ body = null;
150
+ }
151
+
152
+ if (!response.ok) {
153
+ const message =
154
+ typeof body === "object" && body && "error" in body
155
+ ? String((body as { error?: unknown }).error)
156
+ : `remote relay returned ${response.status}`;
157
+ throw new Error(message);
158
+ }
159
+
160
+ return normalizeRemoteCodeCommandResult(body);
161
+ }
162
+
163
+ export function formatRemoteCodeCommandResult(
164
+ command: Exclude<RemoteCodeCommand, { type: "help" }>,
165
+ result: RemoteCodeCommandResult,
166
+ ): string {
167
+ if (result.message?.trim()) return result.message.trim();
168
+ if (result.error?.trim())
169
+ return `Code command failed: ${result.error.trim()}`;
170
+
171
+ if (command.type === "list") return formatRunList(result.runs ?? []);
172
+ if (command.type === "status") return formatStatus(command, result);
173
+
174
+ const id =
175
+ result.runId ||
176
+ result.run?.runId ||
177
+ result.run?.id ||
178
+ result.commandId ||
179
+ result.requestId;
180
+ const suffix = id ? ` (${id})` : "";
181
+ const offline = isOfflineOrSleeping(result);
182
+
183
+ if (command.type === "create") {
184
+ return offline
185
+ ? `Queued code run${suffix}. Your computer looks offline or asleep, so it will pick this up when it wakes.`
186
+ : `Queued code run${suffix}.`;
187
+ }
188
+
189
+ if (command.type === "continue") {
190
+ return offline
191
+ ? `Queued follow-up for ${command.runRef}. Your computer looks offline or asleep, so it will pick this up when it wakes.`
192
+ : `Queued follow-up for ${command.runRef}.`;
193
+ }
194
+
195
+ if (command.type === "approve") {
196
+ return `Approved code-agent request ${command.approvalId}.`;
197
+ }
198
+
199
+ if (command.type === "deny") {
200
+ return `Denied code-agent request ${command.approvalId}.`;
201
+ }
202
+
203
+ if (command.type === "stop") {
204
+ return offline
205
+ ? `Queued stop request for ${command.runRef}. Your computer looks offline or asleep, so it will receive the stop request when it wakes.`
206
+ : `Stop requested for ${command.runRef}.`;
207
+ }
208
+
209
+ return "Code command routed.";
210
+ }
211
+
212
+ function parseCodeCommandBody(body: string): RemoteCodeCommand {
213
+ if (!body) return { type: "help" };
214
+
215
+ const [verbRaw = "", ...restParts] = body.split(/\s+/);
216
+ const verb = verbRaw.toLowerCase();
217
+ const rest = restParts.join(" ").trim();
218
+
219
+ if (verb === "help") return { type: "help" };
220
+ if (verb === "list") return { type: "list" };
221
+ if (verb === "status") {
222
+ return rest ? { type: "status", runRef: rest } : { type: "status" };
223
+ }
224
+ if (verb === "continue") {
225
+ const { first, rest: text } = splitFirst(rest);
226
+ if (!first || !text) {
227
+ return { type: "help", reason: "continue needs a run id and text" };
228
+ }
229
+ return { type: "continue", runRef: first, text };
230
+ }
231
+ if (verb === "approve") {
232
+ return rest
233
+ ? { type: "approve", approvalId: rest }
234
+ : { type: "help", reason: "approve needs a request id" };
235
+ }
236
+ if (verb === "deny") {
237
+ return rest
238
+ ? { type: "deny", approvalId: rest }
239
+ : { type: "help", reason: "deny needs a request id" };
240
+ }
241
+ if (verb === "stop") {
242
+ return rest
243
+ ? { type: "stop", runRef: rest }
244
+ : { type: "help", reason: "stop needs a run id or list index" };
245
+ }
246
+
247
+ return { type: "create", prompt: body };
248
+ }
249
+
250
+ function rawTelegramText(
251
+ incoming: Pick<IncomingMessage, "text" | "platformContext">,
252
+ ): string | null {
253
+ const context = incoming.platformContext;
254
+ return (
255
+ contextString(context.rawText) ||
256
+ contextString(context.originalText) ||
257
+ contextString(context.messageText) ||
258
+ (CODE_COMMAND_RE.test(incoming.text) ? incoming.text : null)
259
+ );
260
+ }
261
+
262
+ function formatCodeCommandHelp(
263
+ command?: Extract<RemoteCodeCommand, { type: "help" }>,
264
+ ): string {
265
+ const prefix = command?.reason ? `${command.reason}.\n\n` : "";
266
+ return `${prefix}Use /code <prompt>, /code list, /code status [run], /code continue <run> <text>, /code approve <id>, /code deny <id>, or /code stop <run>.`;
267
+ }
268
+
269
+ function formatRunList(runs: RemoteCodeRunSummary[]): string {
270
+ if (!runs.length) return "No recent code-agent runs found.";
271
+ const lines = runs.slice(0, 8).map((run, index) => {
272
+ const id = run.runId || run.id || "unknown";
273
+ const title = run.title || run.prompt || "Untitled run";
274
+ const status = run.status || "unknown";
275
+ return `${index + 1}. ${title} — ${status} (${id})`;
276
+ });
277
+ return `Recent code-agent runs:\n${lines.join("\n")}`;
278
+ }
279
+
280
+ function formatStatus(
281
+ command: Extract<RemoteCodeCommand, { type: "status" }>,
282
+ result: RemoteCodeCommandResult,
283
+ ): string {
284
+ const run = result.run;
285
+ const hostStatus =
286
+ result.hostStatus || (result.hostOnline ? "online" : "offline");
287
+ if (!run) {
288
+ const target = command.runRef ? ` for ${command.runRef}` : "";
289
+ return `Code-agent host is ${hostStatus}${target}.`;
290
+ }
291
+
292
+ const id = run.runId || run.id || command.runRef || "unknown";
293
+ const title = run.title || run.prompt || "Untitled run";
294
+ const status = run.status || result.status || "unknown";
295
+ const updated = formatDate(run.updatedAt || run.createdAt);
296
+ return [
297
+ `Code run ${id}: ${status}`,
298
+ `Task: ${title}`,
299
+ `Host: ${hostStatus}`,
300
+ updated ? `Updated: ${updated}` : "",
301
+ ]
302
+ .filter(Boolean)
303
+ .join("\n");
304
+ }
305
+
306
+ function isOfflineOrSleeping(result: RemoteCodeCommandResult): boolean {
307
+ if (result.hostOnline === false) return true;
308
+ const status = result.hostStatus?.toLowerCase();
309
+ return status === "offline" || status === "asleep" || status === "sleeping";
310
+ }
311
+
312
+ function splitFirst(value: string): { first: string; rest: string } {
313
+ const trimmed = value.trim();
314
+ const match = trimmed.match(/^(\S+)(?:\s+([\s\S]+))?$/);
315
+ return { first: match?.[1] || "", rest: match?.[2]?.trim() || "" };
316
+ }
317
+
318
+ function contextString(value: unknown): string | undefined {
319
+ if (typeof value === "string" && value.trim()) return value.trim();
320
+ if (typeof value === "number" && Number.isFinite(value)) return String(value);
321
+ return undefined;
322
+ }
323
+
324
+ function formatDate(value: RemoteCodeRunSummary["updatedAt"]): string | null {
325
+ if (!value) return null;
326
+ const date = value instanceof Date ? value : new Date(value);
327
+ if (Number.isNaN(date.getTime())) return null;
328
+ return date.toISOString();
329
+ }
330
+
331
+ async function tryCoreRemoteCommandHelper(
332
+ envelope: RemoteCodeCommandEnvelope,
333
+ ): Promise<RemoteCodeCommandResult | null> {
334
+ const core = (await import("@agent-native/core/server")) as Record<
335
+ string,
336
+ unknown
337
+ >;
338
+ const helper =
339
+ core.enqueueRemoteCommand ||
340
+ core.enqueueIntegrationRemoteCommand ||
341
+ core.enqueueRemoteIntegrationCommand;
342
+ if (typeof helper !== "function") return null;
343
+ return normalizeRemoteCodeCommandResult(await helper(envelope));
344
+ }
345
+
346
+ function normalizeRemoteCodeCommandResult(
347
+ value: unknown,
348
+ ): RemoteCodeCommandResult {
349
+ if (!value || typeof value !== "object") return { ok: true };
350
+ const result = value as RemoteCodeCommandResult;
351
+ return {
352
+ ok: result.ok,
353
+ status: contextString(result.status),
354
+ hostOnline:
355
+ typeof result.hostOnline === "boolean" ? result.hostOnline : undefined,
356
+ hostStatus: contextString(result.hostStatus),
357
+ commandId: contextString(result.commandId),
358
+ requestId: contextString(result.requestId),
359
+ runId: contextString(result.runId),
360
+ run: result.run,
361
+ runs: Array.isArray(result.runs) ? result.runs : undefined,
362
+ message: contextString(result.message),
363
+ error: contextString(result.error),
364
+ };
365
+ }
366
+
367
+ function resolveRemoteRelayBaseUrl(): string {
368
+ const raw =
369
+ process.env.WEBHOOK_BASE_URL ||
370
+ process.env.APP_URL ||
371
+ process.env.URL ||
372
+ "http://localhost:3000";
373
+ if (/^https?:\/\//i.test(raw)) return raw.replace(/\/$/, "");
374
+ return `https://${raw.replace(/\/$/, "")}`;
375
+ }
@@ -423,7 +423,7 @@ async function notifyApprovers(requestId: string, summary: string) {
423
423
  }).catch(() => {});
424
424
  }
425
425
 
426
- async function createApprovalRequest(input: {
426
+ export async function createApprovalRequest(input: {
427
427
  changeType: string;
428
428
  targetType: string;
429
429
  targetId?: string | null;
@@ -564,6 +564,42 @@ async function applyApprovedRequest(request: DispatchApprovalRequest) {
564
564
  request.reviewedBy || currentOwnerEmail(),
565
565
  );
566
566
  }
567
+ if (request.changeType === "dream-proposal.apply") {
568
+ const { applyApprovedDreamProposal } = await import("./dreams-store.js");
569
+ return applyApprovedDreamProposal(
570
+ payload.proposalId,
571
+ request.reviewedBy || currentOwnerEmail(),
572
+ requestCtx,
573
+ );
574
+ }
575
+ if (request.changeType === "workspace-resource.create") {
576
+ const { applyWorkspaceResourceCreate } =
577
+ await import("./workspace-resources-store.js");
578
+ return applyWorkspaceResourceCreate(
579
+ payload.input,
580
+ request.reviewedBy || currentOwnerEmail(),
581
+ requestCtx,
582
+ );
583
+ }
584
+ if (request.changeType === "workspace-resource.update") {
585
+ const { applyWorkspaceResourceUpdate } =
586
+ await import("./workspace-resources-store.js");
587
+ return applyWorkspaceResourceUpdate(
588
+ payload.id,
589
+ payload.input,
590
+ request.reviewedBy || currentOwnerEmail(),
591
+ requestCtx,
592
+ );
593
+ }
594
+ if (request.changeType === "workspace-resource.delete") {
595
+ const { applyWorkspaceResourceDelete } =
596
+ await import("./workspace-resources-store.js");
597
+ return applyWorkspaceResourceDelete(
598
+ payload.id,
599
+ request.reviewedBy || currentOwnerEmail(),
600
+ requestCtx,
601
+ );
602
+ }
567
603
  throw new Error(`Unsupported approval request type: ${request.changeType}`);
568
604
  }
569
605