deepline 0.1.20 → 0.1.21

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
@@ -266,7 +266,7 @@ function saveProjectDeeplineEnvValues(baseUrl, values, startDir = projectEnvStar
266
266
  }
267
267
 
268
268
  // src/version.ts
269
- var SDK_VERSION = "0.1.20";
269
+ var SDK_VERSION = "0.1.21";
270
270
  var SDK_API_CONTRACT = "2026-05-runs-v2";
271
271
 
272
272
  // ../shared_libs/play-runtime/coordinator-headers.ts
@@ -349,7 +349,7 @@ var HttpClient = class {
349
349
  const response = await fetch(candidateUrl, {
350
350
  method,
351
351
  headers,
352
- body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
352
+ body: options?.formData !== void 0 ? options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
353
353
  signal: controller.signal
354
354
  });
355
355
  clearTimeout(timeoutId);
@@ -468,6 +468,13 @@ var HttpClient = class {
468
468
  headers
469
469
  });
470
470
  }
471
+ async postFormData(path, formData, headers) {
472
+ return this.request(path, {
473
+ method: "POST",
474
+ formData,
475
+ headers
476
+ });
477
+ }
471
478
  /**
472
479
  * Send a DELETE request.
473
480
  *
@@ -576,6 +583,14 @@ function mapLegacyTemporalStatus(status) {
576
583
  return "running";
577
584
  }
578
585
  }
586
+ function decodeBase64Bytes(value) {
587
+ const binary = atob(value);
588
+ const bytes = new Uint8Array(binary.length);
589
+ for (let index = 0; index < binary.length; index += 1) {
590
+ bytes[index] = binary.charCodeAt(index);
591
+ }
592
+ return bytes;
593
+ }
579
594
  var DeeplineClient = class {
580
595
  http;
581
596
  config;
@@ -1027,9 +1042,34 @@ var DeeplineClient = class {
1027
1042
  * ```
1028
1043
  */
