@agentuity/cli 2.0.10 → 2.0.12

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 (233) hide show
  1. package/dist/cache/resource-region.d.ts.map +1 -1
  2. package/dist/cache/resource-region.js +48 -25
  3. package/dist/cache/resource-region.js.map +1 -1
  4. package/dist/cmd/build/vite/agent-discovery.js +4 -4
  5. package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
  6. package/dist/cmd/build/vite/bun-dev-server.d.ts +20 -0
  7. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  8. package/dist/cmd/build/vite/bun-dev-server.js +62 -4
  9. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  10. package/dist/cmd/build/vite/index.d.ts +0 -1
  11. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  12. package/dist/cmd/build/vite/index.js +0 -1
  13. package/dist/cmd/build/vite/index.js.map +1 -1
  14. package/dist/cmd/build/vite/static-renderer.d.ts +17 -0
  15. package/dist/cmd/build/vite/static-renderer.d.ts.map +1 -1
  16. package/dist/cmd/build/vite/static-renderer.js +18 -6
  17. package/dist/cmd/build/vite/static-renderer.js.map +1 -1
  18. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  19. package/dist/cmd/build/vite/vite-asset-server-config.js +34 -27
  20. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  21. package/dist/cmd/build/vite/vite-asset-server.d.ts +9 -0
  22. package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
  23. package/dist/cmd/build/vite/vite-asset-server.js +5 -1
  24. package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
  25. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  26. package/dist/cmd/build/vite/vite-builder.js +12 -1
  27. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  28. package/dist/cmd/build/vite/ws-proxy.d.ts +15 -1
  29. package/dist/cmd/build/vite/ws-proxy.d.ts.map +1 -1
  30. package/dist/cmd/build/vite/ws-proxy.js +33 -0
  31. package/dist/cmd/build/vite/ws-proxy.js.map +1 -1
  32. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  33. package/dist/cmd/cloud/deploy.js +98 -39
  34. package/dist/cmd/cloud/deploy.js.map +1 -1
  35. package/dist/cmd/cloud/sandbox/checkpoint/create.d.ts.map +1 -1
  36. package/dist/cmd/cloud/sandbox/checkpoint/create.js +3 -4
  37. package/dist/cmd/cloud/sandbox/checkpoint/create.js.map +1 -1
  38. package/dist/cmd/cloud/sandbox/checkpoint/delete.d.ts.map +1 -1
  39. package/dist/cmd/cloud/sandbox/checkpoint/delete.js +3 -4
  40. package/dist/cmd/cloud/sandbox/checkpoint/delete.js.map +1 -1
  41. package/dist/cmd/cloud/sandbox/checkpoint/list.d.ts.map +1 -1
  42. package/dist/cmd/cloud/sandbox/checkpoint/list.js +3 -4
  43. package/dist/cmd/cloud/sandbox/checkpoint/list.js.map +1 -1
  44. package/dist/cmd/cloud/sandbox/checkpoint/restore.d.ts.map +1 -1
  45. package/dist/cmd/cloud/sandbox/checkpoint/restore.js +3 -4
  46. package/dist/cmd/cloud/sandbox/checkpoint/restore.js.map +1 -1
  47. package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -1
  48. package/dist/cmd/cloud/sandbox/create.js +13 -4
  49. package/dist/cmd/cloud/sandbox/create.js.map +1 -1
  50. package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -1
  51. package/dist/cmd/cloud/sandbox/delete.js +3 -4
  52. package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
  53. package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -1
  54. package/dist/cmd/cloud/sandbox/env.js +3 -5
  55. package/dist/cmd/cloud/sandbox/env.js.map +1 -1
  56. package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
  57. package/dist/cmd/cloud/sandbox/exec.js +114 -41
  58. package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
  59. package/dist/cmd/cloud/sandbox/execution/list.d.ts.map +1 -1
  60. package/dist/cmd/cloud/sandbox/execution/list.js +3 -5
  61. package/dist/cmd/cloud/sandbox/execution/list.js.map +1 -1
  62. package/dist/cmd/cloud/sandbox/fs/cp.d.ts.map +1 -1
  63. package/dist/cmd/cloud/sandbox/fs/cp.js +61 -113
  64. package/dist/cmd/cloud/sandbox/fs/cp.js.map +1 -1
  65. package/dist/cmd/cloud/sandbox/fs/download.d.ts.map +1 -1
  66. package/dist/cmd/cloud/sandbox/fs/download.js +11 -22
  67. package/dist/cmd/cloud/sandbox/fs/download.js.map +1 -1
  68. package/dist/cmd/cloud/sandbox/fs/ls.d.ts.map +1 -1
  69. package/dist/cmd/cloud/sandbox/fs/ls.js +3 -5
  70. package/dist/cmd/cloud/sandbox/fs/ls.js.map +1 -1
  71. package/dist/cmd/cloud/sandbox/fs/mkdir.d.ts.map +1 -1
  72. package/dist/cmd/cloud/sandbox/fs/mkdir.js +3 -5
  73. package/dist/cmd/cloud/sandbox/fs/mkdir.js.map +1 -1
  74. package/dist/cmd/cloud/sandbox/fs/rm.d.ts.map +1 -1
  75. package/dist/cmd/cloud/sandbox/fs/rm.js +3 -5
  76. package/dist/cmd/cloud/sandbox/fs/rm.js.map +1 -1
  77. package/dist/cmd/cloud/sandbox/fs/rmdir.d.ts.map +1 -1
  78. package/dist/cmd/cloud/sandbox/fs/rmdir.js +3 -5
  79. package/dist/cmd/cloud/sandbox/fs/rmdir.js.map +1 -1
  80. package/dist/cmd/cloud/sandbox/fs/upload.d.ts.map +1 -1
  81. package/dist/cmd/cloud/sandbox/fs/upload.js +7 -8
  82. package/dist/cmd/cloud/sandbox/fs/upload.js.map +1 -1
  83. package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
  84. package/dist/cmd/cloud/sandbox/get.js +21 -7
  85. package/dist/cmd/cloud/sandbox/get.js.map +1 -1
  86. package/dist/cmd/cloud/sandbox/job/create.d.ts.map +1 -1
  87. package/dist/cmd/cloud/sandbox/job/create.js +3 -4
  88. package/dist/cmd/cloud/sandbox/job/create.js.map +1 -1
  89. package/dist/cmd/cloud/sandbox/job/destroy.d.ts.map +1 -1
  90. package/dist/cmd/cloud/sandbox/job/destroy.js +3 -4
  91. package/dist/cmd/cloud/sandbox/job/destroy.js.map +1 -1
  92. package/dist/cmd/cloud/sandbox/job/get.d.ts.map +1 -1
  93. package/dist/cmd/cloud/sandbox/job/get.js +3 -4
  94. package/dist/cmd/cloud/sandbox/job/get.js.map +1 -1
  95. package/dist/cmd/cloud/sandbox/job/list.d.ts.map +1 -1
  96. package/dist/cmd/cloud/sandbox/job/list.js +3 -4
  97. package/dist/cmd/cloud/sandbox/job/list.js.map +1 -1
  98. package/dist/cmd/cloud/sandbox/job/logs.d.ts.map +1 -1
  99. package/dist/cmd/cloud/sandbox/job/logs.js +4 -4
  100. package/dist/cmd/cloud/sandbox/job/logs.js.map +1 -1
  101. package/dist/cmd/cloud/sandbox/pause.d.ts.map +1 -1
  102. package/dist/cmd/cloud/sandbox/pause.js +21 -5
  103. package/dist/cmd/cloud/sandbox/pause.js.map +1 -1
  104. package/dist/cmd/cloud/sandbox/resume.d.ts.map +1 -1
  105. package/dist/cmd/cloud/sandbox/resume.js +3 -4
  106. package/dist/cmd/cloud/sandbox/resume.js.map +1 -1
  107. package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -1
  108. package/dist/cmd/cloud/sandbox/run.js +36 -7
  109. package/dist/cmd/cloud/sandbox/run.js.map +1 -1
  110. package/dist/cmd/cloud/sandbox/util.d.ts +19 -0
  111. package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -1
  112. package/dist/cmd/cloud/sandbox/util.js +40 -2
  113. package/dist/cmd/cloud/sandbox/util.js.map +1 -1
  114. package/dist/cmd/coder/create.d.ts.map +1 -1
  115. package/dist/cmd/coder/create.js +18 -0
  116. package/dist/cmd/coder/create.js.map +1 -1
  117. package/dist/cmd/coder/index.d.ts.map +1 -1
  118. package/dist/cmd/coder/index.js +4 -0
  119. package/dist/cmd/coder/index.js.map +1 -1
  120. package/dist/cmd/coder/start.d.ts.map +1 -1
  121. package/dist/cmd/coder/start.js +52 -1
  122. package/dist/cmd/coder/start.js.map +1 -1
  123. package/dist/cmd/coder/tui-init.js +1 -1
  124. package/dist/cmd/coder/tui-init.js.map +1 -1
  125. package/dist/cmd/coder/update.d.ts.map +1 -1
  126. package/dist/cmd/coder/update.js +21 -1
  127. package/dist/cmd/coder/update.js.map +1 -1
  128. package/dist/cmd/coder/workspace/create.d.ts.map +1 -1
  129. package/dist/cmd/coder/workspace/create.js +57 -13
  130. package/dist/cmd/coder/workspace/create.js.map +1 -1
  131. package/dist/cmd/coder/workspace/index.d.ts.map +1 -1
  132. package/dist/cmd/coder/workspace/index.js +1 -1
  133. package/dist/cmd/coder/workspace/index.js.map +1 -1
  134. package/dist/cmd/coder/workspace/list.js +2 -2
  135. package/dist/cmd/coder/workspace/list.js.map +1 -1
  136. package/dist/cmd/dev/dev-lock.d.ts.map +1 -1
  137. package/dist/cmd/dev/dev-lock.js +43 -17
  138. package/dist/cmd/dev/dev-lock.js.map +1 -1
  139. package/dist/cmd/dev/index.d.ts.map +1 -1
  140. package/dist/cmd/dev/index.js +211 -125
  141. package/dist/cmd/dev/index.js.map +1 -1
  142. package/dist/cmd/dev/process-manager.d.ts +41 -1
  143. package/dist/cmd/dev/process-manager.d.ts.map +1 -1
  144. package/dist/cmd/dev/process-manager.js +160 -31
  145. package/dist/cmd/dev/process-manager.js.map +1 -1
  146. package/dist/cmd/project/create.d.ts.map +1 -1
  147. package/dist/cmd/project/create.js +0 -2
  148. package/dist/cmd/project/create.js.map +1 -1
  149. package/dist/cmd/project/index.d.ts.map +1 -1
  150. package/dist/cmd/project/index.js +0 -3
  151. package/dist/cmd/project/index.js.map +1 -1
  152. package/dist/cmd/project/template-flow.d.ts +0 -1
  153. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  154. package/dist/cmd/project/template-flow.js +1 -124
  155. package/dist/cmd/project/template-flow.js.map +1 -1
  156. package/dist/types.d.ts +1 -1
  157. package/package.json +7 -7
  158. package/src/cache/resource-region.ts +68 -44
  159. package/src/cmd/ai/prompt/web.md +43 -17
  160. package/src/cmd/build/vite/agent-discovery.ts +4 -4
  161. package/src/cmd/build/vite/bun-dev-server.ts +92 -6
  162. package/src/cmd/build/vite/index.ts +0 -1
  163. package/src/cmd/build/vite/static-renderer.ts +18 -7
  164. package/src/cmd/build/vite/vite-asset-server-config.ts +37 -27
  165. package/src/cmd/build/vite/vite-asset-server.ts +5 -1
  166. package/src/cmd/build/vite/vite-builder.ts +12 -1
  167. package/src/cmd/build/vite/ws-proxy.ts +52 -3
  168. package/src/cmd/cloud/deploy.ts +117 -49
  169. package/src/cmd/cloud/sandbox/checkpoint/create.ts +10 -4
  170. package/src/cmd/cloud/sandbox/checkpoint/delete.ts +10 -4
  171. package/src/cmd/cloud/sandbox/checkpoint/list.ts +10 -4
  172. package/src/cmd/cloud/sandbox/checkpoint/restore.ts +10 -4
  173. package/src/cmd/cloud/sandbox/create.ts +14 -4
  174. package/src/cmd/cloud/sandbox/delete.ts +10 -4
  175. package/src/cmd/cloud/sandbox/env.ts +10 -5
  176. package/src/cmd/cloud/sandbox/exec.ts +157 -42
  177. package/src/cmd/cloud/sandbox/execution/list.ts +10 -5
  178. package/src/cmd/cloud/sandbox/fs/cp.ts +94 -126
  179. package/src/cmd/cloud/sandbox/fs/download.ts +18 -25
  180. package/src/cmd/cloud/sandbox/fs/ls.ts +10 -5
  181. package/src/cmd/cloud/sandbox/fs/mkdir.ts +10 -5
  182. package/src/cmd/cloud/sandbox/fs/rm.ts +10 -5
  183. package/src/cmd/cloud/sandbox/fs/rmdir.ts +10 -5
  184. package/src/cmd/cloud/sandbox/fs/upload.ts +14 -8
  185. package/src/cmd/cloud/sandbox/get.ts +28 -7
  186. package/src/cmd/cloud/sandbox/job/create.ts +10 -4
  187. package/src/cmd/cloud/sandbox/job/destroy.ts +10 -4
  188. package/src/cmd/cloud/sandbox/job/get.ts +10 -4
  189. package/src/cmd/cloud/sandbox/job/list.ts +10 -4
  190. package/src/cmd/cloud/sandbox/job/logs.ts +11 -4
  191. package/src/cmd/cloud/sandbox/pause.ts +31 -5
  192. package/src/cmd/cloud/sandbox/resume.ts +10 -4
  193. package/src/cmd/cloud/sandbox/run.ts +49 -11
  194. package/src/cmd/cloud/sandbox/util.ts +63 -2
  195. package/src/cmd/coder/create.ts +24 -1
  196. package/src/cmd/coder/index.ts +4 -0
  197. package/src/cmd/coder/start.ts +63 -1
  198. package/src/cmd/coder/tui-init.ts +1 -1
  199. package/src/cmd/coder/update.ts +18 -1
  200. package/src/cmd/coder/workspace/create.ts +84 -15
  201. package/src/cmd/coder/workspace/index.ts +3 -1
  202. package/src/cmd/coder/workspace/list.ts +2 -2
  203. package/src/cmd/dev/dev-lock.ts +50 -16
  204. package/src/cmd/dev/index.ts +249 -134
  205. package/src/cmd/dev/process-manager.ts +173 -33
  206. package/src/cmd/project/create.ts +0 -2
  207. package/src/cmd/project/index.ts +0 -3
  208. package/src/cmd/project/template-flow.ts +0 -147
  209. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts +0 -45
  210. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts.map +0 -1
  211. package/dist/cmd/build/vite/public-asset-path-plugin.js +0 -166
  212. package/dist/cmd/build/vite/public-asset-path-plugin.js.map +0 -1
  213. package/dist/cmd/project/auth/generate.d.ts +0 -5
  214. package/dist/cmd/project/auth/generate.d.ts.map +0 -1
  215. package/dist/cmd/project/auth/generate.js +0 -102
  216. package/dist/cmd/project/auth/generate.js.map +0 -1
  217. package/dist/cmd/project/auth/index.d.ts +0 -2
  218. package/dist/cmd/project/auth/index.d.ts.map +0 -1
  219. package/dist/cmd/project/auth/index.js +0 -21
  220. package/dist/cmd/project/auth/index.js.map +0 -1
  221. package/dist/cmd/project/auth/init.d.ts +0 -2
  222. package/dist/cmd/project/auth/init.d.ts.map +0 -1
  223. package/dist/cmd/project/auth/init.js +0 -213
  224. package/dist/cmd/project/auth/init.js.map +0 -1
  225. package/dist/cmd/project/auth/shared.d.ts +0 -93
  226. package/dist/cmd/project/auth/shared.d.ts.map +0 -1
  227. package/dist/cmd/project/auth/shared.js +0 -475
  228. package/dist/cmd/project/auth/shared.js.map +0 -1
  229. package/src/cmd/build/vite/public-asset-path-plugin.ts +0 -209
  230. package/src/cmd/project/auth/generate.ts +0 -116
  231. package/src/cmd/project/auth/index.ts +0 -21
  232. package/src/cmd/project/auth/init.ts +0 -256
  233. package/src/cmd/project/auth/shared.ts +0 -591
