@asteroidai/cli 1.9.11 → 1.9.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.
package/dist/asteroid.js CHANGED
@@ -124,7 +124,8 @@ var COMMANDS = [
124
124
  query: [],
125
125
  binary: false,
126
126
  readOnly: false,
127
- destructive: false
127
+ destructive: false,
128
+ capability: "run_execution"
128
129
  },
129
130
  {
130
131
  command: "context",
@@ -1030,7 +1031,8 @@ var COMMANDS = [
1030
1031
  ],
1031
1032
  files: [],
1032
1033
  credentialOrganization: false
1033
- }
1034
+ },
1035
+ capability: "run_execution"
1034
1036
  },
1035
1037
  {
1036
1038
  command: "execution resume",
@@ -1050,7 +1052,8 @@ var COMMANDS = [
1050
1052
  query: [],
1051
1053
  binary: false,
1052
1054
  readOnly: false,
1053
- destructive: false
1055
+ destructive: false,
1056
+ capability: "run_execution"
1054
1057
  },
1055
1058
  {
1056
1059
  command: "insight get",
@@ -1898,7 +1901,8 @@ var COMMANDS = [
1898
1901
  ],
1899
1902
  files: [],
1900
1903
  credentialOrganization: false
1901
- }
1904
+ },
1905
+ capability: "run_execution"
1902
1906
  },
1903
1907
  {
1904
1908
  command: "schedule delete",
@@ -1924,7 +1928,8 @@ var COMMANDS = [
1924
1928
  query: [],
1925
1929
  binary: false,
1926
1930
  readOnly: false,
1927
- destructive: true
1931
+ destructive: true,
1932
+ capability: "run_execution"
1928
1933
  },
1929
1934
  {
1930
1935
  command: "schedule get",
@@ -2105,7 +2110,8 @@ var COMMANDS = [
2105
2110
  ],
2106
2111
  files: [],
2107
2112
  credentialOrganization: false
2108
- }
2113
+ },
2114
+ capability: "run_execution"
2109
2115
  },
2110
2116
  {
2111
2117
  command: "scheduled-execution cancel",
@@ -2125,7 +2131,8 @@ var COMMANDS = [
2125
2131
  query: [],
2126
2132
  binary: false,
2127
2133
  readOnly: false,
2128
- destructive: false
2134
+ destructive: false,
2135
+ capability: "run_execution"
2129
2136
  },
2130
2137
  {
2131
2138
  command: "scheduled-execution create",
@@ -2193,7 +2200,8 @@ var COMMANDS = [
2193
2200
  ],
2194
2201
  files: [],
2195
2202
  credentialOrganization: false
2196
- }
2203
+ },
2204
+ capability: "run_execution"
2197
2205
  },
2198
2206
  {
2199
2207
  command: "scheduled-execution list",
@@ -2295,7 +2303,8 @@ var COMMANDS = [
2295
2303
  ],
2296
2304
  files: [],
2297
2305
  credentialOrganization: false
2298
- }
2306
+ },
2307
+ capability: "run_execution"
2299
2308
  },
2300
2309
  {
2301
2310
  command: "schema validate",
@@ -3435,7 +3444,8 @@ var COMMANDS = [
3435
3444
  ],
3436
3445
  files: [],
3437
3446
  credentialOrganization: false
3438
- }
3447
+ },
3448
+ capability: "run_execution"
3439
3449
  },