1029
1044
  async stagePlayFiles(files) {
1030
- const response = await this.http.post(
1045
+ const formData = new FormData();
1046
+ formData.set(
1047
+ "metadata",
1048
+ JSON.stringify({
1049
+ files: files.map((file, index) => ({
1050
+ index,
1051
+ logicalPath: file.logicalPath,
1052
+ contentHash: file.contentHash,
1053
+ contentType: file.contentType,
1054
+ bytes: file.bytes
1055
+ }))
1056
+ })
1057
+ );
1058
+ for (const [index, file] of files.entries()) {
1059
+ const bytes = decodeBase64Bytes(file.contentBase64);
1060
+ const body = bytes.buffer.slice(
1061
+ bytes.byteOffset,
1062
+ bytes.byteOffset + bytes.byteLength
1063
+ );
1064
+ formData.set(
1065
+ `file:${index}`,
1066
+ new Blob([body], { type: file.contentType }),
1067
+ file.logicalPath
1068
+ );
1069
+ }
1070
+ const response = await this.http.postFormData(
1031
1071
  "/api/v2/plays/files/stage",
1032
- { files }
1072
+ formData
1033
1073
  );
1034
1074
  return response.files;
1035
1075
  }
@@ -1058,9 +1098,14 @@ var DeeplineClient = class {
1058
1098
  * console.log(`Logs: ${status.progress?.logs.length ?? 0} lines`);
1059
1099
  * ```
1060
1100
  */
1061
- async getPlayStatus(workflowId) {
1101
+ async getPlayStatus(workflowId, options) {
1102
+ const params = new URLSearchParams();
1103
+ if (options?.billing === false) {
1104
+ params.set("billing", "false");
1105
+ }
1106
+ const query = params.size > 0 ? `?${params.toString()}` : "";
1062
1107
  const response = await this.http.get(
1063
- `/api/v2/plays/run/${encodeURIComponent(workflowId)}`
1108
+ `/api/v2/plays/run/${encodeURIComponent(workflowId)}${query}`
1064
1109
  );
1065
1110
  return normalizePlayStatus(response);
1066
1111
  }
@@ -4362,7 +4407,77 @@ function createCliProgress(enabled) {
4362
4407
  return progress;
4363
4408
  }
4364
4409
 
4410
+ // src/cli/trace.ts
4411
+ var cliTraceStartedAt = Date.now();
4412
+ function isTruthyEnv(value) {
4413
+ return value === "1" || value === "true" || value === "yes";
4414
+ }
4415
+ function isCliTraceEnabled() {
4416
+ return isTruthyEnv(process.env.DEEPLINE_CLI_TRACE);
4417
+ }
4418
+ function recordCliTrace(event) {
4419
+ if (!isCliTraceEnabled()) {
4420
+ return;
4421
+ }
4422
+ const now = Date.now();
4423
+ const payload = {
4424
+ ts: now,
4425
+ source: "cli",
4426
+ sinceStartMs: now - cliTraceStartedAt,
4427
+ ...event
4428
+ };
4429
+ process.stderr.write(`[cli-trace] ${JSON.stringify(payload)}
4430
+ `);
4431
+ }
4432
+ async function traceCliSpan(phase, fields, run) {
4433
+ if (!isCliTraceEnabled()) {
4434
+ return run();
4435
+ }
4436
+ const startedAt = Date.now();
4437
+ try {
4438
+ const result = await run();
4439
+ recordCliTrace({
4440
+ phase,
4441
+ ms: Date.now() - startedAt,
4442
+ ok: true,
4443
+ ...fields
4444
+ });
4445
+ return result;
4446
+ } catch (error) {
4447
+ recordCliTrace({
4448
+ phase,
4449
+ ms: Date.now() - startedAt,
4450
+ ok: false,
4451
+ error: error instanceof Error ? error.message : String(error),
4452
+ ...fields
4453
+ });
4454
+ throw error;
4455
+ }
4456
+ }
4457
+
4365
4458
  // src/cli/commands/play.ts
4459
+ function traceCliSync(phase, fields, run) {
4460
+ const startedAt = Date.now();
4461
+ try {
4462
+ const result = run();
4463
+ recordCliTrace({
4464
+ phase,
4465
+ ms: Date.now() - startedAt,
4466
+ ok: true,
4467
+ ...fields
4468
+ });
4469
+ return result;
4470
+ } catch (error) {
4471
+ recordCliTrace({
4472
+ phase,
4473
+ ms: Date.now() - startedAt,
4474
+ ok: false,
4475
+ error: error instanceof Error ? error.message : String(error),
4476
+ ...fields
4477
+ });
4478
+ throw error;
4479
+ }
4480
+ }
4366
4481
  function parseReferencedPlayTarget(target) {
4367
4482
  const trimmed = target.trim();
4368
4483
  const slashIndex = trimmed.indexOf("/");
@@ -4601,6 +4716,23 @@ function isLocalFilePathValue(value) {
4601
4716
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
4602
4717
  return (0, import_node_fs6.existsSync)((0, import_node_path8.resolve)(value));
4603
4718
  }
4719
+ function inputContainsLocalFilePath(value) {
4720
+ if (isLocalFilePathValue(value)) {
4721
+ return true;
4722
+ }
4723
+ if (Array.isArray(value)) {
4724
+ return value.some((entry) => inputContainsLocalFilePath(entry));
4725
+ }
4726
+ if (value && typeof value === "object") {
4727
+ return Object.values(value).some(
4728
+ (entry) => inputContainsLocalFilePath(entry)
4729
+ );
4730
+ }
4731
+ return false;
4732
+ }
4733
+ function namedRunNeedsPlayDefinition(input) {
4734
+ return input.revisionSelector === "latest" || getDottedInputValue(input.runtimeInput, "csv") != null || inputContainsLocalFilePath(input.runtimeInput);
4735
+ }
4604
4736
  async function stageFileInputArgs(input) {
4605
4737
  const uniqueBindings = [
4606
4738
  ...new Map(input.bindings.map((binding) => [binding.inputPath, binding])).values()
@@ -4913,6 +5045,8 @@ async function startAndWaitForPlayCompletionByStream(input) {
4913
5045
  let timedOut = false;
4914
5046
  let emittedDashboardUrl = false;
4915
5047
  let lastKnownWorkflowId = "";
5048
+ let eventCount = 0;
5049
+ let firstRunIdMs = null;
4916
5050
  let lastPhase = null;
4917
5051
  const timeout = input.waitTimeoutMs === null ? null : setTimeout(
4918
5052
  () => {
@@ -4925,9 +5059,11 @@ async function startAndWaitForPlayCompletionByStream(input) {
4925
5059
  for await (const event of input.client.startPlayRunStream(input.request, {
4926
5060
  signal: controller.signal
4927
5061
  })) {
5062
+ eventCount += 1;
4928
5063
  const eventRunId = getEventPayload(event).runId;
4929
5064
  if (typeof eventRunId === "string" && eventRunId && eventRunId !== "pending") {
4930
5065
  lastKnownWorkflowId = eventRunId;
5066
+ firstRunIdMs ??= Date.now() - startedAt;
4931
5067
  }
4932
5068
  const workflowId = lastKnownWorkflowId || "pending";
4933
5069
  if (workflowId !== "pending" && !emittedDashboardUrl) {
@@ -4965,6 +5101,16 @@ async function startAndWaitForPlayCompletionByStream(input) {
4965
5101
  });
4966
5102
  const finalStatus = getFinalStatusFromLiveEvent(event);
4967
5103
  if (finalStatus) {
5104
+ recordCliTrace({
5105
+ phase: "cli.play_start_stream_terminal",
5106
+ ms: Date.now() - startedAt,
5107
+ ok: true,
5108
+ playName: input.playName,
5109
+ workflowId: finalStatus.runId || lastKnownWorkflowId || null,
5110
+ eventCount,
5111
+ firstRunIdMs,
5112
+ lastPhase
5113
+ });
4968
5114
  return finalStatus;
4969
5115
  }
4970
5116
  }
@@ -4988,6 +5134,17 @@ async function startAndWaitForPlayCompletionByStream(input) {
4988
5134
  `
4989
5135
  );
4990
5136
  }
