@mesh-tech/mesh-cli 0.1.0 → 0.12.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 (504) hide show
  1. package/assets/intent/agents-fence.md +10 -0
  2. package/assets/intent/intent-claude-gate.mjs +255 -0
  3. package/assets/log-shipper.mjs +94 -0
  4. package/bin/mesh.mjs +80 -0
  5. package/dist/bin/mesh.d.ts +7 -9
  6. package/dist/bin/mesh.d.ts.map +1 -1
  7. package/dist/bin/mesh.js +20826 -37
  8. package/dist/bin/mesh.js.map +7 -1
  9. package/dist/build-info.json +4 -0
  10. package/dist/src/commands/agent-api-client.d.ts +79 -0
  11. package/dist/src/commands/agent-api-client.d.ts.map +1 -0
  12. package/dist/src/commands/agent-api-client.js +170 -0
  13. package/dist/src/commands/agent-api-client.js.map +1 -0
  14. package/dist/src/commands/artifacts.d.ts +13 -0
  15. package/dist/src/commands/artifacts.d.ts.map +1 -0
  16. package/dist/src/commands/artifacts.js +140 -0
  17. package/dist/src/commands/artifacts.js.map +1 -0
  18. package/dist/src/commands/cluster.d.ts +45 -0
  19. package/dist/src/commands/cluster.d.ts.map +1 -0
  20. package/dist/src/commands/cluster.js +259 -0
  21. package/dist/src/commands/cluster.js.map +1 -0
  22. package/dist/src/commands/conversations.d.ts +61 -0
  23. package/dist/src/commands/conversations.d.ts.map +1 -0
  24. package/dist/src/commands/conversations.js +239 -0
  25. package/dist/src/commands/conversations.js.map +1 -0
  26. package/dist/src/commands/create-app.d.ts +26 -3
  27. package/dist/src/commands/create-app.d.ts.map +1 -1
  28. package/dist/src/commands/create-app.js +465 -107
  29. package/dist/src/commands/create-app.js.map +1 -1
  30. package/dist/src/commands/deploy.d.ts +19 -0
  31. package/dist/src/commands/deploy.d.ts.map +1 -1
  32. package/dist/src/commands/deploy.js +83 -142
  33. package/dist/src/commands/deploy.js.map +1 -1
  34. package/dist/src/commands/dev-doctor.d.ts +137 -0
  35. package/dist/src/commands/dev-doctor.d.ts.map +1 -0
  36. package/dist/src/commands/dev-doctor.js +671 -0
  37. package/dist/src/commands/dev-doctor.js.map +1 -0
  38. package/dist/src/commands/dev-launch.d.ts +59 -0
  39. package/dist/src/commands/dev-launch.d.ts.map +1 -0
  40. package/dist/src/commands/dev-launch.js +118 -0
  41. package/dist/src/commands/dev-launch.js.map +1 -0
  42. package/dist/src/commands/dev-token-server.d.ts +32 -0
  43. package/dist/src/commands/dev-token-server.d.ts.map +1 -0
  44. package/dist/src/commands/dev-token-server.js +68 -0
  45. package/dist/src/commands/dev-token-server.js.map +1 -0
  46. package/dist/src/commands/dev.d.ts +289 -2
  47. package/dist/src/commands/dev.d.ts.map +1 -1
  48. package/dist/src/commands/dev.js +2501 -574
  49. package/dist/src/commands/dev.js.map +1 -1
  50. package/dist/src/commands/docs.d.ts +3 -0
  51. package/dist/src/commands/docs.d.ts.map +1 -0
  52. package/dist/src/commands/docs.js +262 -0
  53. package/dist/src/commands/docs.js.map +1 -0
  54. package/dist/src/commands/hub/index.d.ts +99 -0
  55. package/dist/src/commands/hub/index.d.ts.map +1 -0
  56. package/dist/src/commands/hub/index.js +452 -0
  57. package/dist/src/commands/hub/index.js.map +1 -0
  58. package/dist/src/commands/init.d.ts +65 -0
  59. package/dist/src/commands/init.d.ts.map +1 -0
  60. package/dist/src/commands/init.js +370 -0
  61. package/dist/src/commands/init.js.map +1 -0
  62. package/dist/src/commands/install-shim.d.ts +21 -0
  63. package/dist/src/commands/install-shim.d.ts.map +1 -0
  64. package/dist/src/commands/install-shim.js +132 -0
  65. package/dist/src/commands/install-shim.js.map +1 -0
  66. package/dist/src/commands/local/auth-provision.d.ts +71 -0
  67. package/dist/src/commands/local/auth-provision.d.ts.map +1 -0
  68. package/dist/src/commands/local/auth-provision.js +286 -0
  69. package/dist/src/commands/local/auth-provision.js.map +1 -0
  70. package/dist/src/commands/local/dev-local.d.ts +97 -0
  71. package/dist/src/commands/local/dev-local.d.ts.map +1 -0
  72. package/dist/src/commands/local/dev-local.js +306 -0
  73. package/dist/src/commands/local/dev-local.js.map +1 -0
  74. package/dist/src/commands/local/docker-runner.d.ts +37 -0
  75. package/dist/src/commands/local/docker-runner.d.ts.map +1 -0
  76. package/dist/src/commands/local/docker-runner.js +104 -0
  77. package/dist/src/commands/local/docker-runner.js.map +1 -0
  78. package/dist/src/commands/local/helpers.d.ts +22 -0
  79. package/dist/src/commands/local/helpers.d.ts.map +1 -0
  80. package/dist/src/commands/local/helpers.js +46 -0
  81. package/dist/src/commands/local/helpers.js.map +1 -0
  82. package/dist/src/commands/local/hub-local.d.ts +51 -0
  83. package/dist/src/commands/local/hub-local.d.ts.map +1 -0
  84. package/dist/src/commands/local/hub-local.js +197 -0
  85. package/dist/src/commands/local/hub-local.js.map +1 -0
  86. package/dist/src/commands/local/index.d.ts +23 -0
  87. package/dist/src/commands/local/index.d.ts.map +1 -0
  88. package/dist/src/commands/local/index.js +386 -0
  89. package/dist/src/commands/local/index.js.map +1 -0
  90. package/dist/src/commands/local/mocks.d.ts +361 -0
  91. package/dist/src/commands/local/mocks.d.ts.map +1 -0
  92. package/dist/src/commands/local/mocks.js +756 -0
  93. package/dist/src/commands/local/mocks.js.map +1 -0
  94. package/dist/src/commands/local/seed-zitadel.d.ts +151 -0
  95. package/dist/src/commands/local/seed-zitadel.d.ts.map +1 -0
  96. package/dist/src/commands/local/seed-zitadel.js +408 -0
  97. package/dist/src/commands/local/seed-zitadel.js.map +1 -0
  98. package/dist/src/commands/local/seed.d.ts +106 -0
  99. package/dist/src/commands/local/seed.d.ts.map +1 -0
  100. package/dist/src/commands/local/seed.js +252 -0
  101. package/dist/src/commands/local/seed.js.map +1 -0
  102. package/dist/src/commands/local/stack.d.ts +173 -0
  103. package/dist/src/commands/local/stack.d.ts.map +1 -0
  104. package/dist/src/commands/local/stack.js +499 -0
  105. package/dist/src/commands/local/stack.js.map +1 -0
  106. package/dist/src/commands/login.d.ts +256 -12
  107. package/dist/src/commands/login.d.ts.map +1 -1
  108. package/dist/src/commands/login.js +978 -50
  109. package/dist/src/commands/login.js.map +1 -1
  110. package/dist/src/commands/peer-addressing.d.ts +51 -0
  111. package/dist/src/commands/peer-addressing.d.ts.map +1 -0
  112. package/dist/src/commands/peer-addressing.js +64 -0
  113. package/dist/src/commands/peer-addressing.js.map +1 -0
  114. package/dist/src/commands/port-ownership.d.ts +69 -0
  115. package/dist/src/commands/port-ownership.d.ts.map +1 -0
  116. package/dist/src/commands/port-ownership.js +161 -0
  117. package/dist/src/commands/port-ownership.js.map +1 -0
  118. package/dist/src/commands/registry-publish.d.ts +3 -0
  119. package/dist/src/commands/registry-publish.d.ts.map +1 -0
  120. package/dist/src/commands/registry-publish.js +161 -0
  121. package/dist/src/commands/registry-publish.js.map +1 -0
  122. package/dist/src/commands/registry.d.ts +146 -2
  123. package/dist/src/commands/registry.d.ts.map +1 -1
  124. package/dist/src/commands/registry.js +541 -85
  125. package/dist/src/commands/registry.js.map +1 -1
  126. package/dist/src/commands/secrets/index.d.ts.map +1 -1
  127. package/dist/src/commands/secrets/index.js +15 -1
  128. package/dist/src/commands/secrets/index.js.map +1 -1
  129. package/dist/src/commands/secrets/migrate-config.d.ts +24 -0
  130. package/dist/src/commands/secrets/migrate-config.d.ts.map +1 -0
  131. package/dist/src/commands/secrets/migrate-config.js +277 -0
  132. package/dist/src/commands/secrets/migrate-config.js.map +1 -0
  133. package/dist/src/commands/secrets/set.d.ts +4 -0
  134. package/dist/src/commands/secrets/set.d.ts.map +1 -1
  135. package/dist/src/commands/secrets/set.js +243 -64
  136. package/dist/src/commands/secrets/set.js.map +1 -1
  137. package/dist/src/commands/skills.d.ts +34 -0
  138. package/dist/src/commands/skills.d.ts.map +1 -0
  139. package/dist/src/commands/skills.js +207 -0
  140. package/dist/src/commands/skills.js.map +1 -0
  141. package/dist/src/commands/stack.d.ts.map +1 -1
  142. package/dist/src/commands/stack.js +361 -23
  143. package/dist/src/commands/stack.js.map +1 -1
  144. package/dist/src/commands/temporal.d.ts +15 -0
  145. package/dist/src/commands/temporal.d.ts.map +1 -0
  146. package/dist/src/commands/temporal.js +781 -0
  147. package/dist/src/commands/temporal.js.map +1 -0
  148. package/dist/src/commands/tenant.d.ts +56 -0
  149. package/dist/src/commands/tenant.d.ts.map +1 -0
  150. package/dist/src/commands/tenant.js +233 -0
  151. package/dist/src/commands/tenant.js.map +1 -0
  152. package/dist/src/commands/tunnel/index.d.ts +49 -3
  153. package/dist/src/commands/tunnel/index.d.ts.map +1 -1
  154. package/dist/src/commands/tunnel/index.js +331 -8
  155. package/dist/src/commands/tunnel/index.js.map +1 -1
  156. package/dist/src/commands/vcs/clone.d.ts +3 -0
  157. package/dist/src/commands/vcs/clone.d.ts.map +1 -0
  158. package/dist/src/commands/vcs/clone.js +20 -0
  159. package/dist/src/commands/vcs/clone.js.map +1 -0
  160. package/dist/src/commands/vcs/common.d.ts +21 -0
  161. package/dist/src/commands/vcs/common.d.ts.map +1 -0
  162. package/dist/src/commands/vcs/common.js +62 -0
  163. package/dist/src/commands/vcs/common.js.map +1 -0
  164. package/dist/src/commands/vcs/drafts.d.ts +13 -0
  165. package/dist/src/commands/vcs/drafts.d.ts.map +1 -0
  166. package/dist/src/commands/vcs/drafts.js +45 -0
  167. package/dist/src/commands/vcs/drafts.js.map +1 -0
  168. package/dist/src/commands/vcs/get.d.ts +8 -0
  169. package/dist/src/commands/vcs/get.d.ts.map +1 -0
  170. package/dist/src/commands/vcs/get.js +61 -0
  171. package/dist/src/commands/vcs/get.js.map +1 -0
  172. package/dist/src/commands/vcs/index.d.ts +3 -0
  173. package/dist/src/commands/vcs/index.d.ts.map +1 -0
  174. package/dist/src/commands/vcs/index.js +58 -0
  175. package/dist/src/commands/vcs/index.js.map +1 -0
  176. package/dist/src/commands/vcs/propose.d.ts +23 -0
  177. package/dist/src/commands/vcs/propose.d.ts.map +1 -0
  178. package/dist/src/commands/vcs/propose.js +94 -0
  179. package/dist/src/commands/vcs/propose.js.map +1 -0
  180. package/dist/src/commands/vcs/review.d.ts +15 -0
  181. package/dist/src/commands/vcs/review.d.ts.map +1 -0
  182. package/dist/src/commands/vcs/review.js +35 -0
  183. package/dist/src/commands/vcs/review.js.map +1 -0
  184. package/dist/src/commands/vcs-enrich.d.ts +15 -0
  185. package/dist/src/commands/vcs-enrich.d.ts.map +1 -0
  186. package/dist/src/commands/vcs-enrich.js +28 -0
  187. package/dist/src/commands/vcs-enrich.js.map +1 -0
  188. package/dist/src/commands/vpn/index.d.ts +24 -0
  189. package/dist/src/commands/vpn/index.d.ts.map +1 -0
  190. package/dist/src/commands/vpn/index.js +543 -0
  191. package/dist/src/commands/vpn/index.js.map +1 -0
  192. package/dist/src/commands/vpn/tunnel.d.ts +11 -0
  193. package/dist/src/commands/vpn/tunnel.d.ts.map +1 -0
  194. package/dist/src/commands/vpn/tunnel.js +188 -0
  195. package/dist/src/commands/vpn/tunnel.js.map +1 -0
  196. package/dist/src/commands/workflow.d.ts +24 -0
  197. package/dist/src/commands/workflow.d.ts.map +1 -0
  198. package/dist/src/commands/workflow.js +577 -0
  199. package/dist/src/commands/workflow.js.map +1 -0
  200. package/dist/src/docs/assemble.d.ts +217 -0
  201. package/dist/src/docs/assemble.d.ts.map +1 -0
  202. package/dist/src/docs/assemble.js +739 -0
  203. package/dist/src/docs/assemble.js.map +1 -0
  204. package/dist/src/docs/cli-reference.d.ts +93 -0
  205. package/dist/src/docs/cli-reference.d.ts.map +1 -0
  206. package/dist/src/docs/cli-reference.js +256 -0
  207. package/dist/src/docs/cli-reference.js.map +1 -0
  208. package/dist/src/docs/discover.d.ts +60 -0
  209. package/dist/src/docs/discover.d.ts.map +1 -0
  210. package/dist/src/docs/discover.js +233 -0
  211. package/dist/src/docs/discover.js.map +1 -0
  212. package/dist/src/docs/portal.d.ts +79 -0
  213. package/dist/src/docs/portal.d.ts.map +1 -0
  214. package/dist/src/docs/portal.js +242 -0
  215. package/dist/src/docs/portal.js.map +1 -0
  216. package/dist/src/docs/registry-docs.d.ts +43 -0
  217. package/dist/src/docs/registry-docs.d.ts.map +1 -0
  218. package/dist/src/docs/registry-docs.js +138 -0
  219. package/dist/src/docs/registry-docs.js.map +1 -0
  220. package/dist/src/docs/schema.d.ts +48 -0
  221. package/dist/src/docs/schema.d.ts.map +1 -0
  222. package/dist/src/docs/schema.js +96 -0
  223. package/dist/src/docs/schema.js.map +1 -0
  224. package/dist/src/docs/serve.d.ts +27 -0
  225. package/dist/src/docs/serve.d.ts.map +1 -0
  226. package/dist/src/docs/serve.js +102 -0
  227. package/dist/src/docs/serve.js.map +1 -0
  228. package/dist/src/docs/start.d.ts +80 -0
  229. package/dist/src/docs/start.d.ts.map +1 -0
  230. package/dist/src/docs/start.js +313 -0
  231. package/dist/src/docs/start.js.map +1 -0
  232. package/dist/src/eval/agent-eval.d.mts +14 -0
  233. package/dist/src/eval/agent-eval.d.mts.map +1 -0
  234. package/dist/src/eval/agent-eval.mjs +273 -0
  235. package/dist/src/eval/agent-eval.mjs.map +1 -0
  236. package/dist/src/index.js +624 -7
  237. package/dist/src/index.js.map +7 -1
  238. package/dist/src/program.d.ts +26 -0
  239. package/dist/src/program.d.ts.map +1 -0
  240. package/dist/src/program.js +76 -0
  241. package/dist/src/program.js.map +1 -0
  242. package/dist/src/utils/auth-preflight.d.ts +159 -0
  243. package/dist/src/utils/auth-preflight.d.ts.map +1 -0
  244. package/dist/src/utils/auth-preflight.js +298 -0
  245. package/dist/src/utils/auth-preflight.js.map +1 -0
  246. package/dist/src/utils/aws-auth.d.ts +181 -0
  247. package/dist/src/utils/aws-auth.d.ts.map +1 -0
  248. package/dist/src/utils/aws-auth.js +527 -0
  249. package/dist/src/utils/aws-auth.js.map +1 -0
  250. package/dist/src/utils/bastion.d.ts +1 -1
  251. package/dist/src/utils/bastion.d.ts.map +1 -1
  252. package/dist/src/utils/bastion.js +29 -8
  253. package/dist/src/utils/bastion.js.map +1 -1
  254. package/dist/src/utils/build-info.d.ts +33 -0
  255. package/dist/src/utils/build-info.d.ts.map +1 -0
  256. package/dist/src/utils/build-info.js +102 -0
  257. package/dist/src/utils/build-info.js.map +1 -0
  258. package/dist/src/utils/capture-history.d.ts +62 -0
  259. package/dist/src/utils/capture-history.d.ts.map +1 -0
  260. package/dist/src/utils/capture-history.js +94 -0
  261. package/dist/src/utils/capture-history.js.map +1 -0
  262. package/dist/src/utils/deploy-preflight.d.ts +52 -0
  263. package/dist/src/utils/deploy-preflight.d.ts.map +1 -0
  264. package/dist/src/utils/deploy-preflight.js +183 -0
  265. package/dist/src/utils/deploy-preflight.js.map +1 -0
  266. package/dist/src/utils/errors.d.ts +75 -0
  267. package/dist/src/utils/errors.d.ts.map +1 -0
  268. package/dist/src/utils/errors.js +106 -0
  269. package/dist/src/utils/errors.js.map +1 -0
  270. package/dist/src/utils/first-party-contexts.d.ts +40 -0
  271. package/dist/src/utils/first-party-contexts.d.ts.map +1 -0
  272. package/dist/src/utils/first-party-contexts.js +53 -0
  273. package/dist/src/utils/first-party-contexts.js.map +1 -0
  274. package/dist/src/utils/index.d.ts +2 -0
  275. package/dist/src/utils/index.d.ts.map +1 -1
  276. package/dist/src/utils/index.js +2 -0
  277. package/dist/src/utils/index.js.map +1 -1
  278. package/dist/src/utils/kubeconfig.d.ts +62 -0
  279. package/dist/src/utils/kubeconfig.d.ts.map +1 -0
  280. package/dist/src/utils/kubeconfig.js +118 -0
  281. package/dist/src/utils/kubeconfig.js.map +1 -0
  282. package/dist/src/utils/log.d.ts +27 -1
  283. package/dist/src/utils/log.d.ts.map +1 -1
  284. package/dist/src/utils/log.js +59 -5
  285. package/dist/src/utils/log.js.map +1 -1
  286. package/dist/src/utils/pid.d.ts +47 -0
  287. package/dist/src/utils/pid.d.ts.map +1 -0
  288. package/dist/src/utils/pid.js +83 -0
  289. package/dist/src/utils/pid.js.map +1 -0
  290. package/dist/src/utils/pulumi-run.d.ts +23 -0
  291. package/dist/src/utils/pulumi-run.d.ts.map +1 -0
  292. package/dist/src/utils/pulumi-run.js +112 -0
  293. package/dist/src/utils/pulumi-run.js.map +1 -0
  294. package/dist/src/utils/pulumi.d.ts +15 -0
  295. package/dist/src/utils/pulumi.d.ts.map +1 -1
  296. package/dist/src/utils/pulumi.js +35 -0
  297. package/dist/src/utils/pulumi.js.map +1 -1
  298. package/dist/src/utils/reachability.d.ts +29 -0
  299. package/dist/src/utils/reachability.d.ts.map +1 -0
  300. package/dist/src/utils/reachability.js +81 -0
  301. package/dist/src/utils/reachability.js.map +1 -0
  302. package/dist/src/utils/recover-conversation.d.ts +154 -0
  303. package/dist/src/utils/recover-conversation.d.ts.map +1 -0
  304. package/dist/src/utils/recover-conversation.js +314 -0
  305. package/dist/src/utils/recover-conversation.js.map +1 -0
  306. package/dist/src/utils/registry-broker.d.ts +148 -0
  307. package/dist/src/utils/registry-broker.d.ts.map +1 -0
  308. package/dist/src/utils/registry-broker.js +180 -0
  309. package/dist/src/utils/registry-broker.js.map +1 -0
  310. package/dist/src/utils/socks-forward.d.ts +40 -0
  311. package/dist/src/utils/socks-forward.d.ts.map +1 -0
  312. package/dist/src/utils/socks-forward.js +97 -0
  313. package/dist/src/utils/socks-forward.js.map +1 -0
  314. package/dist/src/utils/stack-flag.d.ts +23 -0
  315. package/dist/src/utils/stack-flag.d.ts.map +1 -0
  316. package/dist/src/utils/stack-flag.js +41 -0
  317. package/dist/src/utils/stack-flag.js.map +1 -0
  318. package/dist/src/utils/tailscale-targets.d.ts +52 -0
  319. package/dist/src/utils/tailscale-targets.d.ts.map +1 -0
  320. package/dist/src/utils/tailscale-targets.js +93 -0
  321. package/dist/src/utils/tailscale-targets.js.map +1 -0
  322. package/dist/src/utils/tailscale.d.ts +277 -0
  323. package/dist/src/utils/tailscale.d.ts.map +1 -0
  324. package/dist/src/utils/tailscale.js +1007 -0
  325. package/dist/src/utils/tailscale.js.map +1 -0
  326. package/dist/src/utils/temporal-auth.d.ts +43 -0
  327. package/dist/src/utils/temporal-auth.d.ts.map +1 -0
  328. package/dist/src/utils/temporal-auth.js +176 -0
  329. package/dist/src/utils/temporal-auth.js.map +1 -0
  330. package/dist/src/utils/temporal-codec.d.ts +101 -0
  331. package/dist/src/utils/temporal-codec.d.ts.map +1 -0
  332. package/dist/src/utils/temporal-codec.js +319 -0
  333. package/dist/src/utils/temporal-codec.js.map +1 -0
  334. package/dist/src/utils/tunnel-ownership.d.ts +130 -0
  335. package/dist/src/utils/tunnel-ownership.d.ts.map +1 -0
  336. package/dist/src/utils/tunnel-ownership.js +274 -0
  337. package/dist/src/utils/tunnel-ownership.js.map +1 -0
  338. package/dist/src/utils/vpn-join.d.ts +32 -0
  339. package/dist/src/utils/vpn-join.d.ts.map +1 -0
  340. package/dist/src/utils/vpn-join.js +62 -0
  341. package/dist/src/utils/vpn-join.js.map +1 -0
  342. package/dist/src/utils/vpn.d.ts +62 -0
  343. package/dist/src/utils/vpn.d.ts.map +1 -0
  344. package/dist/src/utils/vpn.js +183 -0
  345. package/dist/src/utils/vpn.js.map +1 -0
  346. package/dist/src/utils/workflow-fingerprint.d.ts +49 -0
  347. package/dist/src/utils/workflow-fingerprint.d.ts.map +1 -0
  348. package/dist/src/utils/workflow-fingerprint.js +135 -0
  349. package/dist/src/utils/workflow-fingerprint.js.map +1 -0
  350. package/dist/src/utils/worktree-identity.d.ts +86 -0
  351. package/dist/src/utils/worktree-identity.d.ts.map +1 -0
  352. package/dist/src/utils/worktree-identity.js +164 -0
  353. package/dist/src/utils/worktree-identity.js.map +1 -0
  354. package/fragments/agents/AGENTS.md.hbs +92 -0
  355. package/fragments/agents/CLAUDE.md.hbs +8 -0
  356. package/fragments/base/Pulumi.dev.yaml.hbs +10 -0
  357. package/fragments/base/Pulumi.yaml.hbs +9 -0
  358. package/fragments/base/index.ts.hbs +107 -0
  359. package/fragments/base/package.json.hbs +22 -0
  360. package/{templates/api-web-db/api → fragments/base}/tsconfig.json +3 -4
  361. package/fragments/bucket/api/src/storage.ts.hbs +81 -0
  362. package/fragments/database/api/src/db.ts.hbs +23 -0
  363. package/fragments/database/prisma/schema.prisma.hbs +18 -0
  364. package/{templates/api-web-db → fragments/service}/api/.dockerignore +2 -0
  365. package/fragments/service/api/package.json.hbs +40 -0
  366. package/fragments/service/api/src/index.ts.hbs +58 -0
  367. package/{templates/api-web-db → fragments/service/api}/tsconfig.json +5 -3
  368. package/fragments/temporal/worker/.dockerignore +4 -0
  369. package/fragments/temporal/worker/Dockerfile +15 -0
  370. package/{templates/temporal-api-worker → fragments/temporal}/worker/package.json.hbs +3 -2
  371. package/fragments/temporal/worker/src/activities.ts.hbs +14 -0
  372. package/fragments/temporal/worker/src/worker.ts.hbs +27 -0
  373. package/fragments/temporal/worker/src/workflows.ts.hbs +24 -0
  374. package/fragments/temporal/worker/tsconfig.json +13 -0
  375. package/package.json +35 -21
  376. package/skills/core/SKILL.md +365 -0
  377. package/skills/pull-remote-agent-context/SKILL.md +194 -0
  378. package/stack/docker-compose.hub.yml +134 -0
  379. package/stack/docker-compose.yml +447 -0
  380. package/stack/hub/Dockerfile.api +18 -0
  381. package/stack/hub/Dockerfile.auth +10 -0
  382. package/stack/hub/Dockerfile.ui +10 -0
  383. package/stack/init/01-databases.sql +12 -0
  384. package/stack/observability/blackbox.yml +20 -0
  385. package/stack/observability/otel-collector.yaml +73 -0
  386. package/stack/observability/prometheus.yml +36 -0
  387. package/stack/observability/tempo.yaml +25 -0
  388. package/stack/temporal/local.yaml +44 -0
  389. package/templates/api-auth/AGENTS.md.hbs +16 -0
  390. package/templates/api-auth/Pulumi.dev.yaml.hbs +8 -0
  391. package/templates/api-auth/Pulumi.yaml.hbs +8 -0
  392. package/templates/api-auth/README.md.hbs +67 -0
  393. package/templates/api-auth/api/package.json.hbs +28 -0
  394. package/templates/api-auth/api/src/index.ts.hbs +96 -0
  395. package/templates/api-auth/api/src/schema.ts.hbs +35 -0
  396. package/templates/api-auth/api/src/seed-authz.ts.hbs +48 -0
  397. package/templates/api-auth/api/src/spicedb-http-provider.ts.hbs +89 -0
  398. package/templates/api-auth/index.ts.hbs +65 -0
  399. package/templates/api-auth/package.json.hbs +20 -0
  400. package/templates/api-auth/skills/develop/SKILL.md.hbs +32 -0
  401. package/templates/api-role-gating/AGENTS.md.hbs +20 -0
  402. package/templates/api-role-gating/Pulumi.dev.yaml.hbs +8 -0
  403. package/templates/api-role-gating/Pulumi.yaml.hbs +8 -0
  404. package/templates/api-role-gating/README.md.hbs +64 -0
  405. package/templates/api-role-gating/api/Dockerfile +17 -0
  406. package/templates/api-role-gating/api/package.json.hbs +28 -0
  407. package/templates/api-role-gating/api/src/authn.ts.hbs +29 -0
  408. package/templates/api-role-gating/api/src/authz.ts.hbs +12 -0
  409. package/templates/api-role-gating/api/src/main.ts.hbs +58 -0
  410. package/templates/api-role-gating/api/src/schema.ts.hbs +22 -0
  411. package/templates/api-role-gating/api/tsconfig.json +13 -0
  412. package/templates/api-role-gating/index.ts.hbs +107 -0
  413. package/templates/api-role-gating/package.json.hbs +21 -0
  414. package/templates/api-role-gating/skills/develop/SKILL.md.hbs +60 -0
  415. package/templates/api-role-gating/tsconfig.json +10 -0
  416. package/templates/apps-repo/README.md.hbs +24 -0
  417. package/templates/apps-repo/gitignore +41 -0
  418. package/templates/apps-repo/npmrc.hbs +7 -0
  419. package/templates/apps-repo/package.json.hbs +15 -0
  420. package/templates/apps-repo/pnpm-workspace.yaml +3 -0
  421. package/templates/apps-repo/tsconfig.json +18 -0
  422. package/templates/external-service/AGENTS.md.hbs +20 -0
  423. package/templates/external-service/Pulumi.dev.yaml.hbs +8 -0
  424. package/templates/external-service/Pulumi.yaml.hbs +8 -0
  425. package/templates/external-service/README.md.hbs +56 -0
  426. package/templates/external-service/api/Dockerfile +15 -0
  427. package/templates/external-service/api/package.json.hbs +25 -0
  428. package/templates/external-service/api/src/index.ts.hbs +81 -0
  429. package/templates/external-service/index.ts.hbs +82 -0
  430. package/templates/external-service/mocks/vendorpay/package.json.hbs +9 -0
  431. package/templates/external-service/mocks/vendorpay/server.mjs.hbs +61 -0
  432. package/templates/external-service/package.json.hbs +34 -0
  433. package/templates/external-service/skills/develop/SKILL.md.hbs +55 -0
  434. package/templates/external-service/tsconfig.json +10 -0
  435. package/templates/platform-repo/AGENTS.md.hbs +18 -0
  436. package/templates/platform-repo/README.md.hbs +38 -0
  437. package/templates/platform-repo/core/Pulumi.yaml.hbs +12 -0
  438. package/templates/platform-repo/core/Pulumi.{{tenant}}-{{env}}.yaml.hbs +57 -0
  439. package/templates/platform-repo/core/index.ts +62 -0
  440. package/templates/platform-repo/core/package.json.hbs +22 -0
  441. package/templates/platform-repo/core/tsconfig.json +8 -0
  442. package/templates/platform-repo/package.json.hbs +15 -0
  443. package/templates/platform-repo/platform/Pulumi.yaml.hbs +12 -0
  444. package/templates/platform-repo/platform/Pulumi.{{tenant}}-{{env}}.yaml.hbs +59 -0
  445. package/templates/platform-repo/platform/index.ts +95 -0
  446. package/templates/platform-repo/platform/package.json.hbs +26 -0
  447. package/templates/platform-repo/platform/tsconfig.json +8 -0
  448. package/templates/platform-repo/pnpm-workspace.yaml +3 -0
  449. package/templates/workflow/AGENTS.md.hbs +15 -0
  450. package/templates/workflow/Pulumi.dev.yaml.hbs +8 -0
  451. package/templates/workflow/Pulumi.yaml.hbs +8 -0
  452. package/templates/workflow/README.md.hbs +45 -0
  453. package/templates/workflow/api/.dockerignore +4 -0
  454. package/templates/workflow/api/Dockerfile +15 -0
  455. package/templates/{temporal-api-worker → workflow}/api/package.json.hbs +8 -6
  456. package/templates/workflow/api/src/index.ts.hbs +130 -0
  457. package/templates/workflow/api/tsconfig.json +14 -0
  458. package/templates/workflow/index.ts.hbs +67 -0
  459. package/templates/workflow/package.json.hbs +20 -0
  460. package/templates/workflow/skills/develop/SKILL.md.hbs +32 -0
  461. package/templates/workflow/tsconfig.json +10 -0
  462. package/templates/workflow/worker/.dockerignore +4 -0
  463. package/templates/workflow/worker/Dockerfile +13 -0
  464. package/templates/workflow/worker/package.json.hbs +25 -0
  465. package/templates/workflow/worker/src/worker.ts.hbs +24 -0
  466. package/templates/workflow/worker/tsconfig.json +14 -0
  467. package/dist/src/commands/devbox.d.ts +0 -22
  468. package/dist/src/commands/devbox.d.ts.map +0 -1
  469. package/dist/src/commands/devbox.js +0 -463
  470. package/dist/src/commands/devbox.js.map +0 -1
  471. package/templates/api-web-db/api/Dockerfile +0 -16
  472. package/templates/api-web-db/api/package.json.hbs +0 -21
  473. package/templates/api-web-db/api/src/index.ts.hbs +0 -123
  474. package/templates/api-web-db/package.json.hbs +0 -27
  475. package/templates/api-web-db/sst.config.ts.hbs +0 -151
  476. package/templates/api-web-db/web/.dockerignore +0 -3
  477. package/templates/api-web-db/web/Dockerfile +0 -17
  478. package/templates/api-web-db/web/app/lib/db.server.ts +0 -36
  479. package/templates/api-web-db/web/app/root.tsx +0 -29
  480. package/templates/api-web-db/web/app/routes/home.tsx.hbs +0 -114
  481. package/templates/api-web-db/web/app/routes.ts +0 -3
  482. package/templates/api-web-db/web/package.json.hbs +0 -30
  483. package/templates/api-web-db/web/prisma/schema.prisma +0 -25
  484. package/templates/api-web-db/web/prisma.config.ts +0 -18
  485. package/templates/api-web-db/web/react-router.config.ts +0 -5
  486. package/templates/api-web-db/web/tsconfig.json +0 -19
  487. package/templates/api-web-db/web/vite.config.ts +0 -9
  488. package/templates/temporal-api-worker/README.md.hbs +0 -133
  489. package/templates/temporal-api-worker/api/src/index.ts.hbs +0 -145
  490. package/templates/temporal-api-worker/package.json.hbs +0 -29
  491. package/templates/temporal-api-worker/sst.config.ts.hbs +0 -161
  492. package/templates/temporal-api-worker/worker/Dockerfile +0 -11
  493. package/templates/temporal-api-worker/worker/src/bundle-workflows.ts +0 -38
  494. package/templates/temporal-api-worker/worker/src/worker.ts.hbs +0 -93
  495. /package/templates/{temporal-api-worker → api-auth}/api/.dockerignore +0 -0
  496. /package/templates/{temporal-api-worker → api-auth}/api/Dockerfile +0 -0
  497. /package/templates/{temporal-api-worker → api-auth}/api/tsconfig.json +0 -0
  498. /package/templates/{temporal-api-worker → api-auth}/tsconfig.json +0 -0
  499. /package/templates/{temporal-api-worker/worker → api-role-gating/api}/.dockerignore +0 -0
  500. /package/templates/{temporal-api-worker/worker → external-service/api}/tsconfig.json +0 -0
  501. /package/templates/{temporal-api-worker → workflow}/api/src/encryption-codec.ts +0 -0
  502. /package/templates/{temporal-api-worker → workflow}/worker/src/activities.ts.hbs +0 -0
  503. /package/templates/{temporal-api-worker → workflow}/worker/src/encryption-codec.ts +0 -0
  504. /package/templates/{temporal-api-worker → workflow}/worker/src/workflows.ts.hbs +0 -0