3440
3450
  {
3441
3451
  command: "workflow execute-sync",
@@ -3534,112 +3544,8 @@ var COMMANDS = [
3534
3544
  ],
3535
3545
  files: [],
3536
3546
  credentialOrganization: false
3537
- }
3538
- },
3539
- {
3540
- command: "workflow file list",
3541
- tool: "workflow_files_list",
3542
- title: "List workflow files",
3543
- description: "List the workflow's editable head as a directory of files: the graph rendered as structural files (settings.yaml, per-node instructions.md, scripts) alongside the workflow's own files. Those files are referenced by fileId unless contents=all is set. Pass paths to read named files only, or contents=none for a manifest with no bodies. The returned rev is what you pass as baseRev to write.",
3544
- method: "GET",
3545
- path: "/agents/v2/workflows/{workflowId}/head/files",
3546
- args: [
3547
- {
3548
- name: "workflowId",
3549
- flag: "workflow-id",
3550
- type: "string",
3551
- required: true
3552
- }
3553
- ],
3554
- query: [
3555
- {
3556
- name: "contents",
3557
- flag: "contents",
3558
- type: "string",
3559
- required: false,
3560
- description: "Which contents come inline: none (a pure manifest), structural (the default), or all (structural plus file bytes within the response budget).",
3561
- enum: ["none", "structural", "all"]
3562
- },
3563
- {
3564
- name: "paths",
3565
- flag: "paths",
3566
- type: "string[]",
3567
- required: false,
3568
- description: "Return only the files at these exact tree paths. A path that names nothing yields no entry. The inline budget applies to the filtered set, so a narrow read can inline files a whole-tree read would have to skip."
3569
- },
3570
- {
3571
- name: "variants",
3572
- flag: "variants",
3573
- type: "string",
3574
- required: false,
3575
- description: `Narrow which variants/<key>/ files the tree carries: "none" strips every variant, a comma-separated list keeps only those variant keys. Files outside variants/ are always kept, and the response's variantKeys still names every variant. Ignored unless the workflow has variant mode enabled; absent keeps every variant.`
3576
- },
3577
- {
3578
- name: "maxFileBytes",
3579
- flag: "max-file-bytes",
3580
- type: "integer",
3581
- required: false,
3582
- description: "Per-file ceiling, in bytes, for inlined file contents. Clamped to the server maximum. Files above the ceiling stay references."
3583
- },
3584
- {
3585
- name: "maxTotalBytes",
3586
- flag: "max-total-bytes",
3587
- type: "integer",
3588
- required: false,
3589
- description: "Ceiling, in bytes, on the total inlined file contents in one response. Clamped to the server maximum. Files are admitted in path order until the ceiling is reached; the rest stay references."
3590
- }
3591
- ],
3592
- binary: false,
3593
- readOnly: true,
3594
- destructive: false
3595
- },
3596
- {
3597
- command: "workflow file patch",
3598
- tool: "workflow_files_patch",
3599
- title: "Write workflow files",
3600
- description: "Write and delete files on the workflow's editable head in one patch. Structural files re-derive the graph; the workflow's own files go to its file store, you just write paths. Pass the rev from `workflow_files_list` as baseRev; a stale value is rejected with 409, so re-read and retry. Editing a published or already-executed version forks a new one instead of rewriting it. Each write carries `contentBase64`: base64-encode the file content, plain text is rejected with 400.",
3601
- method: "PATCH",
3602
- path: "/agents/v2/workflows/{workflowId}/head/files",
3603
- args: [
3604
- {
3605
- name: "workflowId",
3606
- flag: "workflow-id",
3607
- type: "string",
3608
- required: true
3609
- }
3610
- ],
3611
- query: [],
3612
- binary: false,
3613
- readOnly: false,
3614
- destructive: true,
3615
- body: {
3616
- required: true,
3617
- contentType: "application/json",
3618
- fields: [
3619
- {
3620
- name: "baseRev",
3621
- flag: "base-rev",
3622
- type: "integer",
3623
- required: true,
3624
- description: "The revision this edit is based on. Agent-file-only patches overlay the current head even when this is stale. A structural-file patch is rejected with 409 when it does not match the stored head revision."
3625
- },
3626
- {
3627
- name: "writes",
3628
- flag: "writes",
3629
- type: "json",
3630
- required: true,
3631
- description: "Files to upsert."
3632
- },
3633
- {
3634
- name: "deletes",
3635
- flag: "deletes",
3636
- type: "string[]",
3637
- required: true
3638
- }
3639
- ],
3640
- files: [],
3641
- credentialOrganization: false
3642
- }
3547
+ },
3548
+ capability: "run_execution"
3643
3549
  },