5137
+ recordCliTrace({
5138
+ phase: "cli.play_start_stream_fallback",
5139
+ ms: Date.now() - startedAt,
5140
+ ok: false,
5141
+ playName: input.playName,
5142
+ workflowId: lastKnownWorkflowId,
5143
+ eventCount,
5144
+ firstRunIdMs,
5145
+ lastPhase,
5146
+ reason
5147
+ });
4991
5148
  return waitForPlayCompletionByPolling({
4992
5149
  client: input.client,
4993
5150
  workflowId: lastKnownWorkflowId,
@@ -5012,6 +5169,17 @@ async function startAndWaitForPlayCompletionByStream(input) {
5012
5169
  `[play watch] start stream ended after run ${lastKnownWorkflowId}; falling back to polling`
5013
5170
  );
5014
5171
  }
5172
+ recordCliTrace({
5173
+ phase: "cli.play_start_stream_fallback",
5174
+ ms: Date.now() - startedAt,
5175
+ ok: false,
5176
+ playName: input.playName,
5177
+ workflowId: lastKnownWorkflowId,
5178
+ eventCount,
5179
+ firstRunIdMs,
5180
+ lastPhase,
5181
+ reason: "stream ended before terminal event"
5182
+ });
5015
5183
  return waitForPlayCompletionByPolling({
5016
5184
  client: input.client,
5017
5185
  workflowId: lastKnownWorkflowId,
@@ -5086,10 +5254,11 @@ async function waitForPlayCompletionByPolling(input) {
5086
5254
  progress: input.progress
5087
5255
  });
5088
5256
  if (TERMINAL_PLAY_STATUSES2.has(status.status)) {
5089
- return status.result !== void 0 ? status : await input.client.getPlayStatus(input.workflowId);
5257
+ return status.result !== void 0 ? status : await input.client.getPlayStatus(input.workflowId, { billing: false });
5090
5258
  }
5091
5259
  const authoritativeStatus = await input.client.getPlayStatus(
5092
- input.workflowId
5260
+ input.workflowId,
5261
+ { billing: false }
5093
5262
  );
5094
5263
  if (TERMINAL_PLAY_STATUSES2.has(authoritativeStatus.status)) {
5095
5264
  return authoritativeStatus;
@@ -5844,11 +6013,24 @@ async function handleFileBackedRun(options) {
5844
6013
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
5845
6014
  const absolutePlayPath = (0, import_node_path8.resolve)(options.target.path);
5846
6015
  progress.phase("compiling play");
5847
- const sourceCode = (0, import_node_fs6.readFileSync)(absolutePlayPath, "utf-8");
6016
+ const sourceCode = traceCliSync(
6017
+ "cli.play_file_read_source",
6018
+ { targetKind: "file" },
6019
+ () => (0, import_node_fs6.readFileSync)(absolutePlayPath, "utf-8")
6020
+ );
6021
+ const runtimeInput = options.input ? { ...options.input } : {};
5848
6022
  let graph;
5849
6023
  try {
5850
- graph = await collectBundledPlayGraph(absolutePlayPath);
5851
- await compileBundledPlayGraphManifests(client, graph);
6024
+ graph = await traceCliSpan(
6025
+ "cli.play_file_bundle_graph",
6026
+ { targetKind: "file" },
6027
+ () => collectBundledPlayGraph(absolutePlayPath)
6028
+ );
6029
+ await traceCliSpan(
6030
+ "cli.play_file_compile_manifests",
6031
+ { targetKind: "file" },
6032
+ () => compileBundledPlayGraphManifests(client, graph)
6033
+ );
5852
6034
  progress.phase("compiled play");
5853
6035
  } catch (error) {
5854
6036
  progress.fail();
@@ -5859,36 +6041,47 @@ async function handleFileBackedRun(options) {
5859
6041
  const playName = bundleResult.playName ?? extractPlayName(sourceCode, absolutePlayPath);
5860
6042
  try {
5861
6043
  progress.phase("publishing imported plays");
5862
- await publishImportedPlayDependencies(client, graph);
6044
+ await traceCliSpan(
6045
+ "cli.play_file_publish_imports",
6046
+ { targetKind: "file" },
6047
+ () => publishImportedPlayDependencies(client, graph)
6048
+ );
5863
6049
  } catch (error) {
5864
6050
  progress.fail();
5865
6051
  console.error(error instanceof Error ? error.message : String(error));
5866
6052
  return 1;
5867
6053
  }
5868
- const runtimeInput = options.input ? { ...options.input } : {};
5869
6054
  const packagedFileUploads = bundleResult.packagedFiles.map(
5870
6055
  (file) => stageFile(file.logicalPath, file.absolutePath)
5871
6056
  );
6057
+ const compilerManifest = requireCompilerManifest(bundleResult);
5872
6058
  const fileInputBindings = fileInputBindingsFromStaticPipeline(
5873
- requireCompilerManifest(bundleResult).staticPipeline
6059
+ compilerManifest.staticPipeline
5874
6060
  );
5875
6061
  applyCsvShortcutInput({
5876
6062
  runtimeInput,
5877
6063
  bindings: fileInputBindings,
5878
6064
  fallbackInputPath: "file"
5879
6065
  });
5880
- const stagedFileInputs = await stageFileInputArgs({
5881
- client,
5882
- runtimeInput,
5883
- bindings: fileInputBindings,
5884
- progress
5885
- });
6066
+ const stagedFileInputs = await traceCliSpan(
6067
+ "cli.play_stage_inputs",
6068
+ {
6069
+ targetKind: "file",
6070
+ bindingCount: fileInputBindings.length
6071
+ },
6072
+ () => stageFileInputArgs({
6073
+ client,
6074
+ runtimeInput,
6075
+ bindings: fileInputBindings,
6076
+ progress
6077
+ })
6078
+ );
5886
6079
  const startRequest = {
5887
6080
  name: playName,
5888
6081
  sourceCode: bundleResult.sourceCode,
5889
6082
  sourceFiles: bundleResult.sourceFiles,
5890
6083
  runtimeArtifact: bundleResult.artifact,
5891
- compilerManifest: requireCompilerManifest(bundleResult),
6084
+ compilerManifest,
5892
6085
  packagedFileUploads,
5893
6086
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
5894
6087
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
@@ -5897,26 +6090,42 @@ async function handleFileBackedRun(options) {
5897
6090
  };
5898
6091
  if (options.watch) {
5899
6092
  progress.phase("starting run");
5900
- const finalStatus = await startAndWaitForPlayCompletionByStream({
5901
- client,
5902
- request: startRequest,
5903
- playName,
5904
- jsonOutput: options.jsonOutput,
5905
- emitLogs: options.emitLogs,
5906
- waitTimeoutMs: options.waitTimeoutMs,
5907
- progress
5908
- });
5909
- const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
6093
+ const finalStatus = await traceCliSpan(
6094
+ "cli.play_start_watch",
6095
+ { targetKind: "file", playName },
6096
+ () => startAndWaitForPlayCompletionByStream({
6097
+ client,
6098
+ request: startRequest,
6099
+ playName,
6100
+ jsonOutput: options.jsonOutput,
6101
+ emitLogs: options.emitLogs,
6102
+ waitTimeoutMs: options.waitTimeoutMs,
6103
+ progress
6104
+ })
6105
+ );
6106
+ const exportedPath = traceCliSync(
6107
+ "cli.play_export_rows",
6108
+ { targetKind: "file", playName },
6109
+ () => exportPlayStatusRows(finalStatus, options.outPath)
6110
+ );
5910
6111
  if (finalStatus.status === "completed") {
5911
6112
  progress.complete();
5912
6113
  } else {
5913
6114
  progress.fail();
5914
6115
  }
5915
- writePlayResult(finalStatus, options.jsonOutput, { exportedPath });
6116
+ traceCliSync(
6117
+ "cli.play_write_result",
6118
+ { targetKind: "file", playName },
6119
+ () => writePlayResult(finalStatus, options.jsonOutput, { exportedPath })
6120
+ );
5916
6121
  return finalStatus.status === "completed" ? 0 : 1;
5917
6122
  }
5918
6123
  progress.phase("starting run");
5919
- const started = await client.startPlayRun(startRequest);
6124
+ const started = await traceCliSpan(
6125
+ "cli.play_start_unwatched",
6126
+ { targetKind: "file", playName },
6127
+ () => client.startPlayRun(startRequest)
6128
+ );
5920
6129
  const dashboardUrl = buildPlayDashboardUrl(client.baseUrl, playName);
5921
6130
  progress.phase(`loading play on ${dashboardUrl}`);
5922
6131
  progress.complete();
@@ -5951,32 +6160,67 @@ async function handleNamedRun(options) {
5951
6160
  }
5952
6161
  const client = new DeeplineClient();
5953
6162
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
5954
- progress.phase("loading play definition");
5955
- const playDetail = await assertCanonicalNamedPlayReference(client, options.target.name);
5956
- progress.phase("selecting revision");
5957
- const selectedRevisionId = await resolveNamedRunRevisionId({
5958
- client,
5959
- playName: options.target.name,
5960
- revisionId: options.revisionId,
5961
- selector: options.revisionSelector
5962
- });
6163
+ const playName = options.target.name;
5963
6164
  const runtimeInput = options.input ? { ...options.input } : {};
5964
- const fileInputBindings = [
6165
+ const needsPlayDefinition = namedRunNeedsPlayDefinition({
6166
+ runtimeInput,
6167
+ revisionSelector: options.revisionSelector
6168
+ });
6169
+ const playDetail = needsPlayDefinition ? await (async () => {
6170
+ progress.phase("loading play definition");
6171
+ return traceCliSpan(
6172
+ "cli.play_load_definition",
6173
+ { targetKind: "name", playName, skipped: false },
6174
+ () => assertCanonicalNamedPlayReference(client, playName)
6175
+ );
6176
+ })() : (recordCliTrace({
6177
+ phase: "cli.play_load_definition",
6178
+ ms: 0,
6179
+ ok: true,
6180
+ targetKind: "name",
6181
+ playName,
6182
+ skipped: true
6183
+ }), null);
6184
+ progress.phase("selecting revision");
6185
+ const selectedRevisionId = await traceCliSpan(
6186
+ "cli.play_select_revision",
6187
+ {
6188
+ targetKind: "name",
6189
+ playName,
6190
+ selector: options.revisionSelector,
6191
+ hasExplicitRevisionId: Boolean(options.revisionId)
6192
+ },
6193
+ () => resolveNamedRunRevisionId({
6194
+ client,
6195
+ playName,
6196
+ revisionId: options.revisionId,
6197
+ selector: options.revisionSelector
6198
+ })
6199
+ );
6200
+ const fileInputBindings = playDetail ? [
5965
6201
  ...fileInputBindingsFromPlaySchema(playDetail.play.inputSchema),
5966
6202
  ...fileInputBindingsFromStaticPipeline(playDetail.play.staticPipeline)
5967
- ];
6203
+ ] : [];
5968
6204
  applyCsvShortcutInput({
5969
6205
  runtimeInput,
5970
6206
  bindings: fileInputBindings
5971
6207
  });
5972
- const stagedFileInputs = await stageFileInputArgs({
5973
- client,
5974
- runtimeInput,
5975
- bindings: fileInputBindings,
5976
- progress
5977
- });
6208
+ const stagedFileInputs = await traceCliSpan(
6209
+ "cli.play_stage_inputs",
6210
+ {
6211
+ targetKind: "name",
6212
+ playName,
6213
+ bindingCount: fileInputBindings.length
6214
+ },
6215
+ () => stageFileInputArgs({
6216
+ client,
6217
+ runtimeInput,
6218
+ bindings: fileInputBindings,
6219
+ progress
6220
+ })
6221
+ );
5978
6222
  const startRequest = {
5979
- name: options.target.name,
6223
+ name: playName,
5980
6224
  ...selectedRevisionId ? { revisionId: selectedRevisionId } : {},
5981
6225
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
5982
6226
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
@@ -5985,35 +6229,51 @@ async function handleNamedRun(options) {
5985
6229
  };
5986
6230
  if (options.watch) {
5987
6231
  progress.phase("starting run");
5988
- const finalStatus = await startAndWaitForPlayCompletionByStream({
5989
- client,
5990
- request: startRequest,
5991
- playName: options.target.name,
5992
- jsonOutput: options.jsonOutput,
5993
- emitLogs: options.emitLogs,
5994
- waitTimeoutMs: options.waitTimeoutMs,
5995
- progress
5996
- });
5997
- const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
6232
+ const finalStatus = await traceCliSpan(
6233
+ "cli.play_start_watch",
6234
+ { targetKind: "name", playName },
6235
+ () => startAndWaitForPlayCompletionByStream({
6236
+ client,
6237
+ request: startRequest,
6238
+ playName,
6239
+ jsonOutput: options.jsonOutput,
6240
+ emitLogs: options.emitLogs,
6241
+ waitTimeoutMs: options.waitTimeoutMs,
6242
+ progress
6243
+ })
6244
+ );
6245
+ const exportedPath = traceCliSync(
6246
+ "cli.play_export_rows",
6247
+ { targetKind: "name", playName },
6248
+ () => exportPlayStatusRows(finalStatus, options.outPath)
6249
+ );
5998
6250
  if (finalStatus.status === "completed") {
5999
6251
  progress.complete();
6000
6252
  } else {
6001
6253
  progress.fail();
6002
6254
  }
6003
- writePlayResult(finalStatus, options.jsonOutput, { exportedPath });
6255
+ traceCliSync(
6256
+ "cli.play_write_result",
6257
+ { targetKind: "name", playName },
6258
+ () => writePlayResult(finalStatus, options.jsonOutput, { exportedPath })
6259
+ );
6004
6260
  return finalStatus.status === "completed" ? 0 : 1;
6005
6261
  }
6006
6262
  progress.phase("starting run");
6007
- const started = await client.startPlayRun(startRequest);
6263
+ const started = await traceCliSpan(
6264
+ "cli.play_start_unwatched",
6265
+ { targetKind: "name", playName },
6266
+ () => client.startPlayRun(startRequest)
6267
+ );
6008
6268
  const dashboardUrl = buildPlayDashboardUrl(
6009
6269
  client.baseUrl,
6010
- options.target.name
6270
+ playName
6011
6271
  );
6012
6272
  progress.phase(`loading play on ${dashboardUrl}`);
6013
6273
  progress.complete();
6014
6274
  writeStartedPlayRun({
6015
6275
  runId: started.workflowId,
6016
- playName: started.name ?? options.target.name,
6276
+ playName: started.name ?? playName,
6017
6277
  status: started.status,
6018
6278
  statusUrl: started.statusUrl,
6019
6279
  dashboardUrl: started.dashboardUrl ?? dashboardUrl,
@@ -7876,54 +8136,6 @@ async function syncSdkSkillsIfNeeded(baseUrl) {
7876
8136
  writeSdkSkillsStatusLine("SDK skills are up to date.");
7877
8137
  }
7878
8138
 
7879
- // src/cli/trace.ts
7880
- var cliTraceStartedAt = Date.now();
7881
- function isTruthyEnv(value) {
7882
- return value === "1" || value === "true" || value === "yes";
7883
- }
7884
- function isCliTraceEnabled() {
7885
- return isTruthyEnv(process.env.DEEPLINE_CLI_TRACE);
7886
- }
7887
- function recordCliTrace(event) {
7888
- if (!isCliTraceEnabled()) {
7889
- return;
7890
- }
7891
- const now = Date.now();
7892
- const payload = {
7893
- ts: now,
7894
- source: "cli",
7895
- sinceStartMs: now - cliTraceStartedAt,
7896
- ...event
7897
- };
7898
- process.stderr.write(`[cli-trace] ${JSON.stringify(payload)}
7899
- `);
7900
- }
7901
- async function traceCliSpan(phase, fields, run) {
7902
- if (!isCliTraceEnabled()) {
7903
- return run();
7904
- }
7905
- const startedAt = Date.now();
7906
- try {
7907
- const result = await run();
7908
- recordCliTrace({
7909
- phase,
7910
- ms: Date.now() - startedAt,
7911
- ok: true,
7912
- ...fields
7913
- });
7914
- return result;
7915
- } catch (error) {
7916
- recordCliTrace({
7917
- phase,
7918
- ms: Date.now() - startedAt,
7919
- ok: false,
7920
- error: error instanceof Error ? error.message : String(error),
7921
- ...fields
7922
- });
7923
- throw error;
7924
- }
7925
- }
7926
-
7927
8139
  // src/cli/index.ts
7928
8140
  function shouldPrintStartupPhase() {
7929
8141
  if (process.argv.includes("--json")) {
@@ -7934,6 +8146,12 @@ function shouldPrintStartupPhase() {
7934
8146
  const subcommand = args[1];
7935
8147
  return (command === "play" || command === "plays") && subcommand === "run";
7936
8148
  }
8149
+ function shouldDeferSkillsSyncForCommand() {
8150
+ const args = process.argv.slice(2);
8151
+ const command = args[0];
8152
+ const subcommand = args[1];
8153
+ return (command === "play" || command === "plays") && subcommand === "run" && args.includes("--json");
8154
+ }
7937
8155
  async function main() {
7938
8156
  const mainStartedAt = Date.now();
7939
8157
  recordCliTrace({
@@ -7978,11 +8196,13 @@ Output:
7978
8196
  if (printStartupPhase) {
7979
8197
  progress?.phase("checking sdk skills");
7980
8198
  }
7981
- await traceCliSpan(
7982
- "cli.sdk_skills_sync",
7983
- { baseUrl },
7984
- () => syncSdkSkillsIfNeeded(baseUrl)
7985
- );
8199
+ if (!shouldDeferSkillsSyncForCommand()) {
8200
+ await traceCliSpan(
8201
+ "cli.sdk_skills_sync",
8202
+ { baseUrl },
8203
+ () => syncSdkSkillsIfNeeded(baseUrl)
8204
+ );
8205
+ }
7986
8206
  });
7987
8207
  registerAuthCommands(program);
7988
8208
  registerToolsCommands(program);