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.
@@ -1199,7 +1199,7 @@ var SDK_RELEASE = {
1199
1199
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1200
1200
  // getters keep their established compatibility behavior.
1201
1201
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1202
- version: "0.3.71",
1202
+ version: "0.3.72",
1203
1203
  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.",
1204
1204
  packageCapabilities: {
1205
1205
  updatePreferences: 1
@@ -3539,6 +3539,133 @@ function decodePlayRunPublicStatus(value) {
3539
3539
  }
3540
3540
  }
3541
3541
 
3542
+ // ../play-runtime/log-provenance.ts
3543
+ var LOG_LEVELS = [
3544
+ "debug",
3545
+ "info",
3546
+ "warn",
3547
+ "error"
3548
+ ];
3549
+ var LOG_LEVEL_RANK = {
3550
+ debug: 0,
3551
+ info: 1,
3552
+ warn: 2,
3553
+ error: 3
3554
+ };
3555
+ var LOG_PROVENANCE_CLASSES = [
3556
+ "user",
3557
+ "lifecycle",
3558
+ "replay",
3559
+ "infra",
3560
+ "diagnostic",
3561
+ "receipt"
3562
+ ];
3563
+ var LOG_PROVENANCE_POLICY = {
3564
+ user: { watch: true, ui: true, debug: true },
3565
+ lifecycle: { watch: true, ui: true, debug: true },
3566
+ replay: { watch: false, ui: false, debug: true },
3567
+ infra: { watch: false, ui: false, debug: true },
3568
+ diagnostic: { watch: true, ui: true, debug: true },
3569
+ receipt: { watch: false, ui: false, debug: true }
3570
+ };
3571
+ function logProvenanceReaches(provenance, surface) {
3572
+ return LOG_PROVENANCE_POLICY[provenance][surface];
3573
+ }
3574
+ var PROVENANCE_SENTINEL = "";
3575
+ var PROVENANCE_PREFIX = `${PROVENANCE_SENTINEL}prov:`;
3576
+ function logLevelReaches(level, minimum) {
3577
+ return LOG_LEVEL_RANK[level] >= LOG_LEVEL_RANK[minimum];
3578
+ }
3579
+ function parseLogLevel(value) {
3580
+ const normalized = value.trim().toLowerCase();
3581
+ return LOG_LEVELS.includes(normalized) ? normalized : null;
3582
+ }
3583
+ function readProvenanceTag(line) {
3584
+ if (!line.startsWith(PROVENANCE_PREFIX)) {
3585
+ return { provenance: null, line };
3586
+ }
3587
+ const end = line.indexOf(PROVENANCE_SENTINEL, PROVENANCE_PREFIX.length);
3588
+ if (end === -1) {
3589
+ return { provenance: null, line };
3590
+ }
3591
+ const candidate = line.slice(PROVENANCE_PREFIX.length, end);
3592
+ const provenance = LOG_PROVENANCE_CLASSES.includes(candidate) ? candidate : null;
3593
+ return { provenance, line: line.slice(end + 1) };
3594
+ }
3595
+ function stripProvenanceTag(line) {
3596
+ return readProvenanceTag(line).line;
3597
+ }
3598
+ function classifyLegacyLogLine(line) {
3599
+ const message = stripLeadingTimestamp(line);
3600
+ if (/recovered (?:from checkpoint|response from checkpoint)/i.test(message)) {
3601
+ return "replay";
3602
+ }
3603
+ if (/^\[perf\] runtime receipt\b/i.test(message)) {
3604
+ return "receipt";
3605
+ }
3606
+ 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(
3607
+ message
3608
+ ) || /\[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(
3609
+ message
3610
+ ) || /^\[event\] play\.step\.progress\b/.test(message) || /^\[event\] play\.run\.snapshot\b/.test(message) || /^\[event\] play\.sheet\.summary\b/.test(message)) {
3611
+ return "infra";
3612
+ }
3613
+ if (/^\[warn\]/i.test(message) || /^\[error\]/i.test(message) || /^\[runtime\.[a-z_]*(?:failure|error)\]/i.test(message)) {
3614
+ return "diagnostic";
3615
+ }
3616
+ return "user";
3617
+ }
3618
+ function classifyLogLine(line) {
3619
+ const tagged = readProvenanceTag(line);
3620
+ const provenance = tagged.provenance ?? classifyLegacyLogLine(tagged.line);
3621
+ if (tagged.provenance !== null) {
3622
+ return {
3623
+ provenance,
3624
+ level: inferLogLevel(provenance, tagged.line),
3625
+ line: tagged.line
3626
+ };
3627
+ }
3628
+ return {
3629
+ provenance,
3630
+ level: inferLogLevel(provenance, tagged.line),
3631
+ line: tagged.line
3632
+ };
3633
+ }
3634
+ function inferLogLevel(provenance, line) {
3635
+ const message = stripLeadingTimestamp(line);
3636
+ if (/^\[info\]/i.test(message)) {
3637
+ return "info";
3638
+ }
3639
+ if (/^\[debug\]/i.test(message)) {
3640
+ return "debug";
3641
+ }
3642
+ if (/^\[console\.error\]/i.test(message) || /^\[error\]/i.test(message)) {
3643
+ return "error";
3644
+ }
3645
+ if (/^\[console\.warn\]/i.test(message) || /^\[warn\]/i.test(message)) {
3646
+ return "warn";
3647
+ }
3648
+ if (/^\[console\.debug\]/i.test(message)) {
3649
+ return "debug";
3650
+ }
3651
+ if (provenance === "replay" || provenance === "infra" || provenance === "receipt") {
3652
+ return "debug";
3653
+ }
3654
+ if (provenance === "diagnostic") {
3655
+ return "warn";
3656
+ }
3657
+ return "info";
3658
+ }
3659
+ function stripLeadingTimestamp(line) {
3660
+ const match = line.match(/^\[([^\]]+)\]\s*([\s\S]*)$/);
3661
+ if (!match) {
3662
+ return line;
3663
+ }
3664
+ const inner = match[1] ?? "";
3665
+ const isTimestamp = !Number.isNaN(new Date(inner).getTime());
3666
+ return isTimestamp ? match[2] ?? line : line;
3667
+ }
3668
+
3542
3669
  // ../play-runtime/run-snapshot-stream.ts
3543
3670
  function normalizePlayRunLiveStatus(value) {
3544
3671
  return normalizePlayRunLifecycleStatus(value);
@@ -3611,7 +3738,9 @@ function buildSnapshotFromLedger(snapshot) {
3611
3738
  finishedAt: snapshot.finishedAt ?? null,
3612
3739
  durationMs: snapshot.durationMs ?? null,
3613
3740
  updatedAt: snapshot.updatedAt ?? snapshot.finishedAt ?? snapshot.startedAt ?? null,
3614
- logs: snapshot.logTail,
3741
+ // This snapshot is public SDK/API transport. Keep the historical plain
3742
+ // timestamp-prefixed text while provenance remains runtime metadata.
3743
+ logs: snapshot.logTail.map(stripProvenanceTag),
3615
3744
  totalLogCount: snapshot.totalLogCount,
3616
3745
  ...snapshot.logsTruncated ? { logsTruncated: true } : {},
3617
3746
  activeArtifactTableNamespace: snapshot.activeArtifactTableNamespace ?? null,
@@ -15254,7 +15383,7 @@ var PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
15254
15383
  " fetch(key: string, url: string | URL, init?: RequestInit & { headers?: HeadersInit & { 'Idempotency-Key'?: string; 'X-Idempotency-Key'?: string }; auth?: SecretAuthInput }, options?: FetchOptions): Promise<PlayFetchResponse>;",
15255
15384
  " secrets: { get(name: string): SecretPromise; bearer(secret: string | SecretPromise | SecretHandle): SecretAuth; header(header: string, secret: string | SecretPromise | SecretHandle): SecretAuth };",
15256
15385
  ` runPlay<TOutput = unknown>(key: string, playRef: ${cloudReferenceType("ctx.runPlay.playRef")}, input: ${cloudReferenceType("ctx.runPlay.input")}, options: PlayCallOptions): Promise<TOutput>;`,
15257
- " log(message: string): void;",
15386
+ " log(message: string, options?: { level?: 'debug' | 'info' | 'warn' | 'error' }): void;",
15258
15387
  ` sleep(ms: ${cloudReferenceType("ctx.sleep.ms")}): Promise<void>;`,
15259
15388
  "}",
15260
15389
  "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'] };",
@@ -16811,77 +16940,6 @@ function isInternalGlueStepId(stepId) {
16811
16940
  return typeof stepId === "string" && stepId.startsWith(INTERNAL_GLUE_NODE_ID_PREFIX);
16812
16941
  }
16813
16942
 
16814
- // ../play-runtime/log-provenance.ts
16815
- var LOG_PROVENANCE_CLASSES = [
16816
- "user",
16817
- "lifecycle",
16818
- "replay",
16819
- "infra",
16820
- "diagnostic",
16821
- "receipt"
16822
- ];
16823
- var LOG_PROVENANCE_POLICY = {
16824
- user: { watch: true, ui: true, debug: true },
16825
- lifecycle: { watch: true, ui: true, debug: true },
16826
- replay: { watch: false, ui: false, debug: true },
16827
- infra: { watch: false, ui: false, debug: true },
16828
- diagnostic: { watch: true, ui: true, debug: true },
16829
- receipt: { watch: false, ui: false, debug: true }
16830
- };
16831
- function logProvenanceReaches(provenance, surface) {
16832
- return LOG_PROVENANCE_POLICY[provenance][surface];
16833
- }
16834
- var PROVENANCE_SENTINEL = "";
16835
- var PROVENANCE_PREFIX = `${PROVENANCE_SENTINEL}prov:`;
16836
- function readProvenanceTag(line) {
16837
- if (!line.startsWith(PROVENANCE_PREFIX)) {
16838
- return { provenance: null, line };
16839
- }
16840
- const end = line.indexOf(PROVENANCE_SENTINEL, PROVENANCE_PREFIX.length);
16841
- if (end === -1) {
16842
- return { provenance: null, line };
16843
- }
16844
- const candidate = line.slice(PROVENANCE_PREFIX.length, end);
16845
- const provenance = LOG_PROVENANCE_CLASSES.includes(candidate) ? candidate : null;
16846
- return { provenance, line: line.slice(end + 1) };
16847
- }
16848
- function classifyLegacyLogLine(line) {
16849
- const message = stripLeadingTimestamp(line);
16850
- if (/recovered (?:from checkpoint|response from checkpoint)/i.test(message)) {
16851
- return "replay";
16852
- }
16853
- if (/^\[perf\] runtime receipt\b/i.test(message)) {
16854
- return "receipt";
16855
- }
16856
- 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(
16857
- message
16858
- ) || /\[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(
16859
- message
16860
- ) || /^\[event\] play\.step\.progress\b/.test(message) || /^\[event\] play\.run\.snapshot\b/.test(message) || /^\[event\] play\.sheet\.summary\b/.test(message)) {
16861
- return "infra";
16862
- }
16863
- if (/^\[warn\]/i.test(message) || /^\[error\]/i.test(message) || /^\[runtime\.[a-z_]*(?:failure|error)\]/i.test(message)) {
16864
- return "diagnostic";
16865
- }
16866
- return "user";
16867
- }
16868
- function classifyLogLine(line) {
16869
- const tagged = readProvenanceTag(line);
16870
- if (tagged.provenance !== null) {
16871
- return { provenance: tagged.provenance, line: tagged.line };
16872
- }
16873
- return { provenance: classifyLegacyLogLine(tagged.line), line: tagged.line };
16874
- }
16875
- function stripLeadingTimestamp(line) {
16876
- const match = line.match(/^\[([^\]]+)\]\s*([\s\S]*)$/);
16877
- if (!match) {
16878
- return line;
16879
- }
16880
- const inner = match[1] ?? "";
16881
- const isTimestamp = !Number.isNaN(new Date(inner).getTime());
16882
- return isTimestamp ? match[2] ?? line : line;
16883
- }
16884
-
16885
16943
  // ../play-runtime/fixture-behavior.ts
16886
16944
  var FIXTURE_BEHAVIOR_VERSION = 1;
16887
16945
  var FIXTURE_BEHAVIOR_RESPONSE_VERSION = 2;
@@ -18309,7 +18367,11 @@ var TERMINAL_PLAY_STATUSES2 = /* @__PURE__ */ new Set([
18309
18367
  var PLAY_START_TRANSIENT_RETRY_DELAYS_MS = [500, 1500];
18310
18368
  var PLAY_PROGRESS_HEARTBEAT_INTERVAL_MS = 15e3;
18311
18369
  var PLAY_STATUS_HEARTBEAT_INTERVAL_MS = 15e3;
18312
- function watchSurfaceReaches(state, provenance) {
18370
+ function watchSurfaceReaches(state, provenance, level) {
18371
+ const minimumLevel = state.logLevel ?? (state.verbose ? "debug" : "info");
18372
+ if (!logLevelReaches(level, minimumLevel)) {
18373
+ return false;
18374
+ }
18313
18375
  if (logProvenanceReaches(provenance, "watch")) {
18314
18376
  return true;
18315
18377
  }
@@ -18504,7 +18566,7 @@ function emitLiveDebugTableHints(input2) {
18504
18566
  process.stdout
18505
18567
  );
18506
18568
  }
18507
- if (!watchSurfaceReaches(input2.state, "infra")) {
18569
+ if (!watchSurfaceReaches(input2.state, "infra", "debug")) {
18508
18570
  return;
18509
18571
  }
18510
18572
  const tableNamespace = extractTableNamespaceFromLiveEvent(input2.event);
@@ -18607,7 +18669,7 @@ function getStepTransitionLineFromLiveEvent(event, state) {
18607
18669
  if (isTerminal) {
18608
18670
  state.terminalStepIds.add(stepId);
18609
18671
  }
18610
- if (isReplayEcho && !watchSurfaceReaches(state, "replay")) {
18672
+ if (isReplayEcho && !watchSurfaceReaches(state, "replay", "debug")) {
18611
18673
  return null;
18612
18674
  }
18613
18675
  return `step ${label}: ${status}`;
@@ -19011,6 +19073,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
19011
19073
  lastLogIndex: 0,
19012
19074
  emittedRunnerStarted: false,
19013
19075
  verbose: input2.verboseLogs === true,
19076
+ logLevel: input2.logLevel ?? "info",
19014
19077
  lastProgressSignature: null,
19015
19078
  lastProgressHeartbeatAt: 0,
19016
19079
  lastStatusHeartbeatAt: 0
@@ -19389,6 +19452,9 @@ function formatPlayLogLine(rawLine, status, state) {
19389
19452
  const message = timestampMatch?.[2] ?? line;
19390
19453
  const prefix = timestamp ? `${timestamp} ` : "";
19391
19454
  if (/\[worker\] picked up run\b/.test(message)) {
19455
+ if (!logLevelReaches("info", state.logLevel ?? "info")) {
19456
+ return null;
19457
+ }
19392
19458
  if (state.emittedRunnerStarted) {
19393
19459
  return null;
19394
19460
  }
@@ -19405,6 +19471,9 @@ function formatPlayLogLine(rawLine, status, state) {
19405
19471
  /^Starting map over (\d+) items with (\d+) fields \(key: ([^;]+); (\d+) already satisfied; (\d+) pending\)$/
19406
19472
  );
19407
19473
  if (mapStart) {
19474
+ if (!logLevelReaches("info", state.logLevel ?? "info")) {
19475
+ return null;
19476
+ }
19408
19477
  const [, rows, fields, namespace, cached, pending] = mapStart;
19409
19478
  return `${prefix}map ${sourceLabelForNamespace(namespace)}: ${formatInteger(Number(rows))} rows, ${fields} fields, ${formatInteger(Number(cached))} cached, ${formatInteger(Number(pending))} pending`;
19410
19479
  }
@@ -19412,10 +19481,13 @@ function formatPlayLogLine(rawLine, status, state) {
19412
19481
  /^Map completed: (\d+) results \((\d+) executed, (\d+) already satisfied\)$/
19413
19482
  );
19414
19483
  if (mapDone) {
19484
+ if (!logLevelReaches("info", state.logLevel ?? "info")) {
19485
+ return null;
19486
+ }
19415
19487
  const [, results, executed, cached] = mapDone;
19416
19488
  return `${prefix}done: ${formatInteger(Number(results))} results, ${formatInteger(Number(executed))} executed, ${formatInteger(Number(cached))} cached`;
19417
19489
  }
19418
- if (!watchSurfaceReaches(state, classified.provenance)) {
19490
+ if (!watchSurfaceReaches(state, classified.provenance, classified.level)) {
19419
19491
  return null;
19420
19492
  }
19421
19493
  return `${prefix}${message}`;
@@ -21151,13 +21223,12 @@ function parsePlayRunOptions(args) {
21151
21223
  const watch = !args.includes("--no-wait");
21152
21224
  let jsonOutput = watch ? args.includes("--json") : argsWantJson(args);
21153
21225
  const fullJson = args.includes("--full");
21154
- const explicitDebugLogs = args.includes("--logs") || args.some((_, index) => isBarePlayRunDebugFlag(args, index));
21155
- const emitLogs = !jsonOutput || explicitDebugLogs;
21156
21226
  const force = args.includes("--force");
21157
21227
  const forceToolRefresh = args.includes("--force-tool-refresh");
21158
21228
  const open2 = args.includes("--open");
21159
21229
  const debugMapLatency = args.includes("--debug-map-latency");
21160
- const verboseLogs = explicitDebugLogs || debugMapLatency;
21230
+ let logLevel = "info";
21231
+ let hasExplicitLogLevel = false;
21161
21232
  let waitTimeoutMs = null;
21162
21233
  let maxConcurrentExternalCalls = null;
21163
21234
  let maxConcurrentRows = null;
@@ -21178,6 +21249,23 @@ function parsePlayRunOptions(args) {
21178
21249
  input2 = parseJsonInput(args[++index]);
21179
21250
  continue;
21180
21251
  }
21252
+ if (arg === "--log-level" || arg.startsWith("--log-level=")) {
21253
+ const value = arg === "--log-level" ? args[++index] : arg.slice("--log-level=".length);
21254
+ if (!value || value.startsWith("--")) {
21255
+ throw new Error(
21256
+ "--log-level requires one of: debug, info, warn, error."
21257
+ );
21258
+ }
21259
+ const parsed = parseLogLevel(value);
21260
+ if (!parsed) {
21261
+ throw new Error(
21262
+ `Unsupported --log-level ${JSON.stringify(value)}. Use debug, info, warn, or error.`
21263
+ );
21264
+ }
21265
+ logLevel = parsed;
21266
+ hasExplicitLogLevel = true;
21267
+ continue;
21268
+ }
21181
21269
  if (arg === "--run-id-file") {
21182
21270
  const value = args[index + 1];
21183
21271
  if (!value || value.startsWith("--")) {
@@ -21356,6 +21444,17 @@ function parsePlayRunOptions(args) {
21356
21444
  "--live, --latest, and --revision-id only apply to named plays."
21357
21445
  );
21358
21446
  }
21447
+ if (debugMapLatency && logLevel === "info") logLevel = "debug";
21448
+ const usesDebugAlias = args.includes("--logs") || args.some((_, index) => isBarePlayRunDebugFlag(args, index));
21449
+ if (usesDebugAlias && hasExplicitLogLevel && logLevel !== "debug") {
21450
+ throw new Error(
21451
+ "--debug/--logs conflicts with a non-debug --log-level. Use one level selector."
21452
+ );
21453
+ }
21454
+ if (usesDebugAlias) logLevel = "debug";
21455
+ const explicitDebugLogs = usesDebugAlias || logLevel === "debug";
21456
+ const emitLogs = !jsonOutput || explicitDebugLogs || hasExplicitLogLevel;
21457
+ const verboseLogs = explicitDebugLogs || debugMapLatency;
21359
21458
  return {
21360
21459
  target: filePath ? { kind: "file", path: filePath } : { kind: "name", name: playName },
21361
21460
  input: input2,
@@ -21364,6 +21463,7 @@ function parsePlayRunOptions(args) {
21364
21463
  watch,
21365
21464
  emitLogs,
21366
21465
  verboseLogs,
21466
+ logLevel,
21367
21467
  jsonOutput,
21368
21468
  fullJson,
21369
21469
  waitTimeoutMs,
@@ -22261,6 +22361,7 @@ async function handleFileBackedRun(options, hooks) {
22261
22361
  jsonOutput: options.jsonOutput,
22262
22362
  emitLogs: options.emitLogs,
22263
22363
  verboseLogs: options.verboseLogs,
22364
+ logLevel: options.logLevel,
22264
22365
  waitTimeoutMs: options.waitTimeoutMs,
22265
22366
  open: options.open,
22266
22367
  progress,
@@ -22443,6 +22544,7 @@ async function handleNamedRun(options, hooks) {
22443
22544
  jsonOutput: options.jsonOutput,
22444
22545
  emitLogs: options.emitLogs,
22445
22546
  verboseLogs: options.verboseLogs,
22547
+ logLevel: options.logLevel,
22446
22548
  waitTimeoutMs: options.waitTimeoutMs,
22447
22549
  open: options.open,
22448
22550
  progress,
@@ -22560,12 +22662,13 @@ async function handlePlayRun(args, hooks) {
22560
22662
  function parseRunIdPositional(args, usage) {
22561
22663
  for (let index = 0; index < args.length; index += 1) {
22562
22664
  const arg = args[index];
22563
- if (arg === "--json" || arg === "--full" || arg === "--input" || arg === "--logs" || arg === "--debug" || arg === "--compact" || arg === "--log-failed" || arg === "--failed" || arg === "--limit") {
22564
- if (arg === "--limit" && args[index + 1]) {
22665
+ if (arg === "--json" || arg === "--full" || arg === "--input" || arg === "--logs" || arg === "--debug" || arg === "--compact" || arg === "--log-failed" || arg === "--failed" || arg === "--limit" || arg === "--log-level") {
22666
+ if ((arg === "--limit" || arg === "--log-level") && args[index + 1]) {
22565
22667
  index += 1;
22566
22668
  }
22567
22669
  continue;
22568
22670
  }
22671
+ if (arg.startsWith("--log-level=")) continue;
22569
22672
  if ((arg === "--out" || arg === "--reason" || arg === "--dataset") && args[index + 1]) {
22570
22673
  index += 1;
22571
22674
  continue;
@@ -22727,7 +22830,7 @@ async function handleRunsList(args) {
22727
22830
  return 0;
22728
22831
  }
22729
22832
  async function handleRunTail(args) {
22730
- const usage = "Usage: deepline runs tail <run-id> [--json | --jsonl] [--compact] [--debug]";
22833
+ const usage = "Usage: deepline runs tail <run-id> [--json | --jsonl] [--compact] [--log-level debug|info|warn|error]";
22731
22834
  let runId;
22732
22835
  try {
22733
22836
  runId = parseRunIdPositional(args, usage);
@@ -22735,6 +22838,9 @@ async function handleRunTail(args) {
22735
22838
  console.error(error instanceof Error ? error.message : usage);
22736
22839
  return 1;
22737
22840
  }
22841
+ let logLevel = "info";
22842
+ let hasExplicitLogLevel = false;
22843
+ let usesDebugAlias = false;
22738
22844
  for (let index = 0; index < args.length; index += 1) {
22739
22845
  const arg = args[index];
22740
22846
  if (arg === "--cursor") {
@@ -22743,7 +22849,28 @@ async function handleRunTail(args) {
22743
22849
  );
22744
22850
  return 1;
22745
22851
  }
22746
- if (arg.startsWith("--") && arg !== "--json" && arg !== "--jsonl" && arg !== "--compact" && arg !== "--logs" && arg !== "--debug") {
22852
+ if (arg === "--log-level" || arg.startsWith("--log-level=")) {
22853
+ const value = arg === "--log-level" ? args[++index] : arg.slice("--log-level=".length);
22854
+ if (!value || value.startsWith("--")) {
22855
+ console.error("--log-level requires one of: debug, info, warn, error.");
22856
+ return 1;
22857
+ }
22858
+ const parsed = parseLogLevel(value);
22859
+ if (!parsed) {
22860
+ console.error(
22861
+ `Unsupported --log-level ${JSON.stringify(value)}. Use debug, info, warn, or error.`
22862
+ );
22863
+ return 1;
22864
+ }
22865
+ logLevel = parsed;
22866
+ hasExplicitLogLevel = true;
22867
+ continue;
22868
+ }
22869
+ if (arg === "--logs" || arg === "--debug") {
22870
+ usesDebugAlias = true;
22871
+ continue;
22872
+ }
22873
+ if (arg.startsWith("--") && arg !== "--json" && arg !== "--jsonl" && arg !== "--compact") {
22747
22874
  console.error(`${arg} is not supported by deepline runs tail.`);
22748
22875
  return 1;
22749
22876
  }
@@ -22752,10 +22879,17 @@ async function handleRunTail(args) {
22752
22879
  console.error("--json and --jsonl cannot be used together.");
22753
22880
  return 1;
22754
22881
  }
22755
- const debug = args.includes("--logs") || args.includes("--debug");
22756
- if (args.includes("--jsonl") && debug) {
22882
+ if (usesDebugAlias && hasExplicitLogLevel && logLevel !== "debug") {
22757
22883
  console.error(
22758
- "--debug is redundant with --jsonl: JSON Lines already includes every canonical live event."
22884
+ "--debug conflicts with a non-debug --log-level. Use one level selector."
22885
+ );
22886
+ return 1;
22887
+ }
22888
+ if (usesDebugAlias) logLevel = "debug";
22889
+ const debug = logLevel === "debug";
22890
+ if (args.includes("--jsonl") && (debug || hasExplicitLogLevel)) {
22891
+ console.error(
22892
+ "--log-level cannot be combined with --jsonl: JSON Lines already includes every canonical live event."
22759
22893
  );
22760
22894
  return 1;
22761
22895
  }
@@ -22769,7 +22903,8 @@ async function handleRunTail(args) {
22769
22903
  lastProgressSignature: null,
22770
22904
  lastProgressHeartbeatAt: 0,
22771
22905
  lastStatusHeartbeatAt: 0,
22772
- verbose: debug
22906
+ verbose: debug,
22907
+ logLevel
22773
22908
  };
22774
22909
  const status = await client2.runs.tail(runId, {
22775
22910
  onEvent: jsonLines ? (event) => {
@@ -22781,8 +22916,8 @@ async function handleRunTail(args) {
22781
22916
  })}
22782
22917
  `
22783
22918
  );
22784
- } : compact || debug ? (event) => {
22785
- if (debug) {
22919
+ } : compact || debug || hasExplicitLogLevel ? (event) => {
22920
+ if (debug || hasExplicitLogLevel) {
22786
22921
  for (const line of getLogLinesFromLiveEvent(event)) {
22787
22922
  const formatted = formatPlayLogLine(
22788
22923
  line,
@@ -22817,7 +22952,7 @@ async function handleRunTail(args) {
22817
22952
  }
22818
22953
  } : void 0,
22819
22954
  // Human mode only: in --json mode emit nothing non-protocol.
22820
- onReconnect: jsonOutput && !debug ? void 0 : ({ reason }) => {
22955
+ onReconnect: jsonOutput && !debug && !hasExplicitLogLevel ? void 0 : ({ reason }) => {
22821
22956
  process.stderr.write(
22822
22957
  `[runs tail] stream ended without a terminal status; reconnecting to run ${runId} (${reason})
22823
22958
  `
@@ -22833,7 +22968,7 @@ async function handleRunTail(args) {
22833
22968
  return status.status === "failed" ? 1 : 0;
22834
22969
  }
22835
22970
  async function handleRunLogs(args) {
22836
- const usage = "Usage: deepline runs logs <run-id> [--limit 200] [--failed] [--out run.log] [--json] [--debug]";
22971
+ const usage = "Usage: deepline runs logs <run-id> [--limit 200] [--failed] [--out run.log] [--log-level debug|info|warn|error] [--json]";
22837
22972
  let runId;
22838
22973
  try {
22839
22974
  runId = parseRunIdPositional(args, usage);
@@ -22843,10 +22978,34 @@ async function handleRunLogs(args) {
22843
22978
  }
22844
22979
  let limit = 200;
22845
22980
  let outPath = null;
22981
+ let logLevel = "debug";
22982
+ let hasExplicitLogLevel = false;
22983
+ let usesDebugAlias = false;
22846
22984
  const failed = args.includes("--failed");
22847
22985
  for (let index = 0; index < args.length; index += 1) {
22848
22986
  const arg = args[index];
22849
- if (arg === "--debug" || arg === "--logs" || arg === "--json" || arg === "--failed") {
22987
+ if (arg === "--debug" || arg === "--logs") {
22988
+ usesDebugAlias = true;
22989
+ continue;
22990
+ }
22991
+ if (arg === "--json" || arg === "--failed") {
22992
+ continue;
22993
+ }
22994
+ if (arg === "--log-level" || arg.startsWith("--log-level=")) {
22995
+ const value = arg === "--log-level" ? args[++index] : arg.slice("--log-level=".length);
22996
+ if (!value || value.startsWith("--")) {
22997
+ console.error("--log-level requires one of: debug, info, warn, error.");
22998
+ return 1;
22999
+ }
23000
+ const parsed = parseLogLevel(value);
23001
+ if (!parsed) {
23002
+ console.error(
23003
+ `Unsupported --log-level ${JSON.stringify(value)}. Use debug, info, warn, or error.`
23004
+ );
23005
+ return 1;
23006
+ }
23007
+ logLevel = parsed;
23008
+ hasExplicitLogLevel = true;
22850
23009
  continue;
22851
23010
  }
22852
23011
  if (arg === "--limit" && args[index + 1]) {
@@ -22862,6 +23021,13 @@ async function handleRunLogs(args) {
22862
23021
  return 1;
22863
23022
  }
22864
23023
  }
23024
+ if (usesDebugAlias && hasExplicitLogLevel && logLevel !== "debug") {
23025
+ console.error(
23026
+ "--debug conflicts with a non-debug --log-level. Use one level selector."
23027
+ );
23028
+ return 1;
23029
+ }
23030
+ if (usesDebugAlias) logLevel = "debug";
22865
23031
  if (failed && outPath) {
22866
23032
  console.error(
22867
23033
  "--failed cannot be combined with --out. Remove --failed to export the full persisted log stream."
@@ -22871,7 +23037,7 @@ async function handleRunLogs(args) {
22871
23037
  const client2 = new DeeplineClient();
22872
23038
  if (outPath) {
22873
23039
  const result2 = await client2.runs.logs(runId, { all: true });
22874
- const logs = result2.entries;
23040
+ const logs = result2.entries.filter((line) => logLevelReaches(classifyLogLine(line).level, logLevel)).map((line) => classifyLogLine(line).line);
22875
23041
  writeFileSync10(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
22876
23042
  printCommandEnvelope(
22877
23043
  {
@@ -22879,6 +23045,7 @@ async function handleRunLogs(args) {
22879
23045
  log_path: outPath,
22880
23046
  lineCount: logs.length,
22881
23047
  totalCount: result2.totalCount,
23048
+ logLevel,
22882
23049
  ...result2.logsTruncated ? { logsTruncated: true } : {},
22883
23050
  local: { log_path: outPath },
22884
23051
  render: {
@@ -22899,27 +23066,47 @@ async function handleRunLogs(args) {
22899
23066
  );
22900
23067
  return 0;
22901
23068
  }
22902
- const result = await client2.runs.logs(runId, { limit, failed });
22903
- const text = buildRunLogsText(result);
23069
+ const result = await client2.runs.logs(runId, {
23070
+ ...failed ? { limit, failed: true } : { all: logLevel !== "debug", limit }
23071
+ });
23072
+ const matchingEntries = result.entries.filter(
23073
+ (line) => logLevelReaches(classifyLogLine(line).level, logLevel)
23074
+ );
23075
+ const entries = failed ? matchingEntries : matchingEntries.slice(-limit);
23076
+ const matchingEntriesTruncated = !failed && matchingEntries.length > limit;
23077
+ const filteredResult = {
23078
+ ...result,
23079
+ entries,
23080
+ returnedCount: entries.length,
23081
+ truncated: result.truncated || matchingEntriesTruncated,
23082
+ hasMore: result.hasMore || matchingEntriesTruncated,
23083
+ view: failed ? result.view : "tail",
23084
+ next: {
23085
+ ...result.next ?? {},
23086
+ logs: `deepline runs logs ${result.runId} --out run.log --log-level ${logLevel} --json`
23087
+ }
23088
+ };
23089
+ const text = buildRunLogsText(filteredResult);
22904
23090
  printCommandEnvelope(
22905
23091
  {
22906
23092
  runId: result.runId,
22907
23093
  totalCount: result.totalCount,
22908
- returnedCount: result.returnedCount,
23094
+ returnedCount: entries.length,
22909
23095
  firstSequence: result.firstSequence,
22910
23096
  lastSequence: result.lastSequence,
22911
- truncated: result.truncated,
22912
- hasMore: result.hasMore,
23097
+ truncated: filteredResult.truncated,
23098
+ hasMore: filteredResult.hasMore,
23099
+ logLevel,
22913
23100
  ...result.logsTruncated ? { logsTruncated: true } : {},
22914
- entries: result.entries,
22915
- ...result.view ? { view: result.view } : {},
23101
+ entries,
23102
+ ...filteredResult.view ? { view: filteredResult.view } : {},
22916
23103
  ...result.association ? { association: result.association } : {},
22917
23104
  ...result.warning ? { warning: result.warning } : {},
22918
23105
  next: {
22919
23106
  ...result.next ?? {},
22920
- export: `deepline runs logs ${result.runId} --out run.log --json`
23107
+ export: `deepline runs logs ${result.runId} --out run.log --log-level ${logLevel} --json`
22921
23108
  },
22922
- render: { sections: [{ title: "run logs", lines: result.entries }] }
23109
+ render: { sections: [{ title: "run logs", lines: entries }] }
22923
23110
  },
22924
23111
  {
22925
23112
  json: argsWantJson(args),
@@ -22929,7 +23116,7 @@ async function handleRunLogs(args) {
22929
23116
  return 0;
22930
23117
  }
22931
23118
  function buildRunLogsText(result) {
22932
- const lines = [...result.entries];
23119
+ const lines = result.entries.map((line) => classifyLogLine(line).line);
22933
23120
  if (result.warning) {
22934
23121
  if (lines.length > 0) lines.push("");
22935
23122
  lines.push(`warning: ${result.warning}`);
@@ -24313,6 +24500,7 @@ Examples:
24313
24500
  deepline plays run long-background-play --no-wait
24314
24501
  deepline plays run long-background-play --run-id-file ./run-id.json
24315
24502
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
24503
+ deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --log-level debug
24316
24504
  deepline plays run my.play.ts --profile absurd
24317
24505
  deepline plays run my.play.ts --max-concurrent-external-calls 20
24318
24506
  deepline plays run my.play.ts --input @input.json --json
@@ -24332,9 +24520,12 @@ Examples:
24332
24520
  ).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(
24333
24521
  "--run-id-file <path>",
24334
24522
  "Atomically write the accepted run id to a new JSON file"
24335
- ).option("--logs", "Compatibility alias for --debug").option(
24523
+ ).option("--logs", "Compatibility alias for --log-level debug").option(
24336
24524
  "--debug [value]",
24337
- "Stream complete customer-safe runtime logs when passed without a value; otherwise pass input.debug"
24525
+ "Compatibility alias for --log-level debug when bare; --debug <value> remains legacy Play input.debug"
24526
+ ).option(
24527
+ "--log-level <level>",
24528
+ "Minimum live log severity: debug, info (default), warn, or error"
24338
24529
  ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option(
24339
24530
  "--force-tool-refresh",
24340
24531
  "Refresh completed tool receipts; may repeat billed provider calls"
@@ -24384,6 +24575,7 @@ Pass-through input flags:
24384
24575
  ...options.watch || options.wait ? ["--watch"] : [],
24385
24576
  ...options.logs ? ["--logs"] : [],
24386
24577
  ...options.debug === true ? ["--debug"] : typeof options.debug === "string" ? ["--debug", options.debug] : [],
24578
+ ...options.logLevel ? ["--log-level", options.logLevel] : [],
24387
24579
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
24388
24580
  ...options.force ? ["--force"] : [],
24389
24581
  ...options.forceToolRefresh ? ["--force-tool-refresh"] : [],
@@ -24692,10 +24884,15 @@ Concepts:
24692
24884
  tail reads the live stream. logs fetches persisted logs after the fact.
24693
24885
  stop mutates cloud state by requesting cancellation.
24694
24886
 
24887
+ Debug a run:
24888
+ Active: deepline runs tail <run-id> --log-level debug
24889
+ Historical: deepline runs logs <run-id> --out run.log --log-level debug --json
24890
+ Full state: deepline runs get <run-id> --full --json
24891
+
24695
24892
  Examples:
24696
24893
  deepline runs get play/my-play/run/20260501t000000-000 --json
24697
24894
  deepline runs tail play/my-play/run/20260501t000000-000
24698
- deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
24895
+ deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --log-level debug --json
24699
24896
  deepline runs list --play my-play --status failed --json
24700
24897
  deepline runs list --status running --json
24701
24898
  deepline runs stop play/my-play/run/20260501t000000-000 --reason "stale lock" --json
@@ -24801,13 +24998,15 @@ Notes:
24801
24998
  logs for persisted log history. In human output, --compact prints deduplicated
24802
24999
  step transitions and progress instead of the full event stream. --json emits
24803
25000
  one terminal package. --jsonl emits canonical live events as JSON Lines and
24804
- ends with the same compact package shape as runs get --json. Use --debug
24805
- (or legacy --logs) to also print customer-safe runtime log lines to stderr.
25001
+ ends with the same compact package shape as runs get --json. --log-level
25002
+ filters the rendered customer-safe runtime log lines; debug includes runtime
25003
+ and receipt diagnostics and writes them to stderr alongside JSON output.
24806
25004
 
24807
25005
  Examples:
24808
25006
  deepline runs tail play/my-play/run/20260501t000000-000
24809
25007
  deepline runs tail play/my-play/run/20260501t000000-000 --compact
24810
- deepline runs tail play/my-play/run/20260501t000000-000 --debug
25008
+ deepline runs tail play/my-play/run/20260501t000000-000 --log-level debug
25009
+ deepline runs tail play/my-play/run/20260501t000000-000 --log-level error
24811
25010
  deepline runs tail play/my-play/run/20260501t000000-000 --jsonl
24812
25011
  `
24813
25012
  ).option("--json", "Emit one terminal JSON package after the run completes").option(
@@ -24816,9 +25015,9 @@ Examples:
24816
25015
  ).option(
24817
25016
  "--compact",
24818
25017
  "Show deduplicated human step transitions and progress"
24819
- ).option("--logs", "Compatibility alias for --debug").option(
24820
- "--debug",
24821
- "Print customer-safe runtime log lines to stderr while tailing"
25018
+ ).option("--logs", "Compatibility alias for --log-level debug").option("--debug", "Compatibility alias for --log-level debug").option(
25019
+ "--log-level <level>",
25020
+ "Minimum severity: debug, info (default), warn, or error"
24822
25021
  ).action(async (runId, options) => {
24823
25022
  process.exitCode = await handleRunTail([
24824
25023
  runId,
@@ -24826,7 +25025,8 @@ Examples:
24826
25025
  ...options.jsonl ? ["--jsonl"] : [],
24827
25026
  ...options.compact ? ["--compact"] : [],
24828
25027
  ...options.logs ? ["--logs"] : [],
24829
- ...options.debug ? ["--debug"] : []
25028
+ ...options.debug ? ["--debug"] : [],
25029
+ ...options.logLevel ? ["--log-level", options.logLevel] : []
24830
25030
  ]);
24831
25031
  });
24832
25032
  runs.command("logs <runId>").description("Fetch persisted logs for a play run.").addHelpText(
@@ -24834,29 +25034,30 @@ Examples:
24834
25034
  `
24835
25035
  Notes:
24836
25036
  Prints a bounded recent log preview by default. Use --out to write the full
24837
- persisted log stream to a local file. --debug (or legacy --logs) is accepted
24838
- for script parity; this command already returns the unfiltered durable stream.
25037
+ retained stream to a local file. Use --log-level to filter by severity;
25038
+ default debug preserves the complete historical stream.
24839
25039
 
24840
25040
  Examples:
24841
25041
  deepline runs logs play/my-play/run/20260501t000000-000
24842
25042
  deepline runs logs play/my-play/run/20260501t000000-000 --limit 500
24843
25043
  deepline runs logs play/my-play/run/20260501t000000-000 --failed --json
24844
- deepline runs logs play/my-play/run/20260501t000000-000 --debug
24845
- deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
25044
+ deepline runs logs play/my-play/run/20260501t000000-000 --log-level error
25045
+ deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --log-level debug --json
24846
25046
  `
24847
25047
  ).option(
24848
25048
  "--limit <count>",
24849
25049
  "Maximum recent log lines to print without --out",
24850
25050
  "200"
24851
- ).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(
24852
- "--debug",
24853
- "Explicitly request the same persisted log view (no provenance filtering)"
24854
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
25051
+ ).option("--out <path>", "Write the full retained log stream to a file").option("--failed", "Show the bounded terminal-failure log window").option(
25052
+ "--log-level <level>",
25053
+ "Minimum severity: debug (default), info, warn, or error"
25054
+ ).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) => {
24855
25055
  process.exitCode = await handleRunLogs([
24856
25056
  runId,
24857
25057
  ...options.limit ? ["--limit", options.limit] : [],
24858
25058
  ...options.out ? ["--out", options.out] : [],
24859
25059
  ...options.failed ? ["--failed"] : [],
25060
+ ...options.logLevel ? ["--log-level", options.logLevel] : [],
24860
25061
  ...options.logs ? ["--logs"] : [],
24861
25062
  ...options.debug ? ["--debug"] : [],
24862
25063
  ...options.json ? ["--json"] : []