deepline 0.3.71 → 0.3.72

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
@@ -1214,7 +1214,7 @@ var SDK_RELEASE = {
1214
1214
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1215
1215
  // getters keep their established compatibility behavior.
1216
1216
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1217
- version: "0.3.71",
1217
+ version: "0.3.72",
1218
1218
  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.",
1219
1219
  packageCapabilities: {
1220
1220
  updatePreferences: 1
@@ -3554,6 +3554,133 @@ function decodePlayRunPublicStatus(value) {
3554
3554
  }
3555
3555
  }
3556
3556
 
3557
+ // ../play-runtime/log-provenance.ts
3558
+ var LOG_LEVELS = [
3559
+ "debug",
3560
+ "info",
3561
+ "warn",
3562
+ "error"
3563
+ ];
3564
+ var LOG_LEVEL_RANK = {
3565
+ debug: 0,
3566
+ info: 1,
3567
+ warn: 2,
3568
+ error: 3
3569
+ };
3570
+ var LOG_PROVENANCE_CLASSES = [
3571
+ "user",
3572
+ "lifecycle",
3573
+ "replay",
3574
+ "infra",
3575
+ "diagnostic",
3576
+ "receipt"
3577
+ ];
3578
+ var LOG_PROVENANCE_POLICY = {
3579
+ user: { watch: true, ui: true, debug: true },
3580
+ lifecycle: { watch: true, ui: true, debug: true },
3581
+ replay: { watch: false, ui: false, debug: true },
3582
+ infra: { watch: false, ui: false, debug: true },
3583
+ diagnostic: { watch: true, ui: true, debug: true },
3584
+ receipt: { watch: false, ui: false, debug: true }
3585
+ };
3586
+ function logProvenanceReaches(provenance, surface) {
3587
+ return LOG_PROVENANCE_POLICY[provenance][surface];
3588
+ }
3589
+ var PROVENANCE_SENTINEL = "";
3590
+ var PROVENANCE_PREFIX = `${PROVENANCE_SENTINEL}prov:`;
3591
+ function logLevelReaches(level, minimum) {
3592
+ return LOG_LEVEL_RANK[level] >= LOG_LEVEL_RANK[minimum];
3593
+ }
3594
+ function parseLogLevel(value) {
3595
+ const normalized = value.trim().toLowerCase();
3596
+ return LOG_LEVELS.includes(normalized) ? normalized : null;
3597
+ }
3598
+ function readProvenanceTag(line) {
3599
+ if (!line.startsWith(PROVENANCE_PREFIX)) {
3600
+ return { provenance: null, line };
3601
+ }
3602
+ const end = line.indexOf(PROVENANCE_SENTINEL, PROVENANCE_PREFIX.length);
3603
+ if (end === -1) {
3604
+ return { provenance: null, line };
3605
+ }
3606
+ const candidate = line.slice(PROVENANCE_PREFIX.length, end);
3607
+ const provenance = LOG_PROVENANCE_CLASSES.includes(candidate) ? candidate : null;
3608
+ return { provenance, line: line.slice(end + 1) };
3609
+ }
3610
+ function stripProvenanceTag(line) {
3611
+ return readProvenanceTag(line).line;
3612
+ }
3613
+ function classifyLegacyLogLine(line) {
3614
+ const message = stripLeadingTimestamp(line);
3615
+ if (/recovered (?:from checkpoint|response from checkpoint)/i.test(message)) {
3616
+ return "replay";
3617
+ }
3618
+ if (/^\[perf\] runtime receipt\b/i.test(message)) {
3619
+ return "receipt";
3620
+ }
3621
+ if (/^\[perf\] runtime (?:map|state)\b/i.test(message) || /\[worker\] picked up run\b/.test(message) || /\[worker\] heartbeat\b/.test(message) || /\[worker\] progress completedRows=\d+ totalRows=\d+ rowUpdates=\d+/.test(
3622
+ message
3623
+ ) || /\[worker\] step started\b/.test(message) || /\[worker\] Preparing run files\b/.test(message) || /\[worker\] Run files ready\b/.test(message) || /\[worker\] Runtime ready\b/.test(message) || /\[worker\] Sandbox (?:starting|create start|create done|workspace ready|upload start|runner uploaded)\b/.test(
3624
+ message
3625
+ ) || /^\[event\] play\.step\.progress\b/.test(message) || /^\[event\] play\.run\.snapshot\b/.test(message) || /^\[event\] play\.sheet\.summary\b/.test(message)) {
3626
+ return "infra";
3627
+ }
3628
+ if (/^\[warn\]/i.test(message) || /^\[error\]/i.test(message) || /^\[runtime\.[a-z_]*(?:failure|error)\]/i.test(message)) {
3629
+ return "diagnostic";
3630
+ }
3631
+ return "user";
3632
+ }
3633
+ function classifyLogLine(line) {
3634
+ const tagged = readProvenanceTag(line);
3635
+ const provenance = tagged.provenance ?? classifyLegacyLogLine(tagged.line);
3636
+ if (tagged.provenance !== null) {
3637
+ return {
3638
+ provenance,
3639
+ level: inferLogLevel(provenance, tagged.line),
3640
+ line: tagged.line
3641
+ };
3642
+ }
3643
+ return {
3644
+ provenance,
3645
+ level: inferLogLevel(provenance, tagged.line),
3646
+ line: tagged.line
3647
+ };
3648
+ }
3649
+ function inferLogLevel(provenance, line) {
3650
+ const message = stripLeadingTimestamp(line);
3651
+ if (/^\[info\]/i.test(message)) {
3652
+ return "info";
3653
+ }
3654
+ if (/^\[debug\]/i.test(message)) {
3655
+ return "debug";
3656
+ }
3657
+ if (/^\[console\.error\]/i.test(message) || /^\[error\]/i.test(message)) {
3658
+ return "error";
3659
+ }
3660
+ if (/^\[console\.warn\]/i.test(message) || /^\[warn\]/i.test(message)) {
3661
+ return "warn";
3662
+ }
3663
+ if (/^\[console\.debug\]/i.test(message)) {
3664
+ return "debug";
3665
+ }
3666
+ if (provenance === "replay" || provenance === "infra" || provenance === "receipt") {
3667
+ return "debug";
3668
+ }
3669
+ if (provenance === "diagnostic") {
3670
+ return "warn";
3671
+ }
3672
+ return "info";
3673
+ }
3674
+ function stripLeadingTimestamp(line) {
3675
+ const match = line.match(/^\[([^\]]+)\]\s*([\s\S]*)$/);
3676
+ if (!match) {
3677
+ return line;
3678
+ }
3679
+ const inner = match[1] ?? "";
3680
+ const isTimestamp = !Number.isNaN(new Date(inner).getTime());
3681
+ return isTimestamp ? match[2] ?? line : line;
3682
+ }
3683
+
3557
3684
  // ../play-runtime/run-snapshot-stream.ts