3644
3550
  {
3645
3551
  command: "workflow get",
@@ -3687,7 +3593,8 @@ var COMMANDS = [
3687
3593
  query: [],
3688
3594
  binary: false,
3689
3595
  readOnly: false,
3690
- destructive: false
3596
+ destructive: false,
3597
+ capability: "publish"
3691
3598
  },
3692
3599
  {
3693
3600
  command: "workflow head revert",
@@ -3813,6 +3720,113 @@ var COMMANDS = [
3813
3720
  readOnly: true,
3814
3721
  destructive: false
3815
3722
  },
3723
+ {
3724
+ command: "workflow pull",
3725
+ tool: "workflow_files_list",
3726
+ title: "List workflow files",
3727
+ description: "List the workflow's editable head as a directory of files: the graph rendered as structural files (settings.yaml, per-node instructions.md, scripts) alongside the workflow's own files. Those files are referenced by fileId unless contents=all is set. Pass paths to read named files only, or contents=none for a manifest with no bodies. The returned rev is what you pass as baseRev to write.",
3728
+ method: "GET",
3729
+ path: "/agents/v2/workflows/{workflowId}/head/files",
3730
+ args: [
3731
+ {
3732
+ name: "workflowId",
3733
+ flag: "workflow-id",
3734
+ type: "string",
3735
+ required: true
3736
+ }
3737
+ ],
3738
+ query: [
3739
+ {
3740
+ name: "contents",
3741
+ flag: "contents",
3742
+ type: "string",
3743
+ required: false,
3744
+ description: "Which contents come inline: none (a pure manifest), structural (the default), or all (structural plus file bytes within the response budget).",
3745
+ enum: ["none", "structural", "all"]
3746
+ },
3747
+ {
3748
+ name: "paths",
3749
+ flag: "paths",
3750
+ type: "string[]",
3751
+ required: false,
3752
+ description: "Return only the files at these exact tree paths. A path that names nothing yields no entry. The inline budget applies to the filtered set, so a narrow read can inline files a whole-tree read would have to skip."
3753
+ },
3754
+ {
3755
+ name: "variants",
3756
+ flag: "variants",
3757
+ type: "string",
3758
+ required: false,
3759
+ description: `Narrow which variants/<key>/ files the tree carries: "none" strips every variant, a comma-separated list keeps only those variant keys. Files outside variants/ are always kept, and the response's variantKeys still names every variant. Ignored unless the workflow has variant mode enabled; absent keeps every variant.`
3760
+ },
3761
+ {
3762
+ name: "maxFileBytes",
3763
+ flag: "max-file-bytes",
3764
+ type: "integer",
3765
+ required: false,
3766
+ description: "Per-file ceiling, in bytes, for inlined file contents. Clamped to the server maximum. Files above the ceiling stay references."
3767
+ },
3768
+ {
3769
+ name: "maxTotalBytes",
3770
+ flag: "max-total-bytes",
3771
+ type: "integer",
3772
+ required: false,
3773
+ description: "Ceiling, in bytes, on the total inlined file contents in one response. Clamped to the server maximum. Files are admitted in path order until the ceiling is reached; the rest stay references."
3774
+ }
3775
+ ],
3776
+ binary: false,
3777
+ readOnly: true,
3778
+ destructive: false,
3779
+ files: "pull"
3780
+ },
3781
+ {
3782
+ command: "workflow push",
3783
+ tool: "workflow_files_patch",
3784
+ title: "Write workflow files",
3785
+ description: "Write and delete files on the workflow's editable head in one patch. Structural files re-derive the graph; the workflow's own files go to its file store, you just write paths. Pass the rev from `workflow_files_list` as baseRev; a stale value is rejected with 409, so re-read and retry. Editing a published or already-executed version forks a new one instead of rewriting it. Each write carries `contentBase64`: base64-encode the file content, plain text is rejected with 400.",
3786
+ method: "PATCH",
3787
+ path: "/agents/v2/workflows/{workflowId}/head/files",
3788
+ args: [
3789
+ {
3790
+ name: "workflowId",
3791
+ flag: "workflow-id",
3792
+ type: "string",
3793
+ required: true
3794
+ }
3795
+ ],
3796
+ query: [],
3797
+ binary: false,
3798
+ readOnly: false,
3799
+ destructive: true,
3800
+ body: {
3801
+ required: true,
3802
+ contentType: "application/json",
3803
+ fields: [
3804
+ {
3805
+ name: "baseRev",
3806
+ flag: "base-rev",
3807
+ type: "integer",
3808
+ required: true,
3809
+ description: "The revision this edit is based on. Agent-file-only patches overlay the current head even when this is stale. A structural-file patch is rejected with 409 when it does not match the stored head revision."
3810
+ },
3811
+ {
3812
+ name: "writes",
3813
+ flag: "writes",
3814
+ type: "json",
3815
+ required: true,
3816
+ description: "Files to upsert."
3817
+ },
3818
+ {
3819
+ name: "deletes",
3820
+ flag: "deletes",
3821
+ type: "string[]",
3822
+ required: true
3823
+ }
3824
+ ],
3825
+ files: [],
3826
+ credentialOrganization: false
3827
+ },
3828
+ files: "push"
3829
+ },
3816
3830
  {
3817
3831
  command: "workflow rename",
3818
3832
  tool: "workflow_rename",
@@ -4215,70 +4229,8 @@ var COMMANDS = [
4215
4229
  ],
4216
4230
  files: [],
4217
4231
  credentialOrganization: false
4218
- }
4219
- },
4220
- {
4221
- command: "workflow version file list",
4222
- tool: "workflow_version_files_list",
4223
- title: "List workflow version files",
4224
- description: "List a version's files, like `workflow_files_list` does for the editable head. Versions are immutable, so this is read-only.",
4225
- method: "GET",
4226
- path: "/agents/v2/workflows/{workflowId}/versions/{versionId}/files",
4227
- args: [
4228
- {
4229
- name: "workflowId",
4230
- flag: "workflow-id",
4231
- type: "string",
4232
- required: true
4233
- },
4234
- {
4235
- name: "versionId",
4236
- flag: "version-id",
4237
- type: "string",
4238
- required: true
4239
- }
4240
- ],
4241
- query: [
4242
- {
4243
- name: "contents",
4244
- flag: "contents",
4245
- type: "string",
4246
- required: false,
4247
- description: "Which contents come inline: none (a pure manifest), structural (the default), or all (structural plus file bytes within the response budget).",
4248
- enum: ["none", "structural", "all"]
4249
- },
4250
- {
4251
- name: "paths",
4252
- flag: "paths",
4253
- type: "string[]",
4254
- required: false,
4255
- description: "Return only the files at these exact tree paths. A path that names nothing yields no entry. The inline budget applies to the filtered set, so a narrow read can inline files a whole-tree read would have to skip."
4256
- },
4257
- {
4258
- name: "variants",
4259
- flag: "variants",
4260
- type: "string",
4261
- required: false,
4262
- description: `Narrow which variants/<key>/ files the tree carries: "none" strips every variant, a comma-separated list keeps only those variant keys. Files outside variants/ are always kept, and the response's variantKeys still names every variant. Ignored unless the workflow has variant mode enabled; absent keeps every variant.`
4263
- },
4264
- {
4265
- name: "maxFileBytes",
4266
- flag: "max-file-bytes",
4267
- type: "integer",
4268
- required: false,
4269
- description: "Per-file ceiling, in bytes, for inlined file contents. Clamped to the server maximum. Files above the ceiling stay references."
4270
- },
4271
- {
4272
- name: "maxTotalBytes",
4273
- flag: "max-total-bytes",
4274
- type: "integer",
4275
- required: false,
4276
- description: "Ceiling, in bytes, on the total inlined file contents in one response. Clamped to the server maximum. Files are admitted in path order until the ceiling is reached; the rest stay references."
4277
- }
4278
- ],
4279
- binary: false,
4280
- readOnly: true,
4281
- destructive: false
4232
+ },
4233
+ capability: "run_execution"
4282
4234
  },