@@ -95,6 +95,21 @@ const DeployResponseSchema = z.object({
95
95
  .describe('Deployment URLs'),
96
96
  });
97
97
 
98
+ /**
99
+ * Render the final "Uploaded N assets ..." line after a successful CDN
100
+ * upload pass. Reports both the original and on-the-wire totals when gzip
101
+ * compressed at least one file, so the user can see the real transfer cost.
102
+ */
103
+ function formatUploadSummary(count: number, rawBytes: number, transferredBytes: number): string {
104
+ const noun = tui.plural(count, 'asset', 'assets');
105
+ // When no compression happened (icons, fonts, binaries), rawBytes ===
106
+ // transferredBytes and the extra detail would just be noise.
107
+ if (transferredBytes === rawBytes) {
108
+ return `✓ Uploaded ${count} ${noun} (${tui.formatBytes(rawBytes)}) to CDN`;
109
+ }
110
+ return `✓ Uploaded ${count} ${noun} (${tui.formatBytes(transferredBytes)} on wire, ${tui.formatBytes(rawBytes)} raw) to CDN`;
111
+ }
112
+
98
113
  export const deploySubcommand = createSubcommand({
99
114
  name: 'deploy',
100
115
  description: 'Deploy project to the Agentuity Cloud',
@@ -848,8 +863,12 @@ export const deploySubcommand = createSubcommand({
848
863
  }
849
864
 
850
865
  progress(80);
851
- let bytes = 0;
852
- if (build?.assets) {
866
+ // Track both the raw on-disk size and the actual bytes we put on
867
+ // the wire. For gzipped assets these differ significantly; reporting
868
+ // the transferred total gives the user an honest view of CDN cost.
869
+ let rawBytes = 0;
870
+ let transferredBytes = 0;
871
+ if (build?.assets && build.assets.length > 0) {
853
872
  // Start CDN upload diagnostic
854
873
  const endCdnUploadDiagnostic = collector.startDiagnostic('cdn-upload');
855
874
  ctx.logger.trace(`Uploading ${build.assets.length} assets`);
@@ -863,31 +882,64 @@ export const deploySubcommand = createSubcommand({
863
882
  return stepError(errorMsg);
864
883
  }
865
884
 
866
- // Process assets in batches with limited concurrency
867
- const concurrency = Math.min(4, build.assets.length);
868
- for (let i = 0; i < build.assets.length; i += concurrency) {
869
- const batch = build.assets.slice(i, i + concurrency);
870
- const promises: Promise<Response>[] = [];
871
-
872
- for (const asset of batch) {
873
- const assetUrl = instructions.assets[asset.filename];
874
- if (!assetUrl) {
875
- return stepError(
876
- `server did not provide upload URL for asset "${asset.filename}"; upload aborted`
877
- );
885
+ // Pre-flight: every asset the build emitted must have a signed
886
+ // PUT URL from the backend. Failing up-front gives a single
887
+ // clear error instead of aborting mid-batch with partial uploads.
888
+ for (const asset of build.assets) {
889
+ if (!instructions.assets[asset.filename]) {
890
+ const errorMsg = `server did not provide upload URL for asset "${asset.filename}"; upload aborted`;
891
+ collector.addGeneralError('deploy', errorMsg, 'DEPLOY006');
892
+ if (opts.reportFile) {
893
+ await collector.forceWrite();
878
894
  }
895
+ return stepError(errorMsg);
896
+ }
897
+ rawBytes += asset.size;
898
+ }
879
899
 
880
- // Asset filename already includes the subdirectory (e.g., "client/assets/main-abc123.js")
900
+ // Track every temp gzip file we create so we can clean them up
901
+ // even if the deploy is aborted mid-upload (e.g. Ctrl+C).
902
+ const tempFiles = new Set<string>();
903
+ const cleanupTempFiles = () => {
904
+ for (const p of tempFiles) {
905
+ try {
906
+ unlinkSync(p);
907
+ } catch {
908
+ // ignore — may already be gone
909
+ }
910
+ }
911
+ tempFiles.clear();
912
+ };
913
+
914
+ // Hoist narrowed locals for use inside the async upload closure;
915
+ // TS doesn't propagate narrowings of `build` / `instructions`
916
+ // across async callbacks, and we've already null-checked both
917
+ // above.
918
+ const assets = build.assets;
919
+ const assetUrls = instructions.assets;
920
+
921
+ try {
922
+ // Upload each asset with bounded concurrency. gzip compression
923
+ // runs inside the per-asset task, so compressible files
924
+ // compress in parallel (up to `concurrency`) rather than
925
+ // serially — a meaningful win for builds with many JS/CSS
926
+ // chunks since gzip is single-threaded per call.
927
+ const uploadOne = async (
928
+ asset: (typeof assets)[number]
929
+ ): Promise<void> => {
930
+ const assetUrl = assetUrls[asset.filename]!;
931
+ // Asset filename already includes the subdirectory
932
+ // (e.g., "client/assets/main-abc123.js").
881
933
  const filePath = join(projectDir, '.agentuity', asset.filename);
882
934
 
883
935
  const headers: Record<string, string> = {
884
936
  'Content-Type': asset.contentType,
885
937
  };
886
938
 
887
- bytes += asset.size;
888
-
889
939
  let body: Blob;
890
940
  let gzTempPath: string | undefined;
941
+ let onWireSize = asset.size;
942
+
891
943
  if (asset.contentEncoding === 'gzip') {
892
944
  // Gzip to a temp file so Bun.file() can provide
893
945
  // Content-Length to S3 (streaming bodies use chunked
@@ -896,6 +948,7 @@ export const deploySubcommand = createSubcommand({
896
948
  tmpdir(),
897
949
  `agentuity-asset-${deployment.id}-${Date.now()}-${asset.filename.replace(/\//g, '_')}.gz`
898
950
  );
951
+ tempFiles.add(gzTempPath);
899
952
  await pipeline(
900
953
  createReadStream(filePath),
901
954
  createGzip(),
@@ -903,57 +956,72 @@ export const deploySubcommand = createSubcommand({
903
956
  );
904
957
  headers['Content-Encoding'] = 'gzip';
905
958
  body = Bun.file(gzTempPath);
906
- const compressedSize = body.size;
959
+ onWireSize = body.size;
907
960
  ctx.logger.trace(
908
- `Gzip compressed ${asset.filename} (${asset.size} -> ${compressedSize} bytes)`
961
+ `Gzip compressed ${asset.filename} (${asset.size} -> ${onWireSize} bytes)`
909
962
  );
910
963
  } else {
911
964
  body = Bun.file(filePath);
912
965
  }
913
966
 
914
- const assetGzTempPath = gzTempPath;
915
- promises.push(
916
- fetch(assetUrl, {
917
- method: 'PUT',
918
- headers,
919
- body,
920
- signal: stepCtx.signal,
921
- }).then((response) => {
922
- // Clean up temp gzip file after upload completes
923
- if (assetGzTempPath) {
924
- try {
925
- unlinkSync(assetGzTempPath);
926
- } catch {
927
- // ignore — file may already be cleaned up
928
- }
929
- }
930
- return response;
931
- })
932
- );
933
- }
967
+ const response = await fetch(assetUrl, {
968
+ method: 'PUT',
969
+ headers,
970
+ body,
971
+ signal: stepCtx.signal,
972
+ });
934
973
 
935
- const resps = await Promise.all(promises);
936
- for (const r of resps) {
937
- if (!r.ok) {
938
- const errorMsg = `error uploading asset: ${await r.text()}`;
939
- collector.addGeneralError('deploy', errorMsg, 'DEPLOY006');
940
- if (opts.reportFile) {
941
- await collector.forceWrite();
974
+ if (gzTempPath) {
975
+ try {
976
+ unlinkSync(gzTempPath);
977
+ } catch {
978
+ // ignore
942
979
  }
943
- return stepError(errorMsg);
980
+ tempFiles.delete(gzTempPath);
944
981
  }
982
+
983
+ if (!response.ok) {
984
+ throw new Error(
985
+ `asset "${asset.filename}" upload failed: ${response.status} ${await response.text()}`
986
+ );
987
+ }
988
+
989
+ transferredBytes += onWireSize;
990
+ };
991
+
992
+ const concurrency = Math.min(4, assets.length);
993
+ for (let i = 0; i < assets.length; i += concurrency) {
994
+ const batch = assets.slice(i, i + concurrency);
995
+ await Promise.all(batch.map(uploadOne));
945
996
  }
997
+ } catch (error) {
998
+ cleanupTempFiles();
999
+ const errorMsg = error instanceof Error ? error.message : String(error);
1000
+ collector.addGeneralError('deploy', errorMsg, 'DEPLOY006');
1001
+ if (opts.reportFile) {
1002
+ await collector.forceWrite();
1003
+ }
1004
+ return stepError(errorMsg);
946
1005
  }
947
- ctx.logger.trace('Asset uploads complete');
1006
+
1007
+ ctx.logger.trace(
1008
+ `Asset uploads complete: ${build.assets.length} files, raw=${rawBytes}B, on-wire=${transferredBytes}B`
1009
+ );
948
1010
  endCdnUploadDiagnostic();
949
1011
  progress(95);
1012
+ } else {
1013
+ ctx.logger.debug('No assets to upload to CDN');
950
1014
  }
951
1015
 
952
1016
  progress(100);
953
1017
  const output = build?.assets.length
954
1018
  ? [
955
1019
  tui.muted(
956
- `✓ Uploaded ${build.assets.length} ${tui.plural(build.assets.length, 'asset', 'assets')} (${tui.formatBytes(bytes)}) to CDN`
1020
+ formatUploadSummary(
1021
+ build.assets.length,
1022
+ rawBytes,
1023
+ transferredBytes
1024
+ )
957
1025
  ),
958
1026
  ]
959
1027
  : undefined;
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { createCommand } from '../../../../types';
3
3
  import * as tui from '../../../../tui';
4
- import { createSandboxClient } from '../util';
4
+ import { createSandboxClient, resolveSandboxTarget } from '../util';
5
5
  import { getCommand } from '../../../../command-prefix';
6
- import { sandboxResolve, diskCheckpointCreate } from '@agentuity/server';
6
+ import { diskCheckpointCreate } from '@agentuity/server';
7
7
 
8
8
  const CheckpointCreateResponseSchema = z.object({
9
9
  success: z.boolean().describe('Whether the operation succeeded'),
@@ -42,8 +42,14 @@ export const createSubcommand = createCommand({
42
42
 
43
43
  const started = Date.now();
44
44
 
45
- // Resolve sandbox to get region and orgId using CLI API
46
- const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
45
+ const sandboxInfo = await resolveSandboxTarget(
46
+ logger,
47
+ auth,
48
+ apiClient,
49
+ args.sandboxId,
50
+ ctx.config?.name ?? 'production',
51
+ ctx.config
52
+ );
47
53
 
48
54
  const client = createSandboxClient(logger, auth, sandboxInfo.region);
49
55
 
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { createCommand } from '../../../../types';
3
3
  import * as tui from '../../../../tui';
4
- import { createSandboxClient } from '../util';
4
+ import { createSandboxClient, resolveSandboxTarget } from '../util';
5
5
  import { getCommand } from '../../../../command-prefix';
6
- import { sandboxResolve, diskCheckpointDelete } from '@agentuity/server';
6
+ import { diskCheckpointDelete } from '@agentuity/server';
7
7
 
8
8
  const CheckpointDeleteResponseSchema = z.object({
9
9
  success: z.boolean().describe('Whether the operation succeeded'),
@@ -63,8 +63,14 @@ export const deleteSubcommand = createCommand({
63
63
 
64
64
  const started = Date.now();
65
65
 
66
- // Resolve sandbox to get region and orgId using CLI API
67
- const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
66
+ const sandboxInfo = await resolveSandboxTarget(
67
+ logger,
68
+ auth,
69
+ apiClient,
70
+ args.sandboxId,
71
+ ctx.config?.name ?? 'production',
72
+ ctx.config
73
+ );
68
74
 
69
75
  const client = createSandboxClient(logger, auth, sandboxInfo.region);
70
76
 
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { createCommand } from '../../../../types';
3
3
  import * as tui from '../../../../tui';
4
- import { createSandboxClient } from '../util';
4
+ import { createSandboxClient, resolveSandboxTarget } from '../util';
5
5
  import { getCommand } from '../../../../command-prefix';
6
- import { sandboxResolve, diskCheckpointList } from '@agentuity/server';
6
+ import { diskCheckpointList } from '@agentuity/server';
7
7
 
8
8
  const CheckpointInfoSchema = z.object({
9
9
  id: z.string(),
@@ -40,8 +40,14 @@ export const listSubcommand = createCommand({
40
40
  async handler(ctx) {
41
41
  const { args, options, auth, logger, apiClient } = ctx;
42
42
 
43
- // Resolve sandbox to get region and orgId using CLI API
44
- const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
43
+ const sandboxInfo = await resolveSandboxTarget(
44
+ logger,
45
+ auth,
46
+ apiClient,
47
+ args.sandboxId,
48
+ ctx.config?.name ?? 'production',
49
+ ctx.config
50
+ );
45
51
 
46
52
  const client = createSandboxClient(logger, auth, sandboxInfo.region);
47
53
 
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { createCommand } from '../../../../types';
3
3
  import * as tui from '../../../../tui';
4
- import { createSandboxClient } from '../util';
4
+ import { createSandboxClient, resolveSandboxTarget } from '../util';
5
5
  import { getCommand } from '../../../../command-prefix';
6
- import { sandboxResolve, diskCheckpointRestore } from '@agentuity/server';
6
+ import { diskCheckpointRestore } from '@agentuity/server';
7
7
 
8
8
  const CheckpointRestoreResponseSchema = z.object({
9
9
  success: z.boolean().describe('Whether the operation succeeded'),
@@ -42,8 +42,14 @@ export const restoreSubcommand = createCommand({
42
42
 
43
43
  const started = Date.now();
44
44
 
45
- // Resolve sandbox to get region and orgId using CLI API
46
- const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
45
+ const sandboxInfo = await resolveSandboxTarget(
46
+ logger,
47
+ auth,
48
+ apiClient,
49
+ args.sandboxId,
50
+ ctx.config?.name ?? 'production',
51
+ ctx.config
52
+ );
47
53
 
48
54
  const client = createSandboxClient(logger, auth, sandboxInfo.region);
49
55
 
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { createCommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
- import { createSandboxClient, parseFileArgs, cacheSandboxRegion } from './util';
4
+ import { createSandboxClient, parseFileArgs, cacheSandboxTarget } from './util';
5
5
  import { getCommand } from '../../../command-prefix';
6
6
  import { sandboxCreate } from '@agentuity/server';
7
7
  import { StructuredError } from '@agentuity/core';
@@ -72,6 +72,10 @@ export const createSubcommand = createCommand({
72
72
  .string()
73
73
  .optional()
74
74
  .describe('Idle timeout before sandbox is reaped (e.g., "10m", "1h")'),
75
+ pausedTimeout: z
76
+ .string()
77
+ .optional()
78
+ .describe('Maximum time sandbox can remain paused before termination (e.g., "24h")'),
75
79
  env: z.array(z.string()).optional().describe('Environment variables (KEY=VALUE)'),
76
80
  file: z
77
81
  .array(z.string())
@@ -195,7 +199,13 @@ export const createSubcommand = createCommand({
195
199
  opts.network || opts.port
196
200
  ? { enabled: opts.network || opts.port !== undefined, port: opts.port }
197
201
  : undefined,
198
- timeout: opts.idleTimeout ? { idle: opts.idleTimeout } : undefined,
202
+ timeout:
203
+ opts.idleTimeout || opts.pausedTimeout
204
+ ? {
205
+ idle: opts.idleTimeout,
206
+ paused: opts.pausedTimeout,
207
+ }
208
+ : undefined,
199
209
  env: Object.keys(envMap).length > 0 ? envMap : undefined,
200
210
  files: hasFiles ? files : undefined,
201
211
  snapshot: opts.snapshot,
@@ -206,8 +216,8 @@ export const createSubcommand = createCommand({
206
216
  orgId,
207
217
  });
208
218
 
209
- // Cache the region for future lookups
210
- await cacheSandboxRegion(config?.name, result.sandboxId, region);
219
+ // Cache routing context for future sandbox commands.
220
+ await cacheSandboxTarget(config?.name, result.sandboxId, region, orgId);
211
221
 
212
222
  if (!options.json) {
213
223
  const duration = Date.now() - started;
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { createCommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
- import { createSandboxClient, clearSandboxRegionCache } from './util';
4
+ import { createSandboxClient, clearSandboxRegionCache, resolveSandboxTarget } from './util';
5
5
  import { getCommand } from '../../../command-prefix';
6
- import { sandboxDestroy, sandboxResolve } from '@agentuity/server';
6
+ import { sandboxDestroy } from '@agentuity/server';
7
7
 
8
8
  const SandboxDeleteResponseSchema = z.object({
9
9
  success: z.boolean().describe('Whether the operation succeeded'),
@@ -57,8 +57,14 @@ export const deleteSubcommand = createCommand({
57
57
 
58
58
  const started = Date.now();
59
59
 
60
- // Resolve sandbox to get region and orgId using CLI API
61
- const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
60
+ const sandboxInfo = await resolveSandboxTarget(
61
+ logger,
62
+ auth,
63
+ apiClient,
64
+ args.sandboxId,
65
+ config?.name ?? 'production',
66
+ config
67
+ );
62
68
 
63
69
  const client = createSandboxClient(logger, auth, sandboxInfo.region);
64
70
 
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { createCommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
- import { createSandboxClient } from './util';
4
+ import { createSandboxClient, resolveSandboxTarget } from './util';
5
5
  import { getCommand } from '../../../command-prefix';
6
- import { sandboxSetEnv, sandboxResolve } from '@agentuity/server';
6
+ import { sandboxSetEnv } from '@agentuity/server';
7
7
 
8
8
  export const envSubcommand = createCommand({
9
9
  name: 'env',
@@ -44,9 +44,14 @@ export const envSubcommand = createCommand({
44
44
  async handler(ctx) {
45
45
  const { args, opts, options, auth, logger, apiClient } = ctx;
46
46
 
47
- // Resolve sandbox to get region and orgId using CLI API
48
- const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
49
- const { region, orgId } = sandboxInfo;
47
+ const { region, orgId } = await resolveSandboxTarget(
48
+ logger,
49
+ auth,
50
+ apiClient,
51
+ args.sandboxId,
52
+ ctx.config?.name ?? 'production',
53
+ ctx.config
54
+ );
50
55
 
51
56
  const client = createSandboxClient(logger, auth, region);
52
57