@@ -0,0 +1,781 @@
1
+ /**
2
+ * mesh temporal — inspect Temporal workflows for the current app/stack.
3
+ *
4
+ * Commands:
5
+ * mesh temporal describe <workflowId> [runId] Show workflow status and metadata
6
+ * mesh temporal history <workflowId> [runId] Show workflow event history
7
+ *
8
+ * Connection info is resolved from the app's Pulumi stack output (same as mesh dev).
9
+ * Uses the raw gRPC API so we can render events without a codec proxy; when
10
+ * `--show-payloads` is set we resolve the app's `TEMPORAL_ENCODING_KEY` from
11
+ * its Kubernetes secret and decrypt inline via the shared codec helper.
12
+ */
13
+ import { spawnSync } from "node:child_process";
14
+ import { writeFileSync, mkdirSync } from "node:fs";
15
+ import { homedir } from "node:os";
16
+ import { dirname, join, resolve } from "node:path";
17
+ import { logError, logInfo, logSuccess, logWarn } from "../utils/log.js";
18
+ import { classifyHistoryEvents, extractSnapshotMessages, reconstructTranscript, renderTranscriptMarkdown, } from "../utils/recover-conversation.js";
19
+ import { findAppRoot, findStackConfigs, getCurrentStack, pulumiStackOutput, readStackConfig, } from "../utils/pulumi.js";
20
+ import { resolveAwsCredentials } from "../utils/aws-auth.js";
21
+ import { resolveTemporalAuth, acquireTemporalBearer } from "../utils/temporal-auth.js";
22
+ import { buildDecrypterForNamespace, buildRawDecrypterForNamespace, } from "../utils/temporal-codec.js";
23
+ /**
24
+ * Resolve Temporal address and namespace from the current app's stack output.
25
+ * Falls back to env vars if stack output isn't available.
26
+ */
27
+ async function resolveConnection(options) {
28
+ // Explicit overrides take precedence
29
+ if (options.address && options.namespace) {
30
+ return { address: options.address, namespace: options.namespace };
31
+ }
32
+ // Try from environment (set by mesh dev)
33
+ if (!options.address && process.env.TEMPORAL_ADDRESS) {
34
+ const address = process.env.TEMPORAL_ADDRESS;
35
+ const namespace = options.namespace ?? process.env.TEMPORAL_NAMESPACE;
36
+ if (namespace)
37
+ return { address, namespace };
38
+ }
39
+ // Resolve from Pulumi stack output
40
+ const appRoot = findAppRoot(process.cwd());
41
+ if (!appRoot) {
42
+ throw new Error("Not in a Mesh app directory (no Pulumi.yaml found).\n" +
43
+ "Run from an app directory, or provide --address and --namespace.");
44
+ }
45
+ const stack = options.stack ?? getCurrentStack(appRoot);
46
+ if (!stack) {
47
+ const stacks = findStackConfigs(appRoot);
48
+ throw new Error(`No Pulumi stack selected.\n` +
49
+ (stacks.length > 0
50
+ ? `Available: ${stacks.join(", ")}\nUse: mesh temporal --stack <name> ...`
51
+ : "No stack configs found in this directory."));
52
+ }
53
+ const sa = stack ? ["--stack", stack] : [];
54
+ // Resolve AWS credentials the same way mesh dev does
55
+ const deployerRole = readStackConfig(appRoot, stack, "mesh:deployerRole");
56
+ const awsCreds = deployerRole
57
+ ? (await resolveAwsCredentials(deployerRole, appRoot, stack))?.env
58
+ : undefined;
59
+ // Pulumi's `app` output from env.register() is a struct containing a
60
+ // secret-tainted `dev` field (secret because service env vars include values
61
+ // like TEMPORAL_ENCODING_KEY). pulumiStackOutput transparently retries with
62
+ // --show-secrets when it sees a `"[secret]"` placeholder, so we can reach
63
+ // the non-sensitive tunnel/namespace fields nested inside.
64
+ let devOutput;
65
+ let appOutput;
66
+ try {
67
+ const result = pulumiStackOutput(appRoot, "app", sa, awsCreds);
68
+ appOutput = JSON.parse(result);
69
+ devOutput = appOutput.dev ?? appOutput;
70
+ }
71
+ catch {
72
+ // Legacy stacks that exported `dev` directly (pre-env.register() format).
73
+ try {
74
+ const result = pulumiStackOutput(appRoot, "dev", sa, awsCreds);
75
+ devOutput = JSON.parse(result);
76
+ appOutput = devOutput;
77
+ }
78
+ catch {
79
+ throw new Error(`Could not read stack output for '${stack}'.\n` +
80
+ "Ensure you've run: mesh deploy up\n" +
81
+ "Or provide --address and --namespace explicitly.");
82
+ }
83
+ }
84
+ const tunnel = devOutput?.tunnels?.temporal;
85
+ // namespace lives at the app output level, not inside dev
86
+ const namespace = options.namespace ?? appOutput?.namespace ?? devOutput?.namespace;
87
+ if (!tunnel) {
88
+ throw new Error("No temporal tunnel found in stack output.");
89
+ }
90
+ if (!namespace) {
91
+ throw new Error("No temporal namespace found in stack output.");
92
+ }
93
+ // Auth context for minting a Bearer, mirroring resolveTemporalAuthVars in dev.ts:
94
+ // tenant/env/name come from the PLATFORM block (platformName is the platform's
95
+ // name, not the app tenant — it keys the Zitadel issuer lookup).
96
+ const platform = (devOutput?.platform ?? appOutput?.platform);
97
+ const auth = platform
98
+ ? {
99
+ tenant: platform.tenant ?? "mesh",
100
+ env: platform.env ?? "dev",
101
+ platformName: platform.name ?? platform.tenant ?? "mesh",
102
+ }
103
+ : undefined;
104
+ return {
105
+ address: options.address ?? `${tunnel.host}:${tunnel.port}`,
106
+ namespace,
107
+ auth,
108
+ };
109
+ }
110
+ /**
111
+ * Mint a Zitadel Bearer for the connection, or return undefined to connect
112
+ * unauthenticated (correct for local/non-enforcing Temporal). Prefers ambient
113
+ * env creds (e.g. exported by `mesh dev`); otherwise resolves the app's M2M
114
+ * credentials from SSM via the auth context.
115
+ */
116
+ async function resolveBearerToken(auth) {
117
+ try {
118
+ const haveEnvCreds = !!process.env.TEMPORAL_AUTH_CLIENT_ID && !!process.env.ZITADEL_ISSUER;
119
+ const vars = !haveEnvCreds && auth
120
+ ? await resolveTemporalAuth(auth.tenant, auth.env, auth.platformName)
121
+ : {};
122
+ return await acquireTemporalBearer(vars);
123
+ }
124
+ catch (err) {
125
+ logWarn(`Temporal auth unavailable (${err instanceof Error ? err.message : String(err)}); ` +
126
+ `connecting unauthenticated`);
127
+ return undefined;
128
+ }
129
+ }
130
+ // ── Event type names ─────────────────────────────────────────────────────────
131
+ // Temporal event type enum → human-readable name
132
+ const EVENT_TYPE_NAMES = {
133
+ 1: "WorkflowExecutionStarted",
134
+ 2: "WorkflowExecutionCompleted",
135
+ 3: "WorkflowExecutionFailed",
136
+ 4: "WorkflowExecutionTimedOut",
137
+ 5: "WorkflowTaskScheduled",
138
+ 6: "WorkflowTaskStarted",
139
+ 7: "WorkflowTaskCompleted",
140
+ 8: "WorkflowTaskTimedOut",
141
+ 9: "WorkflowTaskFailed",
142
+ 10: "ActivityTaskScheduled",
143
+ 11: "ActivityTaskStarted",
144
+ 12: "ActivityTaskCompleted",
145
+ 13: "ActivityTaskFailed",
146
+ 14: "ActivityTaskTimedOut",
147
+ 15: "ActivityTaskCancelRequested",
148
+ 16: "ActivityTaskCanceled",
149
+ 17: "TimerStarted",
150
+ 18: "TimerFired",
151
+ 19: "TimerCanceled",
152
+ 20: "WorkflowExecutionCancelRequested",
153
+ 21: "WorkflowExecutionCanceled",
154
+ 24: "WorkflowExecutionSignaled", // not 22/23 which were removed
155
+ 25: "WorkflowExecutionTerminated",
156
+ 26: "WorkflowExecutionSignaled",
157
+ 29: "WorkflowPropertiesModified",
158
+ 40: "ChildWorkflowExecutionStarted",
159
+ 41: "ChildWorkflowExecutionCompleted",
160
+ 42: "ChildWorkflowExecutionFailed",
161
+ 43: "ChildWorkflowExecutionCanceled",
162
+ 44: "ChildWorkflowExecutionTimedOut",
163
+ 45: "ChildWorkflowExecutionTerminated",
164
+ 46: "WorkflowPropertiesModified",
165
+ 48: "NexusOperationScheduled",
166
+ 49: "NexusOperationStarted",
167
+ 50: "NexusOperationCompleted",
168
+ 51: "NexusOperationFailed",
169
+ 52: "NexusOperationCanceled",
170
+ 53: "NexusOperationTimedOut",
171
+ };
172
+ // Workflow status enum → name
173
+ const STATUS_NAMES = {
174
+ 0: "UNSPECIFIED",
175
+ 1: "RUNNING",
176
+ 2: "COMPLETED",
177
+ 3: "FAILED",
178
+ 4: "CANCELED",
179
+ 5: "TERMINATED",
180
+ 6: "CONTINUED_AS_NEW",
181
+ 7: "TIMED_OUT",
182
+ };
183
+ // ── Commands ─────────────────────────────────────────────────────────────────
184
+ async function describeWorkflow(workflowId, runId, options) {
185
+ const conn = await connect(options);
186
+ try {
187
+ const desc = await conn.connection.workflowService.describeWorkflowExecution({
188
+ namespace: conn.namespace,
189
+ execution: { workflowId, runId },
190
+ });
191
+ const info = desc.workflowExecutionInfo;
192
+ if (!info) {
193
+ logError("No workflow execution info returned.");
194
+ return;
195
+ }
196
+ console.log(`Workflow: ${workflowId}`);
197
+ console.log(`Run ID: ${info.execution?.runId ?? runId ?? "?"}`);
198
+ console.log(`Type: ${info.type?.name ?? "?"}`);
199
+ console.log(`Status: ${STATUS_NAMES[info.status ?? 0] ?? info.status}`);
200
+ console.log(`Task Queue: ${info.taskQueue ?? "?"}`);
201
+ console.log(`Namespace: ${conn.namespace}`);
202
+ // Pending activities
203
+ const pending = desc.pendingActivities ?? [];
204
+ if (pending.length > 0) {
205
+ console.log(`\nPending Activities (${pending.length}):`);
206
+ for (const pa of pending) {
207
+ console.log(` - ${pa.activityType?.name ?? "?"} (attempt ${pa.attempt}, state: ${pa.state})`);
208
+ }
209
+ }
210
+ // Pending nexus operations
211
+ const pendingNexus = desc.pendingNexusOperations ?? [];
212
+ if (pendingNexus.length > 0) {
213
+ console.log(`\nPending Nexus Operations (${pendingNexus.length}):`);
214
+ for (const pn of pendingNexus) {
215
+ console.log(` - ${pn.operation ?? "?"} → ${pn.endpoint ?? "?"} (state: ${pn.state})`);
216
+ }
217
+ }
218
+ }
219
+ finally {
220
+ conn.connection.close();
221
+ }
222
+ }
223
+ /**
224
+ * Page through a workflow's execution history, yielding each event in order.
225
+ * Shared by `history` (existing-history phase) and `recover-conversation` so the
226
+ * pagination logic lives in one place. Follow-mode long-polling is separate
227
+ * (it uses `waitNewEvent` + terminal detection) and stays in `showHistory`.
228
+ */
229
+ async function* iterHistoryEvents(workflowService, namespace, workflowId, runId, maximumPageSize = 100) {
230
+ let nextPageToken;
231
+ do {
232
+ const resp = await workflowService.getWorkflowExecutionHistory({
233
+ namespace,
234
+ execution: { workflowId, runId },
235
+ maximumPageSize,
236
+ nextPageToken,
237
+ });
238
+ for (const event of resp.history?.events ?? []) {
239
+ yield event;
240
+ }
241
+ nextPageToken = resp.nextPageToken?.length ? resp.nextPageToken : undefined;
242
+ } while (nextPageToken);
243
+ }
244
+ async function showHistory(workflowId, runId, options) {
245
+ const conn = await connect(options);
246
+ const maxEvents = options.follow ? Infinity : parseInt(options.limit ?? "200", 10);
247
+ // Compact mode skips WorkflowTask* events (scheduling noise)
248
+ const skipTypes = new Set([5, 6, 7, 8, 9]); // WorkflowTask*
249
+ // Resolve the per-app encoding key lazily — only when the caller asks for
250
+ // payload bodies. Failure to resolve is non-fatal: we print the history
251
+ // without payloads and the warning from buildDecrypterForNamespace tells
252
+ // the user why.
253
+ const decrypter = options.showPayloads
254
+ ? await buildDecrypterForNamespace(conn.namespace)
255
+ : undefined;
256
+ try {
257
+ let totalShown = 0;
258
+ let lastEventId = 0;
259
+ console.log(`History for ${workflowId} (namespace: ${conn.namespace})${options.follow ? " [following]" : ""}\n`);
260
+ // Fetch existing history first
261
+ for await (const event of iterHistoryEvents(conn.connection.workflowService, conn.namespace, workflowId, runId)) {
262
+ lastEventId = Number(event.eventId);
263
+ const eventType = event.eventType ?? 0;
264
+ if (options.compact !== false && skipTypes.has(eventType))
265
+ continue;
266
+ await printEvent(event, decrypter);
267
+ totalShown++;
268
+ if (totalShown >= maxEvents)
269
+ break;
270
+ }
271
+ if (!options.follow) {
272
+ console.log(`\n${totalShown} events shown.`);
273
+ return;
274
+ }
275
+ // Follow mode: long-poll for new events until workflow completes
276
+ const terminalTypes = new Set([2, 3, 4, 21, 27, 28]); // Completed, Failed, TimedOut, Canceled, Terminated, ContinuedAsNew
277
+ let done = false;
278
+ while (!done) {
279
+ try {
280
+ const resp = await conn.connection.workflowService.getWorkflowExecutionHistory({
281
+ namespace: conn.namespace,
282
+ execution: { workflowId, runId },
283
+ maximumPageSize: 100,
284
+ waitNewEvent: true,
285
+ // Start after the last event we've seen
286
+ ...(lastEventId > 0 ? { skipArchival: true } : {}),
287
+ });
288
+ for (const event of resp.history?.events ?? []) {
289
+ const eid = Number(event.eventId);
290
+ if (eid <= lastEventId)
291
+ continue; // already shown
292
+ lastEventId = eid;
293
+ const eventType = event.eventType ?? 0;
294
+ if (options.compact !== false && skipTypes.has(eventType))
295
+ continue;
296
+ await printEvent(event, decrypter);
297
+ totalShown++;
298
+ // Check if workflow reached a terminal state
299
+ if (terminalTypes.has(eventType)) {
300
+ done = true;
301
+ }
302
+ }
303
+ }
304
+ catch (err) {
305
+ // Connection reset or workflow completed between polls
306
+ if (err?.code === 5 /* NOT_FOUND */ || err?.message?.includes("not found")) {
307
+ console.log("\nWorkflow completed or not found.");
308
+ done = true;
309
+ }
310
+ else {
311
+ throw err;
312
+ }
313
+ }
314
+ }
315
+ console.log(`\n${totalShown} events shown (workflow ended).`);
316
+ }
317
+ finally {
318
+ conn.connection.close();
319
+ }
320
+ }
321
+ async function printEvent(event, decrypter) {
322
+ const eventType = event.eventType ?? 0;
323
+ const typeName = EVENT_TYPE_NAMES[eventType] ?? `Unknown(${eventType})`;
324
+ const id = String(event.eventId).padStart(4);
325
+ const detail = extractEventDetail(event);
326
+ const detailStr = detail ? ` — ${detail}` : "";
327
+ console.log(`${id} ${typeName}${detailStr}`);
328
+ if (!decrypter)
329
+ return;
330
+ // Print any named payload groups attached to this event — activity input/
331
+ // output, signal input, workflow start args, etc. — decrypted and pretty-
332
+ // printed under the header line with a 6-space indent so they align under
333
+ // the event ID column.
334
+ for (const group of extractEventPayloads(event)) {
335
+ const rendered = await renderPayloads(group.payloads, decrypter);
336
+ if (rendered === null)
337
+ continue;
338
+ console.log(` ${group.label}:`);
339
+ for (const line of rendered.split("\n")) {
340
+ console.log(` ${line}`);
341
+ }
342
+ }
343
+ }
344
+ /**
345
+ * Pick out the payload-bearing fields on a history event. Returns an empty
346
+ * array for events that carry no interesting data (workflow task lifecycle,
347
+ * timers, property modifications, etc.).
348
+ */
349
+ function extractEventPayloads(event) {
350
+ const groups = [];
351
+ const pushIfAny = (label, payloads) => {
352
+ if (payloads && payloads.length > 0)
353
+ groups.push({ label, payloads });
354
+ };
355
+ if (event.workflowExecutionStartedEventAttributes) {
356
+ pushIfAny("input", event.workflowExecutionStartedEventAttributes.input?.payloads);
357
+ }
358
+ if (event.workflowExecutionCompletedEventAttributes) {
359
+ pushIfAny("result", event.workflowExecutionCompletedEventAttributes.result?.payloads);
360
+ }
361
+ if (event.workflowExecutionFailedEventAttributes) {
362
+ const failure = event.workflowExecutionFailedEventAttributes.failure;
363
+ if (failure?.message)
364
+ groups.push({ label: "failure", payloads: [{ __failure: failure }] });
365
+ }
366
+ if (event.workflowExecutionSignaledEventAttributes) {
367
+ pushIfAny("signal input", event.workflowExecutionSignaledEventAttributes.input?.payloads);
368
+ }
369
+ if (event.activityTaskScheduledEventAttributes) {
370
+ pushIfAny("input", event.activityTaskScheduledEventAttributes.input?.payloads);
371
+ }
372
+ if (event.activityTaskCompletedEventAttributes) {
373
+ pushIfAny("result", event.activityTaskCompletedEventAttributes.result?.payloads);
374
+ }
375
+ if (event.activityTaskFailedEventAttributes) {
376
+ const failure = event.activityTaskFailedEventAttributes.failure;
377
+ if (failure?.message)
378
+ groups.push({ label: "failure", payloads: [{ __failure: failure }] });
379
+ }
380
+ if (event.nexusOperationScheduledEventAttributes) {
381
+ const input = event.nexusOperationScheduledEventAttributes.input;
382
+ if (input)
383
+ pushIfAny("input", [input]);
384
+ }
385
+ if (event.nexusOperationCompletedEventAttributes) {
386
+ const result = event.nexusOperationCompletedEventAttributes.result;
387
+ if (result)
388
+ pushIfAny("result", [result]);
389
+ }
390
+ if (event.nexusOperationFailedEventAttributes) {
391
+ const failure = event.nexusOperationFailedEventAttributes.failure;
392
+ if (failure?.message)
393
+ groups.push({ label: "failure", payloads: [{ __failure: failure }] });
394
+ }
395
+ return groups;
396
+ }
397
+ /**
398
+ * Render one or more payloads into a multi-line string, or return `null`
399
+ * when nothing rendered (e.g. all payloads were non-encrypted and empty).
400
+ *
401
+ * Failures (`{ __failure: ... }`) are rendered specially since they're a
402
+ * structured error, not an encrypted payload.
403
+ */
404
+ async function renderPayloads(payloads, decrypter) {
405
+ const parts = [];
406
+ for (const payload of payloads) {
407
+ if (payload && typeof payload === "object" && "__failure" in payload) {
408
+ const failure = payload.__failure;
409
+ parts.push(renderFailure(failure));
410
+ continue;
411
+ }
412
+ const decoded = await decrypter(payload);
413
+ if (decoded === null) {
414
+ parts.push("[non-encrypted payload]");
415
+ }
416
+ else {
417
+ parts.push(decoded);
418
+ }
419
+ }
420
+ return parts.length > 0 ? parts.join("\n---\n") : null;
421
+ }
422
+ function renderFailure(failure) {
423
+ const lines = [failure.message ?? "(no message)"];
424
+ if (failure.stackTrace)
425
+ lines.push(failure.stackTrace);
426
+ return lines.join("\n");
427
+ }
428
+ /** Extract a human-readable detail string from event attributes. */
429
+ function extractEventDetail(event) {
430
+ // Activity scheduled
431
+ if (event.activityTaskScheduledEventAttributes) {
432
+ const a = event.activityTaskScheduledEventAttributes;
433
+ return `activity: ${a.activityType?.name ?? "?"}, queue: ${a.taskQueue?.name ?? "?"}`;
434
+ }
435
+ // Activity completed
436
+ if (event.activityTaskCompletedEventAttributes) {
437
+ return `scheduledId: ${event.activityTaskCompletedEventAttributes.scheduledEventId}`;
438
+ }
439
+ // Activity failed
440
+ if (event.activityTaskFailedEventAttributes) {
441
+ const a = event.activityTaskFailedEventAttributes;
442
+ const msg = a.failure?.message ?? "";
443
+ return `scheduledId: ${a.scheduledEventId}${msg ? `, error: ${msg.slice(0, 120)}` : ""}`;
444
+ }
445
+ // Activity timed out
446
+ if (event.activityTaskTimedOutEventAttributes) {
447
+ return `scheduledId: ${event.activityTaskTimedOutEventAttributes.scheduledEventId}`;
448
+ }
449
+ // Nexus scheduled
450
+ if (event.nexusOperationScheduledEventAttributes) {
451
+ const a = event.nexusOperationScheduledEventAttributes;
452
+ return `endpoint: ${a.endpoint ?? "?"}, operation: ${a.operation ?? "?"}, service: ${a.service ?? "?"}`;
453
+ }
454
+ // Nexus completed/failed/timed out
455
+ if (event.nexusOperationCompletedEventAttributes) {
456
+ return `scheduledId: ${event.nexusOperationCompletedEventAttributes.scheduledEventId}`;
457
+ }
458
+ if (event.nexusOperationFailedEventAttributes) {
459
+ const a = event.nexusOperationFailedEventAttributes;
460
+ return `scheduledId: ${a.scheduledEventId}, error: ${a.failure?.message?.slice(0, 120) ?? "?"}`;
461
+ }
462
+ if (event.nexusOperationTimedOutEventAttributes) {
463
+ return `scheduledId: ${event.nexusOperationTimedOutEventAttributes.scheduledEventId}`;
464
+ }
465
+ // Signal
466
+ if (event.workflowExecutionSignaledEventAttributes) {
467
+ return `signal: ${event.workflowExecutionSignaledEventAttributes.signalName ?? "?"}`;
468
+ }
469
+ // Workflow started
470
+ if (event.workflowExecutionStartedEventAttributes) {
471
+ const a = event.workflowExecutionStartedEventAttributes;
472
+ return `type: ${a.workflowType?.name ?? "?"}, queue: ${a.taskQueue?.name ?? "?"}`;
473
+ }
474
+ // Workflow completed/failed
475
+ if (event.workflowExecutionCompletedEventAttributes)
476
+ return null;
477
+ if (event.workflowExecutionFailedEventAttributes) {
478
+ return `error: ${event.workflowExecutionFailedEventAttributes.failure?.message?.slice(0, 120) ?? "?"}`;
479
+ }
480
+ // Timer
481
+ if (event.timerStartedEventAttributes) {
482
+ const dur = event.timerStartedEventAttributes.startToFireTimeout;
483
+ return `timerId: ${event.timerStartedEventAttributes.timerId}, duration: ${dur?.seconds ?? "?"}s`;
484
+ }
485
+ if (event.timerFiredEventAttributes) {
486
+ return `timerId: ${event.timerFiredEventAttributes.timerId}`;
487
+ }
488
+ return null;
489
+ }
490
+ /**
491
+ * Reconstruct an agent conversation's transcript from its durable Temporal
492
+ * history — for when the worker can no longer replay it (code drift) but the
493
+ * history is intact. Fetches the full history (same client/decrypt path as
494
+ * `history`), classifies the `submit_user_message` signals (human turns) and
495
+ * `callLLM` activity completions (assistant turns), decrypts their payloads,
496
+ * and renders an ordered transcript.
497
+ */
498
+ async function recoverConversation(workflowId, runId, options) {
499
+ const conn = await connect(options);
500
+ // The history is encrypted — without the key there's nothing to reconstruct,
501
+ // so (unlike `history`) a missing key is fatal here.
502
+ const decrypter = await buildDecrypterForNamespace(conn.namespace);
503
+ if (!decrypter) {
504
+ conn.connection.close();
505
+ throw new Error("Cannot decrypt conversation payloads: no encoding key available.\n" +
506
+ "Set TEMPORAL_ENCODING_KEY (e.g. from a `mesh dev` worker env) or configure " +
507
+ "kubectl namespace read access, then retry.");
508
+ }
509
+ try {
510
+ // Decode one payload group (signal input / activity result) into a plain
511
+ // object. The decrypter yields pretty-printed JSON; parse it back. Any
512
+ // failure returns undefined so the pure reconstructor emits a placeholder.
513
+ const decodePayload = async (payloads) => {
514
+ const first = payloads?.[0];
515
+ if (first === undefined)
516
+ return undefined;
517
+ const decoded = await decrypter(first);
518
+ if (decoded === null)
519
+ return undefined;
520
+ try {
521
+ return JSON.parse(decoded);
522
+ }
523
+ catch {
524
+ return undefined;
525
+ }
526
+ };
527
+ // Collect the full history in order, then classify it (which activity
528
+ // completions were `callLLM`, which signals were `submit_user_message`)
529
+ // via the shared pure helper.
530
+ const rawEvents = [];
531
+ for await (const event of iterHistoryEvents(conn.connection.workflowService, conn.namespace, workflowId, runId)) {
532
+ rawEvents.push(event);
533
+ }
534
+ // --snapshot: emit the store-ready conversation blob with STRUCTURED
535
+ // ModelMessage[] (tool-call parts intact) for a full-fidelity backfill,
536
+ // rather than the flattened text turns. artifacts/focus are left empty —
537
+ // the artifact index isn't reconstructable from history here, and the store
538
+ // defaults them.
539
+ if (options.snapshot) {
540
+ const messages = await extractSnapshotMessages(rawEvents, decodePayload);
541
+ const blob = {
542
+ conversationId: workflowId,
543
+ messages,
544
+ artifacts: [],
545
+ focus: null,
546
+ };
547
+ const output = JSON.stringify(blob, null, 2) + "\n";
548
+ if (options.out) {
549
+ writeFileSync(options.out, output);
550
+ logSuccess(`Wrote snapshot (${messages.length} messages) to ${options.out}`);
551
+ }
552
+ else {
553
+ process.stdout.write(output);
554
+ }
555
+ return;
556
+ }
557
+ const events = await classifyHistoryEvents(rawEvents, decodePayload);
558
+ const turns = reconstructTranscript(events);
559
+ const output = options.json
560
+ ? JSON.stringify({
561
+ turns: turns.map((t) => ({
562
+ role: t.role,
563
+ text: t.text,
564
+ ...(t.toolCalls ? { toolCalls: t.toolCalls } : {}),
565
+ })),
566
+ }, null, 2) + "\n"
567
+ : renderTranscriptMarkdown(turns);
568
+ if (options.out) {
569
+ writeFileSync(options.out, output);
570
+ logSuccess(`Wrote ${turns.length} turns to ${options.out}`);
571
+ }
572
+ else {
573
+ process.stdout.write(output);
574
+ }
575
+ }
576
+ finally {
577
+ conn.connection.close();
578
+ }
579
+ }
580
+ /**
581
+ * Capture a workflow's FULL durable Temporal history to a replay fixture JSON
582
+ * file — for LOCAL replay debugging of a specific production break. This is the
583
+ * real-history counterpart of the CI gate's synthetic golden fixtures: the
584
+ * output is the same proto3-JSON `{ events }` shape `@mesh-tech/agent-sdk`'s
585
+ * `historyToFixture` produces, so it runs through `replayFixture` locally. It
586
+ * is never committed to the replay fixtures dir — those are synthetic goldens;
587
+ * this file holds real decrypted production data (see warning below).
588
+ *
589
+ * Payloads are DECRYPTED (via the same codec `history --show-payloads` uses) so
590
+ * the fixture replays under agent-sdk's plaintext converter. Because that means
591
+ * the file contains real customer/conversation data, the default output path is
592
+ * `~/.mesh/replay-histories/` — outside any git repo — and a loud warning is
593
+ * printed. An explicit `--out` inside a git repo is checked with
594
+ * `git check-ignore`; a non-ignored path gets a loud warning (but is not
595
+ * blocked). Like `recover-conversation`, a missing encoding key is fatal — an
596
+ * encrypted fixture can't be replayed.
597
+ */
598
+ async function captureHistory(workflowId, runId, options) {
599
+ const conn = await connect(options);
600
+ // A fixture whose payloads stay encrypted can't be replayed (the replayer
601
+ // uses a codec-free converter), so — like recover-conversation — treat a
602
+ // missing key as fatal rather than emitting a useless file.
603
+ const decrypter = await buildRawDecrypterForNamespace(conn.namespace);
604
+ if (!decrypter) {
605
+ conn.connection.close();
606
+ throw new Error("Cannot decrypt history payloads: no encoding key available.\n" +
607
+ "A replay fixture needs decrypted payloads. Set TEMPORAL_ENCODING_KEY " +
608
+ "(e.g. from a `mesh dev` worker env) or configure kubectl namespace read " +
609
+ "access, then retry.");
610
+ }
611
+ try {
612
+ const events = [];
613
+ for await (const event of iterHistoryEvents(conn.connection.workflowService, conn.namespace, workflowId, runId)) {
614
+ events.push(event);
615
+ }
616
+ if (events.length === 0) {
617
+ throw new Error(`No history events found for workflow '${workflowId}'` +
618
+ (runId ? ` (run ${runId})` : "") +
619
+ `. Check the workflow id and namespace (${conn.namespace}).`);
620
+ }
621
+ // Lazy import — pulls in @temporalio/common only when actually capturing,
622
+ // so the CLI still loads without the Temporal SDK installed.
623
+ const { serializeHistoryToFixture } = await import("../utils/capture-history.js");
624
+ const { fixture, eventCount, decryptedPayloads } = await serializeHistoryToFixture(events, decrypter);
625
+ const outPath = options.out ??
626
+ join(homedir(), ".mesh", "replay-histories", `${sanitizeFileId(workflowId)}.json`);
627
+ mkdirSync(dirname(outPath), { recursive: true });
628
+ if (options.out)
629
+ warnIfNotGitIgnored(options.out);
630
+ writeFileSync(outPath, JSON.stringify(fixture, null, 2) + "\n");
631
+ logSuccess(`Wrote replay history (${eventCount} events, ${decryptedPayloads} payloads decrypted) to ${outPath}`);
632
+ logWarn("⚠ This file contains DECRYPTED payloads — real customer/conversation " +
633
+ "data.\n" +
634
+ " For LOCAL replay debugging ONLY. Do NOT commit it. (CI golden " +
635
+ "fixtures are synthetic; this is the debugging counterpart.)");
636
+ }
637
+ finally {
638
+ conn.connection.close();
639
+ }
640
+ }
641
+ /** Make a workflow id safe to use as a filename (slashes, spaces, etc.). */
642
+ function sanitizeFileId(id) {
643
+ return id.replace(/[^A-Za-z0-9._-]/g, "_");
644
+ }
645
+ /**
646
+ * A replay fixture holds real DECRYPTED production data, so when the user
647
+ * points `--out` at a path inside a git repo we check whether that path is
648
+ * git-ignored (`git check-ignore`) and print a LOUD warning when it is not —
649
+ * we warn, we don't block. Best-effort: silent when git is unavailable or the
650
+ * path is outside any repo (exit code 128), since there is nothing to commit
651
+ * it into.
652
+ */
653
+ function warnIfNotGitIgnored(outPath) {
654
+ const abs = resolve(outPath);
655
+ try {
656
+ // Exit 0 = ignored, 1 = in a repo but NOT ignored, 128 = not a repo.
657
+ const res = spawnSync("git", ["-C", dirname(abs), "check-ignore", "-q", abs], {
658
+ stdio: "ignore",
659
+ });
660
+ if (res.status !== 1)
661
+ return;
662
+ }
663
+ catch {
664
+ return; // git missing/unusable — can't check, stay quiet
665
+ }
666
+ logWarn("⚠⚠⚠ OUTPUT PATH IS INSIDE A GIT REPO AND IS *NOT* GITIGNORED ⚠⚠⚠\n" +
667
+ ` ${abs}\n` +
668
+ " This fixture contains DECRYPTED production payloads. Add it to " +
669
+ ".gitignore or move it outside the repo — do NOT commit it.");
670
+ }
671
+ async function terminateWorkflow(workflowId, runId, options) {
672
+ const conn = await connect(options);
673
+ try {
674
+ await conn.connection.workflowService.terminateWorkflowExecution({
675
+ namespace: conn.namespace,
676
+ workflowExecution: { workflowId, runId },
677
+ reason: options.reason ?? "terminated via mesh temporal",
678
+ identity: "mesh-cli",
679
+ });
680
+ logSuccess(`Terminated ${workflowId}${runId ? ` (run ${runId})` : ""} in namespace ${conn.namespace}`);
681
+ }
682
+ finally {
683
+ conn.connection.close();
684
+ }
685
+ }
686
+ async function connect(options) {
687
+ const info = await resolveConnection(options);
688
+ logInfo(`Connecting to ${info.address} (namespace: ${info.namespace})`);
689
+ // Dynamic import — @temporalio/client is only available in workspaces
690
+ // that have it installed. The mesh-cli uses it from the monorepo.
691
+ const { Connection } = await import("@temporalio/client");
692
+ // Attach a Zitadel Bearer when the server enforces auth. Without it the
693
+ // MeshAuthorizer denies calls with "Request unauthorized" (e.g. terminate).
694
+ const token = await resolveBearerToken(info.auth);
695
+ const metadata = token ? { authorization: `Bearer ${token}` } : undefined;
696
+ const connection = await Connection.connect({ address: info.address, metadata });
697
+ return { connection, namespace: info.namespace };
698
+ }
699
+ // ── Registration ─────────────────────────────────────────────────────────────
700
+ export function registerTemporalCommands(program) {
701
+ const temporal = program
702
+ .command("temporal")
703
+ .description("Inspect Temporal workflows for the current app/stack");
704
+ const sharedOpts = (cmd) => cmd
705
+ .option("--stack <stack>", "Pulumi stack name (auto-detected from current directory)")
706
+ .option("--address <addr>", "Temporal server address (default: from stack output)")
707
+ .option("--namespace <ns>", "Temporal namespace (default: from stack output)");
708
+ sharedOpts(temporal
709
+ .command("describe <workflowId> [runId]")
710
+ .description("Show workflow status and metadata")).action(async (workflowId, runId, opts) => {
711
+ try {
712
+ await describeWorkflow(workflowId, runId, opts);
713
+ }
714
+ catch (err) {
715
+ logError(err instanceof Error ? err.message : String(err));
716
+ process.exitCode = 1;
717
+ }
718
+ });
719
+ sharedOpts(temporal
720
+ .command("terminate <workflowId> [runId]")
721
+ .description("Terminate a running workflow (e.g. a wedged/looping conversation)"))
722
+ .option("--reason <reason>", "Termination reason (recorded in workflow history)")
723
+ .action(async (workflowId, runId, opts) => {
724
+ try {
725
+ await terminateWorkflow(workflowId, runId, opts);
726
+ }
727
+ catch (err) {
728
+ logError(err instanceof Error ? err.message : String(err));
729
+ process.exitCode = 1;
730
+ }
731
+ });
732
+ sharedOpts(temporal
733
+ .command("history <workflowId> [runId]")
734
+ .description("Show workflow event history")
735
+ .option("-n, --limit <n>", "Maximum events to show (default: 200)")
736
+ .option("-f, --follow", "Tail the history, waiting for new events until the workflow completes")
737
+ .option("--no-compact", "Show all events including WorkflowTask scheduling noise")
738
+ .option("-p, --show-payloads", "Decrypt and print activity inputs/outputs (reads TEMPORAL_ENCODING_KEY from the app's K8s secret via kubectl)")).action(async (workflowId, runId, opts) => {
739
+ try {
740
+ await showHistory(workflowId, runId, opts);
741
+ }
742
+ catch (err) {
743
+ logError(err instanceof Error ? err.message : String(err));
744
+ process.exitCode = 1;
745
+ }
746
+ });
747
+ sharedOpts(temporal
748
+ .command("recover-conversation <workflowId> [runId]")
749
+ .description("Reconstruct an agent conversation transcript from durable Temporal history " +
750
+ "(for when the worker can no longer replay it). Requires the encoding key — " +
751
+ "reads TEMPORAL_ENCODING_KEY (or the app's K8s secret).")
752
+ .option("--out <path>", "Write the transcript to a file instead of stdout")
753
+ .option("--json", "Emit a structured { turns: [...] } JSON array instead of markdown")
754
+ .option("--snapshot", "Emit a store-ready conversation blob { conversationId, messages, artifacts, focus } " +
755
+ "with STRUCTURED ModelMessage[] (tool-call parts intact) for a full-fidelity backfill")).action(async (workflowId, runId, opts) => {
756
+ try {
757
+ await recoverConversation(workflowId, runId, opts);
758
+ }
759
+ catch (err) {
760
+ logError(err instanceof Error ? err.message : String(err));
761
+ process.exitCode = 1;
762
+ }
763
+ });
764
+ sharedOpts(temporal
765
+ .command("capture-history <workflowId> [runId]")
766
+ .description("Capture a workflow's full history to a replay fixture JSON (proto3-JSON, " +
767
+ "DECRYPTED payloads) for LOCAL replay debugging. Requires the encoding key. " +
768
+ "Defaults to ~/.mesh/replay-histories/<workflowId>.json (outside any repo) — " +
769
+ "do NOT commit the output.")
770
+ .option("--out <path>", "Output path (default: ~/.mesh/replay-histories/<workflowId>.json; a non-gitignored " +
771
+ "path inside a git repo triggers a loud warning)")).action(async (workflowId, runId, opts) => {
772
+ try {
773
+ await captureHistory(workflowId, runId, opts);
774
+ }
775
+ catch (err) {
776
+ logError(err instanceof Error ? err.message : String(err));
777
+ process.exitCode = 1;
778
+ }
779
+ });
780
+ }
781
+ //# sourceMappingURL=temporal.js.map