3558
3685
  function normalizePlayRunLiveStatus(value) {
3559
3686
  return normalizePlayRunLifecycleStatus(value);
@@ -3626,7 +3753,9 @@ function buildSnapshotFromLedger(snapshot) {
3626
3753
  finishedAt: snapshot.finishedAt ?? null,
3627
3754
  durationMs: snapshot.durationMs ?? null,
3628
3755
  updatedAt: snapshot.updatedAt ?? snapshot.finishedAt ?? snapshot.startedAt ?? null,
3629
- logs: snapshot.logTail,
3756
+ // This snapshot is public SDK/API transport. Keep the historical plain
3757
+ // timestamp-prefixed text while provenance remains runtime metadata.
3758
+ logs: snapshot.logTail.map(stripProvenanceTag),
3630
3759
  totalLogCount: snapshot.totalLogCount,
3631
3760
  ...snapshot.logsTruncated ? { logsTruncated: true } : {},
3632
3761
  activeArtifactTableNamespace: snapshot.activeArtifactTableNamespace ?? null,
@@ -15199,7 +15328,7 @@ var PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
15199
15328
  " fetch(key: string, url: string | URL, init?: RequestInit & { headers?: HeadersInit & { 'Idempotency-Key'?: string; 'X-Idempotency-Key'?: string }; auth?: SecretAuthInput }, options?: FetchOptions): Promise<PlayFetchResponse>;",
15200
15329
  " secrets: { get(name: string): SecretPromise; bearer(secret: string | SecretPromise | SecretHandle): SecretAuth; header(header: string, secret: string | SecretPromise | SecretHandle): SecretAuth };",
15201
15330
  ` runPlay<TOutput = unknown>(key: string, playRef: ${cloudReferenceType("ctx.runPlay.playRef")}, input: ${cloudReferenceType("ctx.runPlay.input")}, options: PlayCallOptions): Promise<TOutput>;`,
15202
- " log(message: string): void;",
15331
+ " log(message: string, options?: { level?: 'debug' | 'info' | 'warn' | 'error' }): void;",
15203
15332
  ` sleep(ms: ${cloudReferenceType("ctx.sleep.ms")}): Promise<void>;`,
15204
15333
  "}",
15205
15334
  "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'] };",
@@ -16749,77 +16878,6 @@ function isInternalGlueStepId(stepId) {
16749
16878
  return typeof stepId === "string" && stepId.startsWith(INTERNAL_GLUE_NODE_ID_PREFIX);
16750
16879
  }
16751
16880
 
16752
- // ../play-runtime/log-provenance.ts
16753
- var LOG_PROVENANCE_CLASSES = [
16754
- "user",
16755
- "lifecycle",
16756
- "replay",
16757
- "infra",
16758
- "diagnostic",
16759
- "receipt"
16760
- ];
16761
- var LOG_PROVENANCE_POLICY = {
16762
- user: { watch: true, ui: true, debug: true },
16763
- lifecycle: { watch: true, ui: true, debug: true },
16764
- replay: { watch: false, ui: false, debug: true },
16765
- infra: { watch: false, ui: false, debug: true },
16766
- diagnostic: { watch: true, ui: true, debug: true },
16767
- receipt: { watch: false, ui: false, debug: true }
16768
- };
16769
- function logProvenanceReaches(provenance, surface) {
16770
- return LOG_PROVENANCE_POLICY[provenance][surface];
16771
- }
16772
- var PROVENANCE_SENTINEL = "";
16773
- var PROVENANCE_PREFIX = `${PROVENANCE_SENTINEL}prov:`;
16774
- function readProvenanceTag(line) {
16775
- if (!line.startsWith(PROVENANCE_PREFIX)) {
16776
- return { provenance: null, line };
16777
- }
16778
- const end = line.indexOf(PROVENANCE_SENTINEL, PROVENANCE_PREFIX.length);
16779
- if (end === -1) {
16780
- return { provenance: null, line };
16781
- }
16782
- const candidate = line.slice(PROVENANCE_PREFIX.length, end);
16783
- const provenance = LOG_PROVENANCE_CLASSES.includes(candidate) ? candidate : null;
16784
- return { provenance, line: line.slice(end + 1) };
16785
- }
16786
- function classifyLegacyLogLine(line) {
16787
- const message = stripLeadingTimestamp(line);
16788
- if (/recovered (?:from checkpoint|response from checkpoint)/i.test(message)) {
16789
- return "replay";
16790
- }
16791
- if (/^\[perf\] runtime receipt\b/i.test(message)) {
16792
- return "receipt";
16793
- }
16794
- if (/^\[perf\] runtime (?:map|state)\b/i.test(message) || /\[worker\] picked up run\b/.test(message) || /\[worker\] heartbeat\b/.test(message) || /\[worker\] progress completedRows=\d+ totalRows=\d+ rowUpdates=\d+/.test(
16795
- message
16796
- ) || /\[worker\] step started\b/.test(message) || /\[worker\] Preparing run files\b/.test(message) || /\[worker\] Run files ready\b/.test(message) || /\[worker\] Runtime ready\b/.test(message) || /\[worker\] Sandbox (?:starting|create start|create done|workspace ready|upload start|runner uploaded)\b/.test(
16797
- message
16798
- ) || /^\[event\] play\.step\.progress\b/.test(message) || /^\[event\] play\.run\.snapshot\b/.test(message) || /^\[event\] play\.sheet\.summary\b/.test(message)) {
16799
- return "infra";
16800
- }
16801
- if (/^\[warn\]/i.test(message) || /^\[error\]/i.test(message) || /^\[runtime\.[a-z_]*(?:failure|error)\]/i.test(message)) {
16802
- return "diagnostic";
16803
- }
16804
- return "user";
16805
- }
16806
- function classifyLogLine(line) {
16807
- const tagged = readProvenanceTag(line);
16808
- if (tagged.provenance !== null) {
16809
- return { provenance: tagged.provenance, line: tagged.line };
16810
- }
16811
- return { provenance: classifyLegacyLogLine(tagged.line), line: tagged.line };
16812
- }
16813
- function stripLeadingTimestamp(line) {
16814
- const match = line.match(/^\[([^\]]+)\]\s*([\s\S]*)$/);
16815
- if (!match) {
16816
- return line;
16817
- }
16818
- const inner = match[1] ?? "";
16819
- const isTimestamp = !Number.isNaN(new Date(inner).getTime());
16820
- return isTimestamp ? match[2] ?? line : line;
16821
- }
16822
-
16823
16881
  // ../play-runtime/fixture-behavior.ts
16824
16882
  var FIXTURE_BEHAVIOR_VERSION = 1;
16825
16883
  var FIXTURE_BEHAVIOR_RESPONSE_VERSION = 2;
@@ -18247,7 +18305,11 @@ var TERMINAL_PLAY_STATUSES2 = /* @__PURE__ */ new Set([
18247
18305
  var PLAY_START_TRANSIENT_RETRY_DELAYS_MS = [500, 1500];
18248
18306
  var PLAY_PROGRESS_HEARTBEAT_INTERVAL_MS = 15e3;
18249
18307
  var PLAY_STATUS_HEARTBEAT_INTERVAL_MS = 15e3;
18250
- function watchSurfaceReaches(state, provenance) {
18308
+ function watchSurfaceReaches(state, provenance, level) {
18309
+ const minimumLevel = state.logLevel ?? (state.verbose ? "debug" : "info");
18310
+ if (!logLevelReaches(level, minimumLevel)) {
18311
+ return false;
18312
+ }
18251
18313
  if (logProvenanceReaches(provenance, "watch")) {
18252
18314
  return true;
18253
18315
  }
@@ -18442,7 +18504,7 @@ function emitLiveDebugTableHints(input2) {
18442
18504
  process.stdout
18443
18505
  );
18444
18506
  }
18445
- if (!watchSurfaceReaches(input2.state, "infra")) {
18507
+ if (!watchSurfaceReaches(input2.state, "infra", "debug")) {
18446
18508
  return;
18447
18509
  }
18448
18510
  const tableNamespace = extractTableNamespaceFromLiveEvent(input2.event);
@@ -18545,7 +18607,7 @@ function getStepTransitionLineFromLiveEvent(event, state) {
18545
18607
  if (isTerminal) {
18546
18608
  state.terminalStepIds.add(stepId);
18547
18609
  }
18548
- if (isReplayEcho && !watchSurfaceReaches(state, "replay")) {
18610
+ if (isReplayEcho && !watchSurfaceReaches(state, "replay", "debug")) {
18549
18611
  return null;
18550
18612
  }
18551
18613
  return `step ${label}: ${status}`;
@@ -18949,6 +19011,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
18949
19011
  lastLogIndex: 0,
18950
19012
  emittedRunnerStarted: false,
18951
19013
  verbose: input2.verboseLogs === true,
19014
+ logLevel: input2.logLevel ?? "info",
18952
19015
  lastProgressSignature: null,
18953
19016
  lastProgressHeartbeatAt: 0,
18954
19017
  lastStatusHeartbeatAt: 0
@@ -19327,6 +19390,9 @@ function formatPlayLogLine(rawLine, status, state) {
19327
19390
  const message = timestampMatch?.[2] ?? line;
19328
19391
  const prefix = timestamp ? `${timestamp} ` : "";
19329
19392
  if (/\[worker\] picked up run\b/.test(message)) {
19393
+ if (!logLevelReaches("info", state.logLevel ?? "info")) {
19394
+ return null;
19395
+ }
19330
19396
  if (state.emittedRunnerStarted) {
19331
19397
  return null;
19332
19398
  }
@@ -19343,6 +19409,9 @@ function formatPlayLogLine(rawLine, status, state) {
19343
19409
  /^Starting map over (\d+) items with (\d+) fields \(key: ([^;]+); (\d+) already satisfied; (\d+) pending\)$/
19344
19410
  );
19345
19411
  if (mapStart) {
19412
+ if (!logLevelReaches("info", state.logLevel ?? "info")) {
19413
+ return null;
19414
+ }
19346
19415
  const [, rows, fields, namespace, cached, pending] = mapStart;
19347
19416
  return `${prefix}map ${sourceLabelForNamespace(namespace)}: ${formatInteger(Number(rows))} rows, ${fields} fields, ${formatInteger(Number(cached))} cached, ${formatInteger(Number(pending))} pending`;
19348
19417
  }
@@ -19350,10 +19419,13 @@ function formatPlayLogLine(rawLine, status, state) {
19350
19419
  /^Map completed: (\d+) results \((\d+) executed, (\d+) already satisfied\)$/
19351
19420
  );
19352
19421
  if (mapDone) {
19422
+ if (!logLevelReaches("info", state.logLevel ?? "info")) {
19423
+ return null;
19424
+ }
19353
19425
  const [, results, executed, cached] = mapDone;
19354
19426
  return `${prefix}done: ${formatInteger(Number(results))} results, ${formatInteger(Number(executed))} executed, ${formatInteger(Number(cached))} cached`;
19355
19427
  }
19356
- if (!watchSurfaceReaches(state, classified.provenance)) {
19428
+ if (!watchSurfaceReaches(state, classified.provenance, classified.level)) {
19357
19429
  return null;
19358
19430
  }
19359
19431
  return `${prefix}${message}`;
@@ -21089,13 +21161,12 @@ function parsePlayRunOptions(args) {
21089
21161
  const watch = !args.includes("--no-wait");
21090
21162
  let jsonOutput = watch ? args.includes("--json") : argsWantJson(args);
21091
21163
  const fullJson = args.includes("--full");
21092
- const explicitDebugLogs = args.includes("--logs") || args.some((_, index) => isBarePlayRunDebugFlag(args, index));
21093
- const emitLogs = !jsonOutput || explicitDebugLogs;
21094
21164
  const force = args.includes("--force");
21095
21165
  const forceToolRefresh = args.includes("--force-tool-refresh");
21096
21166
  const open2 = args.includes("--open");
21097
21167
  const debugMapLatency = args.includes("--debug-map-latency");
21098
- const verboseLogs = explicitDebugLogs || debugMapLatency;
21168
+ let logLevel = "info";
21169
+ let hasExplicitLogLevel = false;
21099
21170
  let waitTimeoutMs = null;
21100
21171
  let maxConcurrentExternalCalls = null;
21101
21172
  let maxConcurrentRows = null;
@@ -21116,6 +21187,23 @@ function parsePlayRunOptions(args) {
21116
21187
  input2 = parseJsonInput(args[++index]);
21117
21188
  continue;
21118
21189
  }
21190
+ if (arg === "--log-level" || arg.startsWith("--log-level=")) {
21191
+ const value = arg === "--log-level" ? args[++index] : arg.slice("--log-level=".length);
21192
+ if (!value || value.startsWith("--")) {
21193
+ throw new Error(
21194
+ "--log-level requires one of: debug, info, warn, error."
21195
+ );
21196
+ }
21197
+ const parsed = parseLogLevel(value);
21198
+ if (!parsed) {
21199
+ throw new Error(
21200
+ `Unsupported --log-level ${JSON.stringify(value)}. Use debug, info, warn, or error.`
21201
+ );
21202
+ }
21203
+ logLevel = parsed;
21204
+ hasExplicitLogLevel = true;
21205
+ continue;
21206
+ }
21119
21207
  if (arg === "--run-id-file") {
21120
21208
  const value = args[index + 1];
21121
21209
  if (!value || value.startsWith("--")) {
@@ -21294,6 +21382,17 @@ function parsePlayRunOptions(args) {
21294
21382
  "--live, --latest, and --revision-id only apply to named plays."
21295
21383
  );
21296
21384
  }
21385
+ if (debugMapLatency && logLevel === "info") logLevel = "debug";
21386
+ const usesDebugAlias = args.includes("--logs") || args.some((_, index) => isBarePlayRunDebugFlag(args, index));
21387
+ if (usesDebugAlias && hasExplicitLogLevel && logLevel !== "debug") {
21388
+ throw new Error(
21389
+ "--debug/--logs conflicts with a non-debug --log-level. Use one level selector."
21390
+ );
21391
+ }
21392
+ if (usesDebugAlias) logLevel = "debug";
21393
+ const explicitDebugLogs = usesDebugAlias || logLevel === "debug";
21394
+ const emitLogs = !jsonOutput || explicitDebugLogs || hasExplicitLogLevel;
21395
+ const verboseLogs = explicitDebugLogs || debugMapLatency;
21297
21396
  return {
21298
21397
  target: filePath ? { kind: "file", path: filePath } : { kind: "name", name: playName },
21299
21398
  input: input2,
@@ -21302,6 +21401,7 @@ function parsePlayRunOptions(args) {
21302
21401
  watch,
21303
21402
  emitLogs,
21304
21403
  verboseLogs,
21404
+ logLevel,
21305
21405
  jsonOutput,
21306
21406
  fullJson,
21307
21407
  waitTimeoutMs,
@@ -22199,6 +22299,7 @@ async function handleFileBackedRun(options, hooks) {
22199
22299
  jsonOutput: options.jsonOutput,
22200
22300
  emitLogs: options.emitLogs,
22201
22301
  verboseLogs: options.verboseLogs,
22302
+ logLevel: options.logLevel,
22202
22303
  waitTimeoutMs: options.waitTimeoutMs,
22203
22304
  open: options.open,
22204
22305
  progress,
@@ -22381,6 +22482,7 @@ async function handleNamedRun(options, hooks) {
22381
22482
  jsonOutput: options.jsonOutput,
22382
22483
  emitLogs: options.emitLogs,
22383
22484
  verboseLogs: options.verboseLogs,
22485
+ logLevel: options.logLevel,
22384
22486
  waitTimeoutMs: options.waitTimeoutMs,
22385
22487
  open: options.open,
22386
22488
  progress,
@@ -22498,12 +22600,13 @@ async function handlePlayRun(args, hooks) {
22498
22600
  function parseRunIdPositional(args, usage) {
22499
22601
  for (let index = 0; index < args.length; index += 1) {
22500
22602
  const arg = args[index];
22501
- if (arg === "--json" || arg === "--full" || arg === "--input" || arg === "--logs" || arg === "--debug" || arg === "--compact" || arg === "--log-failed" || arg === "--failed" || arg === "--limit") {
22502
- if (arg === "--limit" && args[index + 1]) {
22603
+ if (arg === "--json" || arg === "--full" || arg === "--input" || arg === "--logs" || arg === "--debug" || arg === "--compact" || arg === "--log-failed" || arg === "--failed" || arg === "--limit" || arg === "--log-level") {
22604
+ if ((arg === "--limit" || arg === "--log-level") && args[index + 1]) {
22503
22605
  index += 1;
22504
22606
  }
22505
22607
  continue;
22506
22608
  }
22609
+ if (arg.startsWith("--log-level=")) continue;
22507
22610
  if ((arg === "--out" || arg === "--reason" || arg === "--dataset") && args[index + 1]) {
22508
22611
  index += 1;
22509
22612
  continue;
@@ -22665,7 +22768,7 @@ async function handleRunsList(args) {
22665
22768
  return 0;
22666
22769
  }
22667
22770
  async function handleRunTail(args) {
22668
- const usage = "Usage: deepline runs tail <run-id> [--json | --jsonl] [--compact] [--debug]";
22771
+ const usage = "Usage: deepline runs tail <run-id> [--json | --jsonl] [--compact] [--log-level debug|info|warn|error]";
22669
22772
  let runId;
22670
22773
  try {
22671
22774
  runId = parseRunIdPositional(args, usage);
@@ -22673,6 +22776,9 @@ async function handleRunTail(args) {
22673
22776
  console.error(error instanceof Error ? error.message : usage);
22674
22777
  return 1;
22675
22778
  }
22779
+ let logLevel = "info";
22780
+ let hasExplicitLogLevel = false;
22781
+ let usesDebugAlias = false;
22676
22782
  for (let index = 0; index < args.length; index += 1) {
22677
22783
  const arg = args[index];
22678
22784
  if (arg === "--cursor") {
@@ -22681,7 +22787,28 @@ async function handleRunTail(args) {
22681
22787
  );
22682
22788
  return 1;
22683
22789
  }
22684
- if (arg.startsWith("--") && arg !== "--json" && arg !== "--jsonl" && arg !== "--compact" && arg !== "--logs" && arg !== "--debug") {
22790
+ if (arg === "--log-level" || arg.startsWith("--log-level=")) {
22791
+ const value = arg === "--log-level" ? args[++index] : arg.slice("--log-level=".length);
22792
+ if (!value || value.startsWith("--")) {
22793
+ console.error("--log-level requires one of: debug, info, warn, error.");
22794
+ return 1;
22795
+ }
22796
+ const parsed = parseLogLevel(value);
22797
+ if (!parsed) {
22798
+ console.error(
22799
+ `Unsupported --log-level ${JSON.stringify(value)}. Use debug, info, warn, or error.`
22800
+ );
22801
+ return 1;
22802
+ }
22803
+ logLevel = parsed;
22804
+ hasExplicitLogLevel = true;
22805
+ continue;
22806
+ }
22807
+ if (arg === "--logs" || arg === "--debug") {
22808
+ usesDebugAlias = true;
22809
+ continue;
22810
+ }
22811
+ if (arg.startsWith("--") && arg !== "--json" && arg !== "--jsonl" && arg !== "--compact") {
22685
22812
  console.error(`${arg} is not supported by deepline runs tail.`);
22686
22813
  return 1;
22687
22814
  }
@@ -22690,10 +22817,17 @@ async function handleRunTail(args) {
22690
22817
  console.error("--json and --jsonl cannot be used together.");
22691
22818
  return 1;
22692
22819
  }
22693
- const debug = args.includes("--logs") || args.includes("--debug");
22694
- if (args.includes("--jsonl") && debug) {
22820
+ if (usesDebugAlias && hasExplicitLogLevel && logLevel !== "debug") {
22695
22821
  console.error(
22696
- "--debug is redundant with --jsonl: JSON Lines already includes every canonical live event."
22822
+ "--debug conflicts with a non-debug --log-level. Use one level selector."
22823
+ );
22824
+ return 1;
22825
+ }
22826
+ if (usesDebugAlias) logLevel = "debug";
22827
+ const debug = logLevel === "debug";
22828
+ if (args.includes("--jsonl") && (debug || hasExplicitLogLevel)) {
22829
+ console.error(
22830
+ "--log-level cannot be combined with --jsonl: JSON Lines already includes every canonical live event."
22697
22831
  );
22698
22832
  return 1;
22699
22833
  }
@@ -22707,7 +22841,8 @@ async function handleRunTail(args) {
22707
22841
  lastProgressSignature: null,
22708
22842
  lastProgressHeartbeatAt: 0,
22709
22843
  lastStatusHeartbeatAt: 0,
22710
- verbose: debug
22844
+ verbose: debug,
22845
+ logLevel
22711
22846
  };
22712
22847
  const status = await client2.runs.tail(runId, {
22713
22848
  onEvent: jsonLines ? (event) => {
@@ -22719,8 +22854,8 @@ async function handleRunTail(args) {
22719
22854
  })}
22720
22855
  `
22721
22856
  );
22722
- } : compact || debug ? (event) => {
22723
- if (debug) {
22857
+ } : compact || debug || hasExplicitLogLevel ? (event) => {
22858
+ if (debug || hasExplicitLogLevel) {
22724
22859
  for (const line of getLogLinesFromLiveEvent(event)) {
22725
22860
  const formatted = formatPlayLogLine(
22726
22861
  line,
@@ -22755,7 +22890,7 @@ async function handleRunTail(args) {
22755
22890
  }
22756
22891
  } : void 0,
22757
22892
  // Human mode only: in --json mode emit nothing non-protocol.
22758
- onReconnect: jsonOutput && !debug ? void 0 : ({ reason }) => {
22893
+ onReconnect: jsonOutput && !debug && !hasExplicitLogLevel ? void 0 : ({ reason }) => {
22759
22894
  process.stderr.write(
22760
22895
  `[runs tail] stream ended without a terminal status; reconnecting to run ${runId} (${reason})
22761
22896
  `
@@ -22771,7 +22906,7 @@ async function handleRunTail(args) {
22771
22906
  return status.status === "failed" ? 1 : 0;
22772
22907
  }
22773
22908
  async function handleRunLogs(args) {
22774
- const usage = "Usage: deepline runs logs <run-id> [--limit 200] [--failed] [--out run.log] [--json] [--debug]";
22909
+ const usage = "Usage: deepline runs logs <run-id> [--limit 200] [--failed] [--out run.log] [--log-level debug|info|warn|error] [--json]";
22775
22910
  let runId;
22776
22911
  try {
22777
22912
  runId = parseRunIdPositional(args, usage);
@@ -22781,10 +22916,34 @@ async function handleRunLogs(args) {
22781
22916
  }
22782
22917
  let limit = 200;
22783
22918
  let outPath = null;
22919
+ let logLevel = "debug";
22920
+ let hasExplicitLogLevel = false;
22921
+ let usesDebugAlias = false;
22784
22922
  const failed = args.includes("--failed");
22785
22923
  for (let index = 0; index < args.length; index += 1) {
22786
22924
  const arg = args[index];
22787
- if (arg === "--debug" || arg === "--logs" || arg === "--json" || arg === "--failed") {
22925
+ if (arg === "--debug" || arg === "--logs") {
22926
+ usesDebugAlias = true;
22927
+ continue;
22928
+ }
22929
+ if (arg === "--json" || arg === "--failed") {
22930
+ continue;
22931
+ }
22932
+ if (arg === "--log-level" || arg.startsWith("--log-level=")) {
22933
+ const value = arg === "--log-level" ? args[++index] : arg.slice("--log-level=".length);
22934
+ if (!value || value.startsWith("--")) {
22935
+ console.error("--log-level requires one of: debug, info, warn, error.");
22936
+ return 1;
22937
+ }
22938
+ const parsed = parseLogLevel(value);
22939
+ if (!parsed) {
22940
+ console.error(
22941
+ `Unsupported --log-level ${JSON.stringify(value)}. Use debug, info, warn, or error.`
22942
+ );
22943
+ return 1;
22944
+ }
22945
+ logLevel = parsed;
22946
+ hasExplicitLogLevel = true;
22788
22947
  continue;
22789
22948
  }
22790
22949
  if (arg === "--limit" && args[index + 1]) {
@@ -22800,6 +22959,13 @@ async function handleRunLogs(args) {
22800
22959
  return 1;
22801
22960
  }
22802
22961
  }
22962
+ if (usesDebugAlias && hasExplicitLogLevel && logLevel !== "debug") {
22963
+ console.error(
22964
+ "--debug conflicts with a non-debug --log-level. Use one level selector."
22965
+ );
22966
+ return 1;
22967
+ }
22968
+ if (usesDebugAlias) logLevel = "debug";
22803
22969
  if (failed && outPath) {
22804
22970
  console.error(
22805
22971
  "--failed cannot be combined with --out. Remove --failed to export the full persisted log stream."
@@ -22809,7 +22975,7 @@ async function handleRunLogs(args) {
22809
22975
  const client2 = new DeeplineClient();
22810
22976
  if (outPath) {
22811
22977
  const result2 = await client2.runs.logs(runId, { all: true });
22812
- const logs = result2.entries;
22978
+ const logs = result2.entries.filter((line) => logLevelReaches(classifyLogLine(line).level, logLevel)).map((line) => classifyLogLine(line).line);
22813
22979
  (0, import_node_fs12.writeFileSync)(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
22814
22980
  printCommandEnvelope(
22815
22981
  {
@@ -22817,6 +22983,7 @@ async function handleRunLogs(args) {
22817
22983
  log_path: outPath,
22818
22984
  lineCount: logs.length,
22819
22985
  totalCount: result2.totalCount,
22986
+ logLevel,
22820
22987
  ...result2.logsTruncated ? { logsTruncated: true } : {},
22821
22988
  local: { log_path: outPath },
22822
22989
  render: {
@@ -22837,27 +23004,47 @@ async function handleRunLogs(args) {
22837
23004
  );
22838
23005
  return 0;
22839
23006
  }
22840
- const result = await client2.runs.logs(runId, { limit, failed });
22841
- const text = buildRunLogsText(result);
23007
+ const result = await client2.runs.logs(runId, {
23008
+ ...failed ? { limit, failed: true } : { all: logLevel !== "debug", limit }
23009
+ });
23010
+ const matchingEntries = result.entries.filter(
23011
+ (line) => logLevelReaches(classifyLogLine(line).level, logLevel)
23012
+ );
23013
+ const entries = failed ? matchingEntries : matchingEntries.slice(-limit);
23014
+ const matchingEntriesTruncated = !failed && matchingEntries.length > limit;
23015
+ const filteredResult = {
23016
+ ...result,
23017
+ entries,
23018
+ returnedCount: entries.length,
23019
+ truncated: result.truncated || matchingEntriesTruncated,
23020
+ hasMore: result.hasMore || matchingEntriesTruncated,
23021
+ view: failed ? result.view : "tail",
23022
+ next: {
23023
+ ...result.next ?? {},
23024
+ logs: `deepline runs logs ${result.runId} --out run.log --log-level ${logLevel} --json`
23025
+ }
23026
+ };
23027
+ const text = buildRunLogsText(filteredResult);
22842
23028
  printCommandEnvelope(
22843
23029
  {
22844
23030
  runId: result.runId,
22845
23031
  totalCount: result.totalCount,
22846
- returnedCount: result.returnedCount,
23032
+ returnedCount: entries.length,
22847
23033
  firstSequence: result.firstSequence,
22848
23034
  lastSequence: result.lastSequence,
22849
- truncated: result.truncated,
22850
- hasMore: result.hasMore,
23035
+ truncated: filteredResult.truncated,
23036
+ hasMore: filteredResult.hasMore,
23037
+ logLevel,
22851
23038
  ...result.logsTruncated ? { logsTruncated: true } : {},
22852
- entries: result.entries,
22853
- ...result.view ? { view: result.view } : {},
23039
+ entries,
23040
+ ...filteredResult.view ? { view: filteredResult.view } : {},
22854
23041
  ...result.association ? { association: result.association } : {},
22855
23042
  ...result.warning ? { warning: result.warning } : {},
22856
23043
  next: {
22857
23044
  ...result.next ?? {},
22858
- export: `deepline runs logs ${result.runId} --out run.log --json`
23045
+ export: `deepline runs logs ${result.runId} --out run.log --log-level ${logLevel} --json`
22859
23046
  },
22860
- render: { sections: [{ title: "run logs", lines: result.entries }] }
23047
+ render: { sections: [{ title: "run logs", lines: entries }] }
22861
23048
  },
22862
23049
  {
22863
23050
  json: argsWantJson(args),
@@ -22867,7 +23054,7 @@ async function handleRunLogs(args) {
22867
23054
  return 0;
22868
23055
  }
22869
23056
  function buildRunLogsText(result) {
22870
- const lines = [...result.entries];
23057
+ const lines = result.entries.map((line) => classifyLogLine(line).line);
22871
23058
  if (result.warning) {
22872
23059
  if (lines.length > 0) lines.push("");
22873
23060
  lines.push(`warning: ${result.warning}`);
@@ -24251,6 +24438,7 @@ Examples:
24251
24438
  deepline plays run long-background-play --no-wait
24252
24439
  deepline plays run long-background-play --run-id-file ./run-id.json
24253
24440
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
24441
+ deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --log-level debug
24254
24442
  deepline plays run my.play.ts --profile absurd
24255
24443
  deepline plays run my.play.ts --max-concurrent-external-calls 20
24256
24444
  deepline plays run my.play.ts --input @input.json --json
@@ -24270,9 +24458,12 @@ Examples:
24270
24458
  ).option("--watch", "Compatibility alias; run waits by default").option("--wait", "Compatibility alias; run waits by default").option("--no-wait", "Start the run and return immediately").option(
24271
24459
  "--run-id-file <path>",
24272
24460
  "Atomically write the accepted run id to a new JSON file"
24273
- ).option("--logs", "Compatibility alias for --debug").option(
24461
+ ).option("--logs", "Compatibility alias for --log-level debug").option(
24274
24462
  "--debug [value]",
24275
- "Stream complete customer-safe runtime logs when passed without a value; otherwise pass input.debug"
24463
+ "Compatibility alias for --log-level debug when bare; --debug <value> remains legacy Play input.debug"
24464
+ ).option(
24465
+ "--log-level <level>",
24466
+ "Minimum live log severity: debug, info (default), warn, or error"
24276
24467
  ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option(
24277
24468
  "--force-tool-refresh",
24278
24469
  "Refresh completed tool receipts; may repeat billed provider calls"
@@ -24322,6 +24513,7 @@ Pass-through input flags:
24322
24513
  ...options.watch || options.wait ? ["--watch"] : [],
24323
24514
  ...options.logs ? ["--logs"] : [],
24324
24515
  ...options.debug === true ? ["--debug"] : typeof options.debug === "string" ? ["--debug", options.debug] : [],
24516
+ ...options.logLevel ? ["--log-level", options.logLevel] : [],
24325
24517
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
24326
24518
  ...options.force ? ["--force"] : [],
24327
24519
  ...options.forceToolRefresh ? ["--force-tool-refresh"] : [],
@@ -24630,10 +24822,15 @@ Concepts:
24630
24822
  tail reads the live stream. logs fetches persisted logs after the fact.
24631
24823
  stop mutates cloud state by requesting cancellation.
24632
24824
 
24825
+ Debug a run:
24826
+ Active: deepline runs tail <run-id> --log-level debug
24827
+ Historical: deepline runs logs <run-id> --out run.log --log-level debug --json
24828
+ Full state: deepline runs get <run-id> --full --json
24829
+
24633
24830
  Examples:
24634
24831
  deepline runs get play/my-play/run/20260501t000000-000 --json
24635
24832
  deepline runs tail play/my-play/run/20260501t000000-000
24636
- deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
24833
+ deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --log-level debug --json
24637
24834
  deepline runs list --play my-play --status failed --json
24638
24835
  deepline runs list --status running --json
24639
24836
  deepline runs stop play/my-play/run/20260501t000000-000 --reason "stale lock" --json
@@ -24739,13 +24936,15 @@ Notes:
24739
24936
  logs for persisted log history. In human output, --compact prints deduplicated
24740
24937
  step transitions and progress instead of the full event stream. --json emits
24741
24938
  one terminal package. --jsonl emits canonical live events as JSON Lines and
24742
- ends with the same compact package shape as runs get --json. Use --debug
24743
- (or legacy --logs) to also print customer-safe runtime log lines to stderr.
24939
+ ends with the same compact package shape as runs get --json. --log-level
24940
+ filters the rendered customer-safe runtime log lines; debug includes runtime
24941
+ and receipt diagnostics and writes them to stderr alongside JSON output.
24744
24942
 
24745
24943
  Examples:
24746
24944
  deepline runs tail play/my-play/run/20260501t000000-000
24747
24945
  deepline runs tail play/my-play/run/20260501t000000-000 --compact
24748
- deepline runs tail play/my-play/run/20260501t000000-000 --debug
24946
+ deepline runs tail play/my-play/run/20260501t000000-000 --log-level debug
24947
+ deepline runs tail play/my-play/run/20260501t000000-000 --log-level error
24749
24948
  deepline runs tail play/my-play/run/20260501t000000-000 --jsonl
24750
24949
  `
24751
24950
  ).option("--json", "Emit one terminal JSON package after the run completes").option(
@@ -24754,9 +24953,9 @@ Examples:
24754
24953
  ).option(
24755
24954
  "--compact",
24756
24955
  "Show deduplicated human step transitions and progress"
24757
- ).option("--logs", "Compatibility alias for --debug").option(
24758
- "--debug",
24759
- "Print customer-safe runtime log lines to stderr while tailing"
24956
+ ).option("--logs", "Compatibility alias for --log-level debug").option("--debug", "Compatibility alias for --log-level debug").option(
24957
+ "--log-level <level>",
24958
+ "Minimum severity: debug, info (default), warn, or error"
24760
24959
  ).action(async (runId, options) => {
24761
24960
  process.exitCode = await handleRunTail([
24762
24961
  runId,
@@ -24764,7 +24963,8 @@ Examples:
24764
24963
  ...options.jsonl ? ["--jsonl"] : [],
24765
24964
  ...options.compact ? ["--compact"] : [],
24766
24965
  ...options.logs ? ["--logs"] : [],
24767
- ...options.debug ? ["--debug"] : []
24966
+ ...options.debug ? ["--debug"] : [],
24967
+ ...options.logLevel ? ["--log-level", options.logLevel] : []
24768
24968
  ]);
24769
24969
  });
24770
24970
  runs.command("logs <runId>").description("Fetch persisted logs for a play run.").addHelpText(
@@ -24772,29 +24972,30 @@ Examples:
24772
24972
  `
24773
24973
  Notes:
24774
24974
  Prints a bounded recent log preview by default. Use --out to write the full
24775
- persisted log stream to a local file. --debug (or legacy --logs) is accepted
24776
- for script parity; this command already returns the unfiltered durable stream.
24975
+ retained stream to a local file. Use --log-level to filter by severity;
24976
+ default debug preserves the complete historical stream.
24777
24977
 
24778
24978
  Examples:
24779
24979
  deepline runs logs play/my-play/run/20260501t000000-000
24780
24980
  deepline runs logs play/my-play/run/20260501t000000-000 --limit 500
24781
24981
  deepline runs logs play/my-play/run/20260501t000000-000 --failed --json
24782
- deepline runs logs play/my-play/run/20260501t000000-000 --debug
24783
- deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
24982
+ deepline runs logs play/my-play/run/20260501t000000-000 --log-level error
24983
+ deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --log-level debug --json
24784
24984
  `
24785
24985
  ).option(
24786
24986
  "--limit <count>",
24787
24987
  "Maximum recent log lines to print without --out",
24788
24988
  "200"
24789
- ).option("--out <path>", "Write the full persisted log stream to a file").option("--failed", "Show the bounded terminal-failure log window").option("--logs", "Compatibility alias for --debug").option(
24790
- "--debug",
24791
- "Explicitly request the same persisted log view (no provenance filtering)"
24792
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
24989
+ ).option("--out <path>", "Write the full retained log stream to a file").option("--failed", "Show the bounded terminal-failure log window").option(
24990
+ "--log-level <level>",
24991
+ "Minimum severity: debug (default), info, warn, or error"
24992
+ ).option("--logs", "Compatibility alias for --log-level debug").option("--debug", "Compatibility alias for --log-level debug").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
24793
24993
  process.exitCode = await handleRunLogs([
24794
24994
  runId,
24795
24995
  ...options.limit ? ["--limit", options.limit] : [],
24796
24996
  ...options.out ? ["--out", options.out] : [],
24797
24997
  ...options.failed ? ["--failed"] : [],
24998
+ ...options.logLevel ? ["--log-level", options.logLevel] : [],
24798
24999
  ...options.logs ? ["--logs"] : [],
24799
25000
  ...options.debug ? ["--debug"] : [],
24800
25001
  ...options.json ? ["--json"] : []