deepline 0.3.59 → 0.3.60

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/cli/index.js CHANGED
@@ -181,7 +181,7 @@ function configureProxyFromEnv() {
181
181
  configureProxyFromEnv();
182
182
 
183
183
  // src/cli/index.ts
184
- var import_promises10 = require("fs/promises");
184
+ var import_promises11 = require("fs/promises");
185
185
  var import_node_path28 = require("path");
186
186
  var import_node_os18 = require("os");
187
187
  var import_commander4 = require("commander");
@@ -1025,6 +1025,51 @@ function resolveProjectPinTarget(startDir = process.cwd()) {
1025
1025
  function getActiveProjectAuthSource(startDir = process.cwd()) {
1026
1026
  return loadProjectEnvCandidates(startDir)[0] ?? null;
1027
1027
  }
1028
+ function findNearestProjectMarkerDir(startDir) {
1029
+ let current = (0, import_node_path.resolve)(startDir);
1030
+ while (true) {
1031
+ if (COWORK_PROJECT_MARKERS.some((marker) => (0, import_node_fs.existsSync)((0, import_node_path.join)(current, marker)))) {
1032
+ return current;
1033
+ }
1034
+ const parent = (0, import_node_path.dirname)(current);
1035
+ if (parent === current) return null;
1036
+ current = parent;
1037
+ }
1038
+ }
1039
+ function resolveCliAuthProvenance(config, startDir = process.cwd()) {
1040
+ const envApiKey = process.env[API_KEY_ENV]?.trim();
1041
+ const folderAuth = getResolvedProjectAuthSource(
1042
+ config.baseUrl,
1043
+ config.apiKey,
1044
+ startDir
1045
+ );
1046
+ const pinTarget = resolveProjectPinTarget(startDir);
1047
+ const markerDir = findNearestProjectMarkerDir(startDir);
1048
+ const project = !pinTarget.ok ? {
1049
+ state: "ambiguous_cowork_project",
1050
+ candidates: pinTarget.candidates
1051
+ } : folderAuth ? {
1052
+ state: "project",
1053
+ dir: (0, import_node_path.dirname)(folderAuth.filePath),
1054
+ pinPath: folderAuth.filePath,
1055
+ source: "folder"
1056
+ } : pinTarget.source === "cowork" ? {
1057
+ state: "project",
1058
+ dir: pinTarget.dir,
1059
+ pinPath: (0, import_node_path.join)(pinTarget.dir, PROJECT_DEEPLINE_ENV_FILE),
1060
+ source: "cowork"
1061
+ } : markerDir ? {
1062
+ state: "project",
1063
+ dir: markerDir,
1064
+ pinPath: (0, import_node_path.join)(markerDir, PROJECT_DEEPLINE_ENV_FILE),
1065
+ source: "marker"
1066
+ } : { state: "not_project" };
1067
+ return {
1068
+ scope: envApiKey ? "env" : folderAuth ? "folder" : "global",
1069
+ project,
1070
+ folderAuthPath: folderAuth?.filePath ?? null
1071
+ };
1072
+ }
1028
1073
 
1029
1074
  // ../plays/artifact-contract-version.ts
1030
1075
  var CURRENT_PLAY_ARTIFACT_CONTRACT_VERSION = 2;
@@ -1075,7 +1120,7 @@ var SDK_RELEASE = {
1075
1120
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1076
1121
  // getters keep their established compatibility behavior.
1077
1122
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1078
- version: "0.3.59",
1123
+ version: "0.3.60",
1079
1124
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
1080
1125
  packageCapabilities: {
1081
1126
  updatePreferences: 1
@@ -4879,6 +4924,7 @@ var DeeplineClient = class {
4879
4924
  ...this.summarizePlayListItem(play, options),
4880
4925
  currentPublishedVersion: play.currentPublishedVersion ?? play.liveRevision?.version ?? null,
4881
4926
  latestRunId: play.latestRunId ?? detail.latestRuns[0]?.workflowId ?? null,
4927
+ ...play.triggerMetadata ? { triggerMetadata: play.triggerMetadata } : {},
4882
4928
  ...play.runtimeLimit ? { runtimeLimit: play.runtimeLimit } : {},
4883
4929
  ...play.activeScheduledPlays ? { activeScheduledPlays: play.activeScheduledPlays } : {}
4884
4930
  };
@@ -13620,6 +13666,39 @@ var PLAY_SQL_LISTENER_TOOL_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*\.[a-zA-Z][a-zA-Z0-
13620
13666
  var PLAY_SQL_LISTENER_WHERE_OPERATOR_SET = new Set(
13621
13667
  PLAY_SQL_LISTENER_WHERE_OPERATORS
13622
13668
  );
13669
+ var PLAY_AUTHORING_BINDING_FIELDS = {
13670
+ root: [
13671
+ "billing",
13672
+ "compatibility",
13673
+ "cron",
13674
+ "inline",
13675
+ "runtime",
13676
+ "secrets",
13677
+ "sqlListeners",
13678
+ "webhook"
13679
+ ],
13680
+ cron: ["schedule", "timezone", "input"],
13681
+ webhook: ["auth", "hmac"],
13682
+ sqlListener: [
13683
+ "id",
13684
+ "tool",
13685
+ "stream",
13686
+ "where",
13687
+ "table",
13688
+ "monitor",
13689
+ "output",
13690
+ "operations"
13691
+ ]
13692
+ };
13693
+ var PLAY_AUTHORING_DEFINE_PLAY_OPTION_FIELDS = [
13694
+ "id",
13695
+ "name",
13696
+ "description",
13697
+ "input",
13698
+ "run",
13699
+ "bindings",
13700
+ ...PLAY_AUTHORING_BINDING_FIELDS.root
13701
+ ];
13623
13702
  var PLAY_AUTHORING_DOCUMENTATION = {
13624
13703
  fetchBatching: {
13625
13704
  warning: "A static ctx.fetch key inside a loop is a warning because every iteration must still have distinct method, URL, body, or safe headers. One durable receipt must never stand in for every request.",
@@ -13881,6 +13960,22 @@ var PLAY_AUTHORING_FIELD_REGISTRY = {
13881
13960
  description: "IANA timezone. Omitted means UTC.",
13882
13961
  errorMessage: "bindings.cron.timezone must be a valid non-empty IANA timezone string."
13883
13962
  },
13963
+ "bindings.cron.input": {
13964
+ schema: import_typebox.Type.Object({}, { additionalProperties: true }),
13965
+ fixtures: {
13966
+ valid: { apply: true },
13967
+ invalid: ["apply"],
13968
+ absent: void 0,
13969
+ unresolved: ["cronInput"],
13970
+ edition1: void 0
13971
+ },
13972
+ referenceType: "Record<string, unknown>",
13973
+ required: false,
13974
+ resolution: "static-required",
13975
+ issueCode: "play_authoring_binding_invalid",
13976
+ description: "Static JSON object passed to every run created by this cron binding.",
13977
+ errorMessage: "bindings.cron.input must be a static JSON object (no variables, spreads, or functions)."
13978
+ },
13884
13979
  "bindings.sqlListeners": {
13885
13980
  schema: import_typebox.Type.Array(import_typebox.Type.Object({}, { additionalProperties: true })),
13886
13981
  fixtures: {
@@ -14884,14 +14979,15 @@ var PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
14884
14979
  " readonly timeoutMs?: PlayRuntimeTimeoutMs;",
14885
14980
  " readonly receiptWaitMs?: PlayReceiptWaitMs;",
14886
14981
  "};",
14887
- "export type PlayBindings = {",
14982
+ "export type PlayCronInput<TInput> = TInput extends readonly unknown[] ? never : TInput extends object ? TInput : never;",
14983
+ "export type PlayBindings<TInput = Record<string, unknown>> = {",
14888
14984
  ` description?: ${cloudReferenceType("description")};`,
14889
14985
  ` compatibility?: { toolErrorSchemaVersion?: ${cloudReferenceType("compatibility.toolErrorSchemaVersion")}; toolResponseReceiptRevision?: ${cloudReferenceType("compatibility.toolResponseReceiptRevision")} };`,
14890
14986
  ` inline?: ${cloudReferenceType("inline")};`,
14891
14987
  ` billing?: { maxCreditsPerRun?: ${cloudReferenceType("billing.maxCreditsPerRun")} };`,
14892
14988
  ` runtime?: { timeout?: ${cloudReferenceType("runtime.timeout")}; size?: ${cloudReferenceType("runtime.size")} };`,
14893
14989
  ` webhook?: { hmac?: { algorithm?: ${cloudReferenceType("bindings.webhook.hmac.algorithm")}; header?: ${cloudReferenceType("bindings.webhook.hmac.header")}; secretEnv: ${cloudReferenceType("bindings.webhook.hmac.secretEnv")} }; auth?: { type: ${cloudReferenceType("bindings.webhook.auth.type")}; headerFamily: ${cloudReferenceType("bindings.webhook.auth.headerFamily")}; signingSecrets: readonly ${cloudReferenceType("bindings.webhook.auth.signingSecrets[]")}[]; toleranceSeconds?: ${cloudReferenceType("bindings.webhook.auth.toleranceSeconds")} } };`,
14894
- ` cron?: { schedule: ${cloudReferenceType("bindings.cron.schedule")}; timezone?: ${cloudReferenceType("bindings.cron.timezone")} };`,
14990
+ ` cron?: { schedule: ${cloudReferenceType("bindings.cron.schedule")}; timezone?: ${cloudReferenceType("bindings.cron.timezone")}; input?: PlayCronInput<TInput> };`,
14895
14991
  " sqlListeners?: readonly SqlListenerDeclaration[];",
14896
14992
  ` secrets?: readonly ${cloudReferenceType("bindings.secrets[]")}[];`,
14897
14993
  "};",
@@ -14957,8 +15053,10 @@ var PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
14957
15053
  " log(message: string): void;",
14958
15054
  ` sleep(ms: ${cloudReferenceType("ctx.sleep.ms")}): Promise<void>;`,
14959
15055
  "}",
14960
- "export type DefinePlayConfig<TInput, TOutput extends PlayReturnObject> = { id: string; description?: string; input: PlayInputContract<TInput>; run: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>; bindings?: PlayBindings; billing?: PlayBindings['billing']; runtime?: PlayBindings['runtime']; compatibility?: PlayBindings['compatibility'] };",
14961
- "export type DefinedPlay<TInput, TOutput extends PlayReturnObject> = ((ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>) & { readonly name: string; readonly __inputType?: TInput; readonly __outputType?: TOutput; readonly runtime?: PlayBindings['runtime']; readonly compatibility?: PlayBindings['compatibility'] };"
15056
+ "export type DefinePlayConfig<TInput, TOutput extends PlayReturnObject> = { id: string; description?: string; input: PlayInputContract<TInput>; run: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>; bindings?: PlayBindings<TInput>; billing?: PlayBindings<TInput>['billing']; runtime?: PlayBindings<TInput>['runtime']; compatibility?: PlayBindings<TInput>['compatibility'] };",
15057
+ "export type DefinedPlay<TInput, TOutput extends PlayReturnObject> = ((ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>) & { readonly name: string; readonly __inputType?: TInput; readonly __outputType?: TOutput; readonly bindings?: PlayBindings<TInput>; readonly runtime?: PlayBindings<TInput>['runtime']; readonly compatibility?: PlayBindings<TInput>['compatibility'] };",
15058
+ "export type PlayHandlerInput<THandler> = THandler extends (context: DeeplinePlayRuntimeContext, input: infer TInput) => Promise<PlayReturnObject> ? TInput : never;",
15059
+ "export type PlayHandlerOutput<THandler> = THandler extends (context: DeeplinePlayRuntimeContext, input: unknown) => Promise<infer TOutput extends PlayReturnObject> ? TOutput : never;"
14962
15060
  ];
14963
15061
 
14964
15062
  // ../plays/ts-ast.ts
@@ -20770,6 +20868,11 @@ function writeStartedPlayRun(input2) {
20770
20868
  name: input2.playName,
20771
20869
  status: input2.status ?? "started",
20772
20870
  dashboardUrl: input2.dashboardUrl,
20871
+ execution: {
20872
+ revision: input2.revisionLabel ?? "resolved by Deepline",
20873
+ input_field_count: input2.inputFieldCount ?? 0,
20874
+ cache_policy: input2.forceToolRefresh ? "completed provider receipts may be refreshed" : input2.force ? "fresh run graph; completed provider receipts may still be reused" : "completed provider receipts may be reused"
20875
+ },
20773
20876
  next: {
20774
20877
  inspect: `deepline runs get ${input2.runId} --json`,
20775
20878
  full: `deepline runs get ${input2.runId} --full --json`,
@@ -20781,6 +20884,9 @@ function writeStartedPlayRun(input2) {
20781
20884
  const lines = [
20782
20885
  `Started ${input2.playName}`,
20783
20886
  ` run id: ${input2.runId}`,
20887
+ ` revision: ${input2.revisionLabel ?? "resolved by Deepline"}`,
20888
+ ` input: ${input2.inputFieldCount ?? 0} top-level field(s) supplied`,
20889
+ ` cache: ${input2.forceToolRefresh ? "completed provider receipts may be refreshed" : input2.force ? "fresh run graph; completed provider receipts may still be reused" : "completed provider receipts may be reused"}`,
20784
20890
  ` inspect: deepline runs get ${input2.runId} --json`,
20785
20891
  ` full debug: deepline runs get ${input2.runId} --full --json`,
20786
20892
  ` logs: deepline runs logs ${input2.runId} --json`,
@@ -21318,7 +21424,7 @@ function printPlayTriggers(triggers) {
21318
21424
  if (!triggers) return;
21319
21425
  const hasAny = (triggers.sqlListeners?.length ?? 0) > 0 || Boolean(triggers.cron) || triggers.webhook === true;
21320
21426
  if (!hasAny) return;
21321
- console.log(" triggers:");
21427
+ console.log(" declared triggers (source only):");
21322
21428
  for (const listener of triggers.sqlListeners ?? []) {
21323
21429
  const target = listener.tool && listener.stream ? `${listener.tool}/${listener.stream}` : listener.tool ?? listener.stream ?? listener.id;
21324
21430
  const operations = listener.operations.length ? listener.operations.join(", ") : "INSERT, UPDATE";
@@ -21333,10 +21439,77 @@ function printPlayTriggers(triggers) {
21333
21439
  if (triggers.cron) {
21334
21440
  const timezone = triggers.cron.timezone ? ` (${triggers.cron.timezone})` : "";
21335
21441
  console.log(` cron \u2192 ${triggers.cron.schedule}${timezone}`);
21442
+ if (triggers.cron.input && Object.keys(triggers.cron.input).length > 0) {
21443
+ console.log(` input \u2192 ${JSON.stringify(triggers.cron.input)}`);
21444
+ }
21336
21445
  }
21337
21446
  if (triggers.webhook === true) {
21338
21447
  console.log(" webhook \u2192 enabled");
21339
21448
  }
21449
+ if (triggers.cron) {
21450
+ console.log(
21451
+ " This check validates the declaration only. Publish this revision before a cron can be armed."
21452
+ );
21453
+ }
21454
+ }
21455
+ function cronExecutionLabel(status) {
21456
+ if (!status) return "not configured";
21457
+ if (status === "active") return "armed";
21458
+ if (status === "blocked") return "blocked";
21459
+ return status;
21460
+ }
21461
+ function readLiveCronMetadata(play) {
21462
+ const record2 = readRecord(play);
21463
+ const metadata = readRecord(record2?.triggerMetadata);
21464
+ return {
21465
+ schedule: typeof metadata?.cronSchedule === "string" ? metadata.cronSchedule : null,
21466
+ timezone: typeof metadata?.cronTimezone === "string" ? metadata.cronTimezone : null,
21467
+ nextScheduledAt: typeof metadata?.nextScheduledAt === "number" ? metadata.nextScheduledAt : null
21468
+ };
21469
+ }
21470
+ function liveTriggerStatusLines(status, play) {
21471
+ const cron = readLiveCronMetadata(play);
21472
+ if (!status?.cron && !cron.schedule && !status?.webhook) return [];
21473
+ const lines = [];
21474
+ if (status?.cron || cron.schedule) {
21475
+ const timezone = cron.timezone ? ` (${cron.timezone})` : "";
21476
+ lines.push(
21477
+ ` Scheduled execution: ${cronExecutionLabel(status?.cron ?? null)}${cron.schedule ? ` \u2014 ${cron.schedule}${timezone}` : ""}`
21478
+ );
21479
+ if (cron.nextScheduledAt !== null && status?.cron === "active") {
21480
+ lines.push(
21481
+ ` Next scheduled run: ${formatTimestamp(cron.nextScheduledAt)}`
21482
+ );
21483
+ }
21484
+ if (status?.blockedReason) {
21485
+ lines.push(` Schedule issue: ${status.blockedReason}`);
21486
+ }
21487
+ }
21488
+ if (status?.webhook) {
21489
+ lines.push(` Webhook: ${status.webhook}`);
21490
+ }
21491
+ return lines;
21492
+ }
21493
+ function triggerStatusFromMetadata(value) {
21494
+ const metadata = readRecord(value);
21495
+ return {
21496
+ cron: typeof metadata?.cronStatus === "string" ? metadata.cronStatus : null,
21497
+ webhook: typeof metadata?.webhookStatus === "string" ? metadata.webhookStatus : null,
21498
+ blockedReason: typeof metadata?.blockedReason === "string" ? metadata.blockedReason : null
21499
+ };
21500
+ }
21501
+ function printPublishReceipt(input2) {
21502
+ console.log(`\u2713 Published ${input2.name} as v${input2.liveVersion ?? "?"}`);
21503
+ if (input2.previousLiveVersion !== void 0 && input2.previousLiveVersion !== null) {
21504
+ console.log(` previous live: v${input2.previousLiveVersion}`);
21505
+ }
21506
+ for (const line of liveTriggerStatusLines(
21507
+ triggerStatusFromMetadata(input2.triggerMetadata),
21508
+ { triggerMetadata: input2.triggerMetadata }
21509
+ )) {
21510
+ console.log(line);
21511
+ }
21512
+ console.log(` revisions: deepline plays versions --name ${input2.name}`);
21340
21513
  }
21341
21514
  function printRecognizedSummary(recognized) {
21342
21515
  if (!recognized) return;
@@ -21912,7 +22085,11 @@ async function handleFileBackedRun(options, hooks) {
21912
22085
  dashboardUrl: resolvedDashboardUrl,
21913
22086
  package: options.fullJson ? void 0 : started.package,
21914
22087
  jsonOutput: options.jsonOutput,
21915
- progress
22088
+ progress,
22089
+ inputFieldCount: Object.keys(options.input ?? {}).length,
22090
+ revisionLabel: "local file revision",
22091
+ force: options.force,
22092
+ forceToolRefresh: options.forceToolRefresh
21916
22093
  });
21917
22094
  return 0;
21918
22095
  }
@@ -22095,7 +22272,11 @@ async function handleNamedRun(options, hooks) {
22095
22272
  dashboardUrl: resolvedDashboardUrl,
22096
22273
  package: options.fullJson ? void 0 : started.package,
22097
22274
  jsonOutput: options.jsonOutput,
22098
- progress
22275
+ progress,
22276
+ inputFieldCount: Object.keys(options.input ?? {}).length,
22277
+ revisionLabel: selectedRevisionId ? `pinned revision ${selectedRevisionId}` : "live revision",
22278
+ force: options.force,
22279
+ forceToolRefresh: options.forceToolRefresh
22099
22280
  });
22100
22281
  return 0;
22101
22282
  }
@@ -22761,7 +22942,17 @@ async function handlePlayGet(args) {
22761
22942
  );
22762
22943
  console.log(`Live version: ${detail.play.liveRevision?.version ?? "\u2014"}`);
22763
22944
  console.log(`Draft dirty: ${detail.play.isDraftDirty ? "yes" : "no"}`);
22764
- console.log(`Runs: ${detail.latestRuns.length}`);
22945
+ if (detail.play.isDraftDirty && detail.play.liveRevision?.version) {
22946
+ console.log(
22947
+ ` Scheduled and named runs continue to use live v${detail.play.liveRevision.version}.`
22948
+ );
22949
+ }
22950
+ for (const line of liveTriggerStatusLines(
22951
+ detail.play.triggerStatus,
22952
+ detail.play
22953
+ )) {
22954
+ console.log(line);
22955
+ }
22765
22956
  console.log(`Updated: ${formatTimestamp(detail.play.updatedAt)}`);
22766
22957
  console.log(`Sheet rows: ${detail.sheetSummary?.stats?.total ?? 0}`);
22767
22958
  if (detail.customerDbUrl) {
@@ -22846,19 +23037,23 @@ async function handlePlayList(args) {
22846
23037
  if (play.inputSchema || play.hasInputSchema) {
22847
23038
  process.stdout.write(" inputSchema: yes\n");
22848
23039
  }
22849
- const configuredTriggers = [
22850
- play.triggerStatus?.cron ? `cron=${play.triggerStatus.cron}` : null,
22851
- play.triggerStatus?.webhook ? `webhook=${play.triggerStatus.webhook}` : null
22852
- ].filter(Boolean);
22853
- if (configuredTriggers.length > 0) {
22854
- process.stdout.write(` triggers: ${configuredTriggers.join(", ")}
22855
- `);
22856
- if (play.triggerStatus?.blockedReason) {
23040
+ if (play.triggerStatus?.cron) {
23041
+ process.stdout.write(
23042
+ ` scheduled execution: ${cronExecutionLabel(play.triggerStatus.cron)}
23043
+ `
23044
+ );
23045
+ if (play.triggerStatus.blockedReason) {
22857
23046
  process.stdout.write(
22858
- ` trigger issue: ${play.triggerStatus.blockedReason}
23047
+ ` schedule issue: ${play.triggerStatus.blockedReason}
22859
23048
  `
22860
23049
  );
22861
23050
  }
23051
+ } else {
23052
+ process.stdout.write(" scheduled execution: not configured\n");
23053
+ }
23054
+ if (play.triggerStatus?.webhook) {
23055
+ process.stdout.write(` webhook: ${play.triggerStatus.webhook}
23056
+ `);
22862
23057
  }
22863
23058
  process.stdout.write(` run: deepline plays run ${reference} --watch
22864
23059
  `);
@@ -22966,15 +23161,13 @@ function printPlayDescription(play) {
22966
23161
  console.log(` ${line}`);
22967
23162
  }
22968
23163
  }
22969
- const configuredTriggers = [
22970
- play.triggerStatus?.cron ? `cron=${play.triggerStatus.cron}` : null,
22971
- play.triggerStatus?.webhook ? `webhook=${play.triggerStatus.webhook}` : null
22972
- ].filter(Boolean);
22973
- if (configuredTriggers.length > 0) {
22974
- console.log(` Triggers: ${configuredTriggers.join(", ")}`);
23164
+ for (const line of liveTriggerStatusLines(play.triggerStatus, play)) {
23165
+ console.log(line);
22975
23166
  }
22976
- if (play.triggerStatus?.blockedReason) {
22977
- console.log(` Trigger issue: ${play.triggerStatus.blockedReason}`);
23167
+ if (play.isDraftDirty && play.liveVersion) {
23168
+ console.log(
23169
+ ` Draft note: scheduled runs continue to use live v${play.liveVersion}.`
23170
+ );
22978
23171
  }
22979
23172
  const runtimeLimit = formatPlayRuntimeLimit(play.runtimeLimit);
22980
23173
  if (runtimeLimit) {
@@ -23400,7 +23593,9 @@ async function handlePlaySave(args) {
23400
23593
  console.log(
23401
23594
  `\u2713 Saved ${playName} working draft as v${result.version ?? "?"}`
23402
23595
  );
23403
- console.log(" Live revision unchanged.");
23596
+ console.log(
23597
+ " Live revision and any armed schedule are unchanged; scheduled runs do not use this draft yet."
23598
+ );
23404
23599
  console.log(` publish: ${result.next.publish}`);
23405
23600
  }
23406
23601
  return 0;
@@ -23547,24 +23742,19 @@ async function handlePlayPublish(args) {
23547
23742
  process.stdout.write(`${JSON.stringify(result2)}
23548
23743
  `);
23549
23744
  } else {
23550
- console.log(
23551
- `\u2713 Published ${rootPlayName} as v${result2.liveVersion ?? "?"}`
23552
- );
23745
+ printPublishReceipt({
23746
+ name: rootPlayName,
23747
+ liveVersion: result2.liveVersion,
23748
+ previousLiveVersion: result2.previousLiveVersion,
23749
+ triggerMetadata: result2.triggerMetadata
23750
+ });
23553
23751
  console.log(` source: ${result2.sourceHash.slice(0, 12)}`);
23554
23752
  console.log(` artifact: ${result2.artifactHash.slice(0, 12)}`);
23555
- if (result2.previousLiveVersion !== null) {
23556
- console.log(
23557
- ` previous live: v${result2.previousLiveVersion} (${result2.previousArtifactHash?.slice(0, 12) ?? "unknown artifact"})`
23558
- );
23559
- }
23560
23753
  if (result2.sourceBytes.before !== null) {
23561
23754
  console.log(
23562
23755
  ` source bytes: ${result2.sourceBytes.before.toLocaleString()} \u2192 ${result2.sourceBytes.after.toLocaleString()}`
23563
23756
  );
23564
23757
  }
23565
- console.log(
23566
- ` revisions: deepline plays versions --name ${rootPlayName}`
23567
- );
23568
23758
  }
23569
23759
  return 0;
23570
23760
  }
@@ -23605,8 +23795,16 @@ async function handlePlayPublish(args) {
23605
23795
  resolvedName,
23606
23796
  revisionId ? { revisionId } : {}
23607
23797
  );
23608
- process.stdout.write(`${JSON.stringify(result)}
23798
+ if (options.jsonOutput) {
23799
+ process.stdout.write(`${JSON.stringify(result)}
23609
23800
  `);
23801
+ } else {
23802
+ printPublishReceipt({
23803
+ name: result.name,
23804
+ liveVersion: result.liveVersion,
23805
+ triggerMetadata: result.triggerMetadata
23806
+ });
23807
+ }
23610
23808
  return result.success ? 0 : 1;
23611
23809
  }
23612
23810
  async function handlePlayDelete(args) {
@@ -31388,7 +31586,7 @@ function parseJsonObjectArg(raw, argLabel) {
31388
31586
  return parsed;
31389
31587
  }
31390
31588
  function resolveMonitorJsonBody(input2) {
31391
- const readFile5 = input2.readFile ?? ((path) => (0, import_node_fs14.readFileSync)(path, "utf-8"));
31589
+ const readFile6 = input2.readFile ?? ((path) => (0, import_node_fs14.readFileSync)(path, "utf-8"));
31392
31590
  const readStdin = input2.readStdin ?? (() => (0, import_node_fs14.readFileSync)(0, "utf-8"));
31393
31591
  if (input2.positional !== void 0 && input2.file !== void 0) {
31394
31592
  throw new MonitorsUsageError(
@@ -31404,7 +31602,7 @@ function resolveMonitorJsonBody(input2) {
31404
31602
  }
31405
31603
  let raw;
31406
31604
  try {
31407
- raw = readFile5(input2.file);
31605
+ raw = readFile6(input2.file);
31408
31606
  } catch (error) {
31409
31607
  throw new MonitorsUsageError(
31410
31608
  `Could not read --file ${input2.file}: ${error instanceof Error ? error.message : String(error)}`
@@ -33481,6 +33679,7 @@ async function handleOrgStatus(options) {
33481
33679
  config.apiKey
33482
33680
  );
33483
33681
  const folderTarget = resolveProjectPinTarget();
33682
+ const provenance = resolveCliAuthProvenance(config);
33484
33683
  const hostPath = hostEnvFilePath(config.baseUrl);
33485
33684
  const envApiKey = processEnvValue(API_KEY_ENV);
33486
33685
  const envHostUrl = processEnvValue(HOST_URL_ENV);
@@ -33529,6 +33728,9 @@ async function handleOrgStatus(options) {
33529
33728
  lines.push(`${API_KEY_ENV} overrides saved auth for this process.`);
33530
33729
  } else if (activeProject) {
33531
33730
  lines.push("Global auth is overridden in this folder.");
33731
+ } else if (provenance.scope === "global" && provenance.project.state === "project") {
33732
+ lines.push("Cloud mutations are blocked until this project is pinned.");
33733
+ lines.push("Pin it: deepline org set --auth-scope folder");
33532
33734
  }
33533
33735
  printCommandEnvelope(
33534
33736
  {
@@ -33539,6 +33741,15 @@ async function handleOrgStatus(options) {
33539
33741
  auth_source: authSource,
33540
33742
  host_env_path: hostPath,
33541
33743
  folder_target: folderTargetPayload,
33744
+ project_pin: provenance.scope === "global" && provenance.project.state === "project" ? {
33745
+ required: true,
33746
+ path: provenance.project.pinPath,
33747
+ cloud_mutations_blocked: true,
33748
+ command: "deepline org set --auth-scope folder"
33749
+ } : {
33750
+ required: false,
33751
+ cloud_mutations_blocked: false
33752
+ },
33542
33753
  next: {
33543
33754
  set_auto: "deepline org set <org>",
33544
33755
  set_folder: "deepline org set <org> --auth-scope folder",
@@ -33554,6 +33765,41 @@ async function handleOrgStatus(options) {
33554
33765
  async function handleOrgSwitch(selection, options) {
33555
33766
  const authScope = normalizeAuthScope2(options.authScope);
33556
33767
  const config = resolveConfig();
33768
+ const provenance = resolveCliAuthProvenance(config);
33769
+ if (!selection && !options.orgId && authScope === "folder" && provenance.scope === "global" && provenance.project.state === "project") {
33770
+ const project_env_paths2 = saveProjectDeeplineEnvValues(
33771
+ {
33772
+ [HOST_URL_ENV]: config.baseUrl,
33773
+ [API_KEY_ENV]: config.apiKey
33774
+ },
33775
+ provenance.project.dir
33776
+ );
33777
+ printCommandEnvelope(
33778
+ {
33779
+ ok: true,
33780
+ unchanged: true,
33781
+ requested_auth_scope: "folder",
33782
+ effective_auth_scope: "folder",
33783
+ auth_scope: "folder",
33784
+ project_env_paths: project_env_paths2,
33785
+ next: { status: "deepline org status --json" },
33786
+ render: {
33787
+ sections: [
33788
+ {
33789
+ title: "org set",
33790
+ lines: [
33791
+ "\u2713 Pinned this project to the current target.",
33792
+ `Saved folder auth in ${project_env_paths2[0]}.`,
33793
+ "Global host auth was not changed."
33794
+ ]
33795
+ }
33796
+ ]
33797
+ }
33798
+ },
33799
+ { json: options.json }
33800
+ );
33801
+ return;
33802
+ }
33557
33803
  const http = new HttpClient(config);
33558
33804
  const payload = await fetchOrganizations(http, config.apiKey);
33559
33805
  if (!selection && !options.orgId) {
@@ -33775,6 +34021,9 @@ Notes:
33775
34021
  use this org. Existing folder pins still override global auth.
33776
34022
 
33777
34023
  Process env DEEPLINE_API_KEY overrides saved auth for that command only.
34024
+ For projects, agents, CI, and multiple customer workspaces, prefer folder
34025
+ scope or a per-command DEEPLINE_API_KEY. Global scope is machine-wide and
34026
+ can make an unrelated terminal target the last-selected organization.
33778
34027
 
33779
34028
  Agent loop:
33780
34029
  deepline org list --json
@@ -33850,7 +34099,9 @@ Examples:
33850
34099
  `
33851
34100
  Notes:
33852
34101
  Selection can be a list number, exact organization name, or organization id.
33853
- Without a selection, prints choices.
34102
+ Without a selection, prints choices. With --auth-scope folder while this
34103
+ project is using global host auth, it pins the current target directly; this
34104
+ is the fastest safe repair for a blocked cloud mutation.
33854
34105
 
33855
34106
  Mutates local auth state and asks Deepline for an org-scoped API key. It
33856
34107
  writes only the selected scope:
@@ -33865,6 +34116,11 @@ Notes:
33865
34116
  folder, commands in that folder still use the folder pin until it is changed
33866
34117
  or removed.
33867
34118
 
34119
+ Prefer --auth-scope folder for a repository or customer workspace. Use
34120
+ --auth-scope global only for deliberate host-wide interactive defaults; it
34121
+ is shared by every unpinned CLI on this machine. For automation, pass
34122
+ DEEPLINE_API_KEY only to that invocation and confirm with org status --json.
34123
+
33868
34124
  Use --json for stable fields including effective_auth_scope,
33869
34125
  auth_scope_reason, host_env_path, project_env_paths, warnings, org_id, and
33870
34126
  org_name.
@@ -33988,6 +34244,7 @@ Deprecated:
33988
34244
 
33989
34245
  // src/cli/commands/secrets.ts
33990
34246
  var import_node_process = require("process");
34247
+ var import_promises9 = require("fs/promises");
33991
34248
  var hiddenInputBuffer = "";
33992
34249
  function normalizeSecretName(value) {
33993
34250
  const normalized = value.trim().toUpperCase();
@@ -34000,7 +34257,10 @@ function normalizeSecretName(value) {
34000
34257
  }
34001
34258
  function renderSecret(secret) {
34002
34259
  const scope = secret.scope === "play" && secret.playName ? `play:${secret.playName}` : secret.scope;
34003
- return `${secret.name} (${scope}) - ${secret.status}${secret.hasValue ? ", set" : ", empty"}`;
34260
+ const added = new Date(secret.createdAt).toISOString();
34261
+ const updated = new Date(secret.updatedAt).toISOString();
34262
+ const lastUsed = secret.lastUsedAt ? `, last used ${new Date(secret.lastUsedAt).toISOString()}` : ", never used";
34263
+ return `${secret.name} (${scope}) - ${secret.status}${secret.hasValue ? ", set" : ", empty"}, added ${added}${updated !== added ? `, updated ${updated}` : ""}${lastUsed}`;
34004
34264
  }
34005
34265
  async function readHiddenLine(prompt, streams = {}) {
34006
34266
  const inputStream = streams.input ?? import_node_process.stdin;
@@ -34092,6 +34352,48 @@ async function readSecretValue() {
34092
34352
  }
34093
34353
  return first;
34094
34354
  }
34355
+ function trimOneTerminalNewline(value) {
34356
+ return value.endsWith("\r\n") ? value.slice(0, -2) : value.endsWith("\n") ? value.slice(0, -1) : value;
34357
+ }
34358
+ async function readSecretValueFromOptions(options) {
34359
+ const sources = [
34360
+ options.valueStdin ? "--value-stdin" : null,
34361
+ options.fromEnv ? "--from-env" : null,
34362
+ options.fromFile ? "--from-file" : null
34363
+ ].filter((source) => Boolean(source));
34364
+ if (sources.length > 1) {
34365
+ throw new Error(
34366
+ "Use exactly one secret source: --value-stdin, --from-env, or --from-file."
34367
+ );
34368
+ }
34369
+ if (sources.length === 0) return readSecretValue();
34370
+ let value;
34371
+ if (options.valueStdin) {
34372
+ if (import_node_process.stdin.isTTY) {
34373
+ throw new Error(
34374
+ "--value-stdin requires piped stdin. Omit it to use the hidden interactive prompt."
34375
+ );
34376
+ }
34377
+ const chunks = [];
34378
+ for await (const chunk of import_node_process.stdin) {
34379
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
34380
+ }
34381
+ value = trimOneTerminalNewline(Buffer.concat(chunks).toString("utf8"));
34382
+ } else if (options.fromEnv) {
34383
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(options.fromEnv)) {
34384
+ throw new Error("--from-env must name a valid environment variable.");
34385
+ }
34386
+ const envValue = process.env[options.fromEnv];
34387
+ if (envValue === void 0) {
34388
+ throw new Error(`Environment variable ${options.fromEnv} is not set.`);
34389
+ }
34390
+ value = envValue;
34391
+ } else {
34392
+ value = trimOneTerminalNewline(await (0, import_promises9.readFile)(options.fromFile, "utf8"));
34393
+ }
34394
+ if (!value) throw new Error("Secret value is required.");
34395
+ return value;
34396
+ }
34095
34397
  function preventShellHistoryLeak(forbidden) {
34096
34398
  if (forbidden.length > 0) {
34097
34399
  throw new Error(
@@ -34132,7 +34434,7 @@ async function handleCheck(nameInput, options) {
34132
34434
  {
34133
34435
  title: "secret check",
34134
34436
  lines: [
34135
- secret ? `${name}: active` : `${name}: missing, disabled, or empty`
34437
+ secret ? `${name}: active \u2014 ${renderSecret(secret)}` : `${name}: missing, disabled, or empty`
34136
34438
  ]
34137
34439
  }
34138
34440
  ]
@@ -34150,7 +34452,7 @@ async function handleSet(nameInput, forbidden, options) {
34150
34452
  if (scope === "play" && !playName) {
34151
34453
  throw new Error("--play <name> is required when --scope play is used.");
34152
34454
  }
34153
- const value = await readSecretValue();
34455
+ const value = await readSecretValueFromOptions(options);
34154
34456
  const { http } = getAuthedHttpClient();
34155
34457
  const response = await http.post(
34156
34458
  "/api/v2/secrets",
@@ -34170,7 +34472,10 @@ async function handleSet(nameInput, forbidden, options) {
34170
34472
  sections: [
34171
34473
  {
34172
34474
  title: "secret saved",
34173
- lines: [`${secret.name}: saved (${secret.scope})`]
34475
+ lines: [
34476
+ `${secret.name}: saved (${secret.scope}); secret value was not displayed.`,
34477
+ renderSecret(secret)
34478
+ ]
34174
34479
  }
34175
34480
  ]
34176
34481
  }
@@ -34183,14 +34488,18 @@ function registerSecretsCommands(program) {
34183
34488
  "after",
34184
34489
  `
34185
34490
  Notes:
34186
- Secret values are never accepted as command arguments, stdin pipes, env vars,
34187
- or files. Use deepline secrets set NAME and type the value at the hidden TTY
34188
- prompt. Agents can list/check metadata but should not enter secret values.
34491
+ Secret values are never accepted as command arguments. Use the hidden prompt,
34492
+ or one explicit non-argv source: --value-stdin, --from-env NAME, or
34493
+ --from-file PATH. Values are never printed. secrets list shows only status,
34494
+ added, updated, and last-used metadata.
34189
34495
 
34190
34496
  Examples:
34191
34497
  deepline secrets list
34192
34498
  deepline secrets check HUBSPOT_TOKEN
34193
34499
  deepline secrets set HUBSPOT_TOKEN
34500
+ printf %s "$HUBSPOT_TOKEN" | deepline secrets set HUBSPOT_TOKEN --value-stdin
34501
+ deepline secrets set HUBSPOT_TOKEN --from-env HUBSPOT_TOKEN
34502
+ deepline secrets set HUBSPOT_TOKEN --from-file ./hubspot-token.txt
34194
34503
  `
34195
34504
  );
34196
34505
  secrets.command("list").description("List secret metadata only.").option("--json", "Emit JSON output").action(async (options) => {
@@ -34199,7 +34508,7 @@ Examples:
34199
34508
  secrets.command("check").description("Check whether a secret exists and is active.").argument("<name>", "Secret name").option("--json", "Emit JSON output").action(async (name, options) => {
34200
34509
  await handleCheck(name, options);
34201
34510
  });
34202
- secrets.command("set").description("Set or rotate a secret through a hidden interactive prompt.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play", "org").option("--play <name>", "Play name for play-scoped secrets").action(
34511
+ secrets.command("set").description("Set or rotate a secret without exposing its value in argv.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play", "org").option("--play <name>", "Play name for play-scoped secrets").option("--value-stdin", "Read the value from piped stdin").option("--from-env <name>", "Read the value from an environment variable").option("--from-file <path>", "Read the value from a file").action(
34203
34512
  async (name, forbidden, options) => {
34204
34513
  await handleSet(name, forbidden ?? [], options);
34205
34514
  }
@@ -40735,7 +41044,7 @@ Examples:
40735
41044
  }
40736
41045
 
40737
41046
  // src/cli/commands/workflow.ts
40738
- var import_promises9 = require("fs/promises");
41047
+ var import_promises10 = require("fs/promises");
40739
41048
  var import_node_path27 = require("path");
40740
41049
 
40741
41050
  // src/cli/workflow-to-play.ts
@@ -40953,7 +41262,7 @@ function readStatus(payload) {
40953
41262
  }
40954
41263
  async function readJsonOption(payload, file) {
40955
41264
  if (file) {
40956
- const raw = await (0, import_promises9.readFile)((0, import_node_path27.resolve)(file), "utf8");
41265
+ const raw = await (0, import_promises10.readFile)((0, import_node_path27.resolve)(file), "utf8");
40957
41266
  return JSON.parse(raw);
40958
41267
  }
40959
41268
  if (payload) {
@@ -40988,8 +41297,8 @@ async function transformOne(api, workflowId, outDir, publish) {
40988
41297
  { workflowName: workflow.name, version: revision.version }
40989
41298
  );
40990
41299
  const file = (0, import_node_path27.join)((0, import_node_path27.resolve)(outDir), `${compiled.playName}.play.ts`);
40991
- await (0, import_promises9.mkdir)((0, import_node_path27.dirname)(file), { recursive: true });
40992
- await (0, import_promises9.writeFile)(file, compiled.sourceCode, "utf8");
41300
+ await (0, import_promises10.mkdir)((0, import_node_path27.dirname)(file), { recursive: true });
41301
+ await (0, import_promises10.writeFile)(file, compiled.sourceCode, "utf8");
40993
41302
  let published = false;
40994
41303
  if (publish) {
40995
41304
  const code = await handlePlayPublish([file]);
@@ -41719,6 +42028,97 @@ async function maybeReportSdkCliFailure(input2) {
41719
42028
 
41720
42029
  // src/cli/index.ts
41721
42030
  var PREFLIGHT_TIMEOUT_MS = 3e3;
42031
+ var ProjectOrgPinRequiredError = class extends Error {
42032
+ code = "PROJECT_ORG_NOT_PINNED";
42033
+ exitCode = 3;
42034
+ payload;
42035
+ constructor(input2) {
42036
+ super("Cloud work is blocked because this project uses global host auth.");
42037
+ this.name = "ProjectOrgPinRequiredError";
42038
+ this.payload = {
42039
+ ok: false,
42040
+ exitCode: this.exitCode,
42041
+ code: this.code,
42042
+ message: this.message,
42043
+ command: input2.command,
42044
+ auth: { scope: "global", source: "host", projectPinned: false },
42045
+ project: { dir: input2.projectDir, pinPath: input2.pinPath },
42046
+ next: "deepline org set --auth-scope folder"
42047
+ };
42048
+ }
42049
+ };
42050
+ function commandUsesOnlyReadOrLocalOperations(command) {
42051
+ const [group, action] = command.split(" ");
42052
+ if ([
42053
+ "auth",
42054
+ "org",
42055
+ "health",
42056
+ "preflight",
42057
+ "version",
42058
+ "update",
42059
+ "skills",
42060
+ "doctor",
42061
+ "quickstart"
42062
+ ].includes(group ?? "")) {
42063
+ return true;
42064
+ }
42065
+ if (group === "plays") {
42066
+ return [
42067
+ "check",
42068
+ "get",
42069
+ "list",
42070
+ "search",
42071
+ "grep",
42072
+ "describe",
42073
+ "versions"
42074
+ ].includes(action ?? "");
42075
+ }
42076
+ if (group === "runs") {
42077
+ return ["get", "list", "tail", "logs", "export"].includes(action ?? "");
42078
+ }
42079
+ if (group === "tools") {
42080
+ return ["list", "search", "get", "describe"].includes(action ?? "");
42081
+ }
42082
+ if (group === "providers") return ["list", "get"].includes(action ?? "");
42083
+ if (group === "secrets") return ["list", "check"].includes(action ?? "");
42084
+ if (group === "billing")
42085
+ return ["balance", "usage", "history"].includes(action ?? "");
42086
+ return false;
42087
+ }
42088
+ function assertProjectCloudWorkIsPinned(command) {
42089
+ if (process.argv.includes("--dry-run") || commandUsesOnlyReadOrLocalOperations(command)) {
42090
+ return;
42091
+ }
42092
+ const config = resolveConfig();
42093
+ const provenance = resolveCliAuthProvenance(config);
42094
+ if (provenance.scope !== "global" || provenance.project.state !== "project") {
42095
+ return;
42096
+ }
42097
+ throw new ProjectOrgPinRequiredError({
42098
+ command,
42099
+ projectDir: provenance.project.dir,
42100
+ pinPath: provenance.project.pinPath
42101
+ });
42102
+ }
42103
+ function printProjectOrgPinRequiredError(error) {
42104
+ if (shouldEmitJson(process.argv.includes("--json"))) {
42105
+ printJson(error.payload);
42106
+ return;
42107
+ }
42108
+ const project = error.payload.project;
42109
+ process.stderr.write(
42110
+ [
42111
+ "\u2717 Cloud work is blocked in this project",
42112
+ "",
42113
+ " Auth: global host default",
42114
+ " This project is not pinned. Global auth is shared by every unpinned CLI on this machine.",
42115
+ "",
42116
+ " Pin this folder to the current target:",
42117
+ " deepline org set --auth-scope folder",
42118
+ ` This writes: ${project.pinPath}`
42119
+ ].join("\n") + "\n"
42120
+ );
42121
+ }
41722
42122
  function asCommanderError(error) {
41723
42123
  if (!(error instanceof Error) || !("code" in error)) {
41724
42124
  return null;
@@ -41776,10 +42176,10 @@ function topLevelCommandKnown(program, commandName) {
41776
42176
  );
41777
42177
  }
41778
42178
  async function runPlayRunnerHealthCheck() {
41779
- const dir = await (0, import_promises10.mkdtemp)((0, import_node_path28.join)((0, import_node_os18.tmpdir)(), "deepline-health-play-"));
42179
+ const dir = await (0, import_promises11.mkdtemp)((0, import_node_path28.join)((0, import_node_os18.tmpdir)(), "deepline-health-play-"));
41780
42180
  const file = (0, import_node_path28.join)(dir, "health-check.play.ts");
41781
42181
  try {
41782
- await (0, import_promises10.writeFile)(
42182
+ await (0, import_promises11.writeFile)(
41783
42183
  file,
41784
42184
  [
41785
42185
  "import { definePlay } from 'deepline';",
@@ -41828,7 +42228,7 @@ async function runPlayRunnerHealthCheck() {
41828
42228
  }
41829
42229
  };
41830
42230
  } finally {
41831
- await (0, import_promises10.rm)(dir, { recursive: true, force: true });
42231
+ await (0, import_promises11.rm)(dir, { recursive: true, force: true });
41832
42232
  }
41833
42233
  }
41834
42234
  function pickString(value, ...keys) {
@@ -42028,11 +42428,12 @@ Exit codes:
42028
42428
  if (actionCommand.name() === "version" || actionCommand.name() === "update" || actionCommand.name() === "setup" || actionCommand.name() === "skills" || actionCommand.name() === "doctor" || isAutoUpdateSettingsInvocation() || isDeprecatedCommandInvocation()) {
42029
42429
  return;
42030
42430
  }
42431
+ const compatibilityCommand = compatibilityCommandPath(actionCommand) || actionCommand.name();
42432
+ assertProjectCloudWorkIsPinned(compatibilityCommand);
42031
42433
  if (printStartupPhase) {
42032
42434
  progress?.phase("checking sdk compatibility");
42033
42435
  }
42034
42436
  const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
42035
- const compatibilityCommand = compatibilityCommandPath(actionCommand) || actionCommand.name();
42036
42437
  const shouldDeferSkillsSync = shouldDeferSkillsSyncForCommand();
42037
42438
  const skillsVersion = shouldDeferSkillsSync ? void 0 : readSdkSkillsLocalVersion(baseUrl);
42038
42439
  const compatibility = await traceCliSpan(
@@ -42209,7 +42610,10 @@ Examples:
42209
42610
  });
42210
42611
  progress?.fail();
42211
42612
  const wantsJson = process.argv.includes("--json");
42212
- if (commanderError) {
42613
+ if (error instanceof ProjectOrgPinRequiredError) {
42614
+ printProjectOrgPinRequiredError(error);
42615
+ process.exitCode = error.exitCode;
42616
+ } else if (commanderError) {
42213
42617
  if (commanderError.code === "commander.unknownCommand") {
42214
42618
  }
42215
42619
  process.exitCode = commanderError.code === "commander.unknownCommand" && !wantsJson ? 2 : commanderError.exitCode ?? 1;