4283
4235
  {
4284
4236
  command: "workflow version file url",
@@ -4434,7 +4386,72 @@ var COMMANDS = [
4434
4386
  query: [],
4435
4387
  binary: false,
4436
4388
  readOnly: false,
4437
- destructive: false
4389
+ destructive: false,
4390
+ capability: "publish"
4391
+ },
4392
+ {
4393
+ command: "workflow version pull",
4394
+ tool: "workflow_version_files_list",
4395
+ title: "List workflow version files",
4396
+ description: "List a version's files, like `workflow_files_list` does for the editable head. Versions are immutable, so this is read-only.",
4397
+ method: "GET",
4398
+ path: "/agents/v2/workflows/{workflowId}/versions/{versionId}/files",
4399
+ args: [
4400
+ {
4401
+ name: "workflowId",
4402
+ flag: "workflow-id",
4403
+ type: "string",
4404
+ required: true
4405
+ },
4406
+ {
4407
+ name: "versionId",
4408
+ flag: "version-id",
4409
+ type: "string",
4410
+ required: true
4411
+ }
4412
+ ],
4413
+ query: [
4414
+ {
4415
+ name: "contents",
4416
+ flag: "contents",
4417
+ type: "string",
4418
+ required: false,
4419
+ description: "Which contents come inline: none (a pure manifest), structural (the default), or all (structural plus file bytes within the response budget).",
4420
+ enum: ["none", "structural", "all"]
4421
+ },
4422
+ {
4423
+ name: "paths",
4424
+ flag: "paths",
4425
+ type: "string[]",
4426
+ required: false,
4427
+ description: "Return only the files at these exact tree paths. A path that names nothing yields no entry. The inline budget applies to the filtered set, so a narrow read can inline files a whole-tree read would have to skip."
4428
+ },
4429
+ {
4430
+ name: "variants",
4431
+ flag: "variants",
4432
+ type: "string",
4433
+ required: false,
4434
+ description: `Narrow which variants/<key>/ files the tree carries: "none" strips every variant, a comma-separated list keeps only those variant keys. Files outside variants/ are always kept, and the response's variantKeys still names every variant. Ignored unless the workflow has variant mode enabled; absent keeps every variant.`
4435
+ },
4436
+ {
4437
+ name: "maxFileBytes",
4438
+ flag: "max-file-bytes",
4439
+ type: "integer",
4440
+ required: false,
4441
+ description: "Per-file ceiling, in bytes, for inlined file contents. Clamped to the server maximum. Files above the ceiling stay references."
4442
+ },
4443
+ {
4444
+ name: "maxTotalBytes",
4445
+ flag: "max-total-bytes",
4446
+ type: "integer",
4447
+ required: false,
4448
+ description: "Ceiling, in bytes, on the total inlined file contents in one response. Clamped to the server maximum. Files are admitted in path order until the ceiling is reached; the rest stay references."
4449
+ }
4450
+ ],
4451
+ binary: false,
4452
+ readOnly: true,
4453
+ destructive: false,
4454
+ files: "pull"
4438
4455
  },
4439
4456
  {
4440
4457
  command: "workflow version validate",
@@ -4510,11 +4527,6 @@ var COMMANDS = [
4510
4527
  function option(name, type, description, extra = {}) {
4511
4528
  return { name, flag: name, type, required: false, description, ...extra };
4512
4529
  }
4513
- var DIR = option(
4514
- "dir",
4515
- "string",
4516
- "Write here instead of `<workflow-name>/...` under the current directory."
4517
- );
4518
4530
  var local = {
4519
4531
  method: "GET",
4520
4532
  path: "",
@@ -4523,46 +4535,6 @@ var local = {
4523
4535
  local: true
4524
4536
  };
4525
4537
  var SYNC_COMMANDS = [
4526
- {
4527
- ...local,
4528
- command: "workflow pull",
4529
- tool: "workflow_pull",
4530
- title: "Pull a workflow to disk",
4531
- description: "Write a workflow's editable head to `<workflow-name>/head/` as files: settings, per-node instructions and scripts, and the workflow's own files. Pass --version-id for a pinned version, written read-only to `<workflow-name>/.versions/`. Edit the head files, then run `asteroid workflow push` from that folder.",
4532
- readOnly: true,
4533
- args: [
4534
- {
4535
- name: "workflowId",
4536
- flag: "workflow-id",
4537
- type: "string",
4538
- required: true
4539
- }
4540
- ],
4541
- query: [
4542
- option(
4543
- "version-id",
4544
- "string",
4545
- "A workflow version ID. Omit for the editable head."
4546
- ),
4547
- DIR
4548
- ]
4549
- },
4550
- {
4551
- ...local,
4552
- command: "workflow push",
4553
- tool: "workflow_push",
4554
- title: "Push local edits to a workflow head",
4555
- description: "Send the edits in a pulled head folder to the workflow's editable head: changed and new files are written, removed files are deleted. Fails if the head changed since the pull; pull again and reapply. Push does not publish.",
4556
- readOnly: false,
4557
- args: [],
4558
- query: [
4559
- option(
4560
- "dir",
4561
- "string",
4562
- "The pulled head folder. Defaults to the current directory."
4563
- )
4564
- ]
4565
- },
4566
4538
  {
4567
4539
  ...local,
4568
4540
  command: "execution pull",
@@ -4952,6 +4924,16 @@ function leafOptions(leaf, command) {
4952
4924
  for (const file of command.body?.files ?? []) {
4953
4925
  leaf.option(`--${file} <path>`, "File to upload. Repeatable.", collect);
4954
4926
  }
4927
+ if (command.files === "pull")
4928
+ leaf.option(
4929
+ "--out <dir>",
4930
+ "Write here instead of ./<workflow-name>/head (a version: ./<workflow-name>/.versions/...). --json prints the file listing instead."
4931
+ );
4932
+ if (command.files === "push")
4933
+ leaf.option(
4934
+ "--from <dir>",
4935
+ "The pulled head folder to push. Defaults to the current folder."
4936
+ );
4955
4937
  }
4956
4938
  function toParsed(leaf, positionals, dotted) {
4957
4939
  const globals = leaf.optsWithGlobals();
@@ -5453,7 +5435,7 @@ var ApiError = class extends Error {
5453
5435
  status;
5454
5436
  body;
5455
5437
  };
5456
- var VERSION = "1.9.11";
5438
+ var VERSION = "1.9.12";
5457
5439
  function problem(status, body, fallback) {
5458
5440
  if (body && typeof body === "object") {
5459
5441
  const record2 = body;
@@ -6308,16 +6290,10 @@ function nodeFiles(cwd) {
6308
6290
 
6309
6291
  // src/sync/workflow-pull.ts
6310
6292
  var CONCURRENCY = 16;
6311
- function treeRequest(options) {
6312
- const base = `/agents/v2/workflows/${options.workflowId}`;
6313
- const path = options.versionId ? `${base}/versions/${options.versionId}/files` : `${base}/head/files`;
6314
- return get(path, { contents: "all" });
6315
- }
6316
- function pullDir(options, tree) {
6317
- if (options.dir) return options.dir;
6318
- const root = workflowRoot(options.root, tree.workflowName);
6319
- if (!options.versionId) return join3(root, "head");
6320
- return join3(root, ".versions", workflowDirName(tree.versionId, tree.version));
6293
+ function pullDir(root, tree, head) {
6294
+ const base = workflowRoot(root, tree.workflowName);
6295
+ if (head) return join3(base, "head");
6296
+ return join3(base, ".versions", workflowDirName(tree.versionId, tree.version));
6321
6297
  }
6322
6298
  async function agentFileBytes(sync, workflowId, tree, entry) {
6323
6299
  const path = `/agents/v2/workflows/${workflowId}/versions/${tree.versionId}/files/${entry.fileId}/signed-url`;
@@ -6367,8 +6343,14 @@ async function writeManifest(sync, dir, manifest) {
6367
6343
  await sync.files.write(join3(dir, MANIFEST), Buffer.from(text2, "utf8"));
6368
6344
  }
6369
6345
  async function pullWorkflow(sync, options) {
6370
- const tree = await sync.remote.json(treeRequest(options));
6371
- const dir = pullDir(options, tree);
6346
+ const request = {
6347
+ ...options.request,
6348
+ query: new URLSearchParams(options.request.query)
6349
+ };
6350
+ request.query.set("contents", "all");
6351
+ const tree = await sync.remote.json(request);
6352
+ const head = request.path.endsWith("/head/files");
6353
+ const dir = options.dir ?? pullDir(options.root ?? "", tree, head);
6372
6354
  const { hashes, skipped, shared } = await writeEntries(
6373
6355
  sync,
6374
6356
  options,
@@ -6380,7 +6362,7 @@ async function pullWorkflow(sync, options) {
6380
6362
  await writeManifest(sync, dir, {
6381
6363
  workflowId: options.workflowId,
6382
6364
  versionId: tree.versionId,
6383
- head: !options.versionId,
6365
+ head,
6384
6366
  rev: tree.rev,
6385
6367
  files: hashes
6386
6368
  });
@@ -6392,6 +6374,7 @@ async function pullWorkflow(sync, options) {
6392
6374
  version: tree.version,
6393
6375
  rev: tree.rev,
6394
6376
  dir,
6377
+ head,
6395
6378
  written: Object.keys(hashes).length,
6396
6379
  shared,
6397
6380
  skipped
@@ -6406,7 +6389,8 @@ function formatWorkflowPull(result) {
6406
6389
  `Written to: ${result.dir}/`,
6407
6390
  files,
6408
6391
  result.skipped.length > 0 ? `Skipped:
6409
- ${result.skipped.map((s) => ` - ${s}`).join("\n")}` : null
6392
+ ${result.skipped.map((s) => ` - ${s}`).join("\n")}` : null,
6393
+ result.head ? `Edit the files, then run \`asteroid workflow push\` from ${result.dir}/.` : "This is a pinned version. It is read-only."
6410
6394
  ].filter(Boolean).join("\n");
6411
6395
  }
6412
6396
 
@@ -6488,8 +6472,13 @@ async function refresh2(sync, dir, manifest, pushed) {
6488
6472
  await writeManifest(sync, dir, next);
6489
6473
  return next;
6490
6474
  }
6491
- async function pushWorkflow(sync, dir) {
6475
+ async function pushWorkflow(sync, dir, workflowId) {
6492
6476
  const manifest = await readManifest(sync, dir);
6477
+ if (workflowId !== void 0 && manifest.workflowId !== workflowId) {
6478
+ throw new UsageError(
6479
+ `${dir} holds workflow ${manifest.workflowId}, not ${workflowId}.`
6480
+ );
6481
+ }
6493
6482
  const { writes, deletes } = await localChanges(sync, dir, manifest);
6494
6483
  const result = {
6495
6484
  workflowId: manifest.workflowId,
@@ -6550,34 +6539,56 @@ function executionOptions(parsed) {
6550
6539
  dir: dir ? () => dir : void 0
6551
6540
  };
6552
6541
  }
6542
+ function withoutFlag(parsed, name) {
6543
+ const flags = new Map(parsed.flags);
6544
+ flags.delete(name);
6545
+ return { ...parsed, flags };
6546
+ }
6547
+ function runsLocally(command, parsed) {
6548
+ if (command.local) return true;
6549
+ if (command.files === "pull") return !parsed.json;
6550
+ if (command.files === "push") return parsed.body === void 0;
6551
+ return false;
6552
+ }
6553
+ var PARTIAL = ["paths", "variants"];
6554
+ function rejectPartial(parsed) {
6555
+ const used = PARTIAL.filter((name) => parsed.flags.has(name));
6556
+ if (used.length === 0) return;
6557
+ throw new UsageError(
6558
+ `pull writes the whole tree, so it cannot take ${used.map((name) => `--${name}`).join(" or ")}. Add --json to list those files instead.`
6559
+ );
6560
+ }
6561
+ async function pull(command, parsed, sync, deps) {
6562
+ rejectPartial(parsed);
6563
+ const result = await pullWorkflow(sync, {
6564
+ workflowId: parsed.positionals[0],
6565
+ request: await buildRequest(command, withoutFlag(parsed, "out"), {
6566
+ io: deps.io
6567
+ }),
6568
+ dir: flag(parsed, "out"),
6569
+ root: deps.root ?? "",
6570
+ ...deps.workflowPull
6571
+ });
6572
+ return { result, text: formatWorkflowPull(result) };
6573
+ }
6553
6574
  async function execute(command, parsed, sync, deps) {
6554
- const root = deps.root ?? "";
6555
- switch (command.command) {
6556
- case "workflow pull": {
6557
- const result = await pullWorkflow(sync, {
6558
- workflowId: parsed.positionals[0],
6559
- versionId: flag(parsed, "version-id"),
6560
- dir: flag(parsed, "dir"),
6561
- root,
6562
- ...deps.workflowPull
6563
- });
6564
- return { result, text: formatWorkflowPull(result) };
6565
- }
6566
- case "workflow push": {
6567
- const result = await pushWorkflow(sync, flag(parsed, "dir") ?? ".");
6568
- return { result, text: formatWorkflowPush(result) };
6569
- }
6570
- case "execution pull": {
6571
- const result = await pullExecution(sync, {
6572
- ...executionOptions(parsed),
6573
- root,
6574
- ...deps.executionPull
6575
- });
6576
- return { result, text: formatExecutionPull(result) };
6577
- }
6578
- default:
6579
- throw new UsageError(`unknown command ${command.command}`);
6575
+ if (command.files === "pull") return pull(command, parsed, sync, deps);
6576
+ if (command.files === "push") {
6577
+ const result2 = await pushWorkflow(
6578
+ sync,
6579
+ flag(parsed, "from") ?? ".",
6580
+ parsed.positionals[0] || void 0
6581
+ );
6582
+ return { result: result2, text: formatWorkflowPush(result2) };
6580
6583
  }
6584
+ if (command.command !== "execution pull")
6585
+ throw new UsageError(`unknown command ${command.command}`);
6586
+ const result = await pullExecution(sync, {
6587
+ ...executionOptions(parsed),
6588
+ root: deps.root ?? "",
6589
+ ...deps.executionPull
6590
+ });
6591
+ return { result, text: formatExecutionPull(result) };
6581
6592
  }
6582
6593
  async function runSync(command, parsed, deps) {
6583
6594
  const sync = {
@@ -6710,7 +6721,9 @@ async function run(argv2, deps) {
6710
6721
  commands: ALL_COMMANDS,
6711
6722
  builtins: BUILTINS,
6712
6723
  version: VERSION,
6713
- description: DESCRIPTION
6724
+ description: DESCRIPTION,
6725
+ defaultArg: (command, arg) => command.files === "push" && arg.name === "workflowId" ? "" : void 0,
6726
+ defaultArgNote: "<workflow-id> defaults to the workflow the pushed folder was pulled from."
6714
6727
  });
6715
6728
  if (invocation.kind === "exit") {
6716
6729
  if (invocation.stdout) deps.stdout(invocation.stdout);
@@ -6720,7 +6733,7 @@ async function run(argv2, deps) {
6720
6733
  if (invocation.kind === "builtin") {
6721
6734
  return await runBuiltin(invocation.name, invocation.parsed, deps);
6722
6735
  }
6723
- if (invocation.command.local) {
6736
+ if (runsLocally(invocation.command, invocation.parsed)) {
6724
6737
  const auth = await authFor(invocation.parsed, deps);
6725
6738
  announce(invocation.command, auth, deps);
6726
6739
  return await runSync(invocation.command, invocation.parsed, {