deepline 0.3.274 → 0.3.275
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/bundling-sources/sdk/src/client.ts +140 -11
- package/dist/bundling-sources/sdk/src/index.ts +3 -0
- package/dist/bundling-sources/sdk/src/play.ts +4 -10
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/runs/log-cursor.ts +35 -0
- package/dist/bundling-sources/sdk/src/types.ts +10 -3
- package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +12 -26
- package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +7 -3
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +15 -7
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +18 -18
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1 -0
- package/dist/bundling-sources/shared_libs/plays/docflow-binding-owner.ts +7 -4
- package/dist/bundling-sources/shared_libs/plays/table-csv.ts +152 -0
- package/dist/cli/index.js +326 -59
- package/dist/cli/index.mjs +326 -59
- package/dist/{client-D6fRwhnE.d.ts → client-5zY7LsId.d.ts} +70 -5
- package/dist/{client-2rIHKJiq.d.mts → client-CbNvJLgV.d.mts} +70 -5
- package/dist/index.d.mts +6 -12
- package/dist/index.d.ts +6 -12
- package/dist/index.js +87 -9
- package/dist/index.mjs +87 -9
- package/dist/install-integrity.json +4 -2
- package/dist/plays/run-request.d.mts +1 -1
- package/dist/plays/run-request.d.ts +1 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -1985,18 +1985,18 @@ function playInputExampleArgs(schema) {
|
|
|
1985
1985
|
if (!schema) return " --input '@<input.json>'";
|
|
1986
1986
|
if (schema.$ref || schema.allOf) return " --input '@<input.json>'";
|
|
1987
1987
|
const csv = schema.csvInput;
|
|
1988
|
-
const
|
|
1988
|
+
const csvField2 = typeof csv?.inputField === "string" ? csv.inputField : null;
|
|
1989
1989
|
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
1990
|
-
const csvOnlyRequired = required.every((key) => key ===
|
|
1990
|
+
const csvOnlyRequired = required.every((key) => key === csvField2);
|
|
1991
1991
|
const alternatives = schema.oneOf ?? schema.anyOf;
|
|
1992
1992
|
const hasCsvAlternative = Array.isArray(alternatives) && alternatives.some((branch) => {
|
|
1993
1993
|
if (!branch || typeof branch !== "object") return false;
|
|
1994
1994
|
const keys = branch.required;
|
|
1995
|
-
return Array.isArray(keys) && keys.includes(
|
|
1995
|
+
return Array.isArray(keys) && keys.includes(csvField2) && keys.every((key) => key === csvField2);
|
|
1996
1996
|
});
|
|
1997
|
-
if (
|
|
1998
|
-
if (
|
|
1999
|
-
const value = JSON.stringify({ [
|
|
1997
|
+
if (csvField2 && csvOnlyRequired && (!alternatives || hasCsvAlternative)) {
|
|
1998
|
+
if (csvField2 === "csv") return " --csv '<contacts.csv>'";
|
|
1999
|
+
const value = JSON.stringify({ [csvField2]: "<contacts.csv>" });
|
|
2000
2000
|
return ` --input '${value.replace(/'/g, "'\\''")}'`;
|
|
2001
2001
|
}
|
|
2002
2002
|
if (Array.isArray(schema.required) && !required.length && !csv && !alternatives) {
|
|
@@ -3507,7 +3507,7 @@ var SDK_RELEASE = {
|
|
|
3507
3507
|
// getters keep their established compatibility behavior.
|
|
3508
3508
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3509
3509
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3510
|
-
version: "0.3.
|
|
3510
|
+
version: "0.3.275",
|
|
3511
3511
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
3512
3512
|
packageCapabilities: {
|
|
3513
3513
|
updatePreferences: 1
|
|
@@ -6210,6 +6210,28 @@ async function* watchRunEvents(options) {
|
|
|
6210
6210
|
}
|
|
6211
6211
|
}
|
|
6212
6212
|
|
|
6213
|
+
// src/runs/log-cursor.ts
|
|
6214
|
+
var RUN_LOGS_CURSOR_PREFIX = "before:";
|
|
6215
|
+
function encodeRunLogsCursor(beforeSequence) {
|
|
6216
|
+
return `${RUN_LOGS_CURSOR_PREFIX}${beforeSequence}`;
|
|
6217
|
+
}
|
|
6218
|
+
function isRunLogsCursor(value) {
|
|
6219
|
+
return value.startsWith(RUN_LOGS_CURSOR_PREFIX);
|
|
6220
|
+
}
|
|
6221
|
+
function parseRunLogsCursor(value) {
|
|
6222
|
+
const raw = isRunLogsCursor(value) ? value.slice(RUN_LOGS_CURSOR_PREFIX.length) : "";
|
|
6223
|
+
const parsed = /^[1-9]\d*$/.test(raw) ? Number(raw) : NaN;
|
|
6224
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
6225
|
+
throw Object.assign(
|
|
6226
|
+
new Error(
|
|
6227
|
+
`Invalid run log cursor ${JSON.stringify(value)}. Pass the nextCursor value from a previous deepline runs logs result.`
|
|
6228
|
+
),
|
|
6229
|
+
{ exitCode: 2 }
|
|
6230
|
+
);
|
|
6231
|
+
}
|
|
6232
|
+
return parsed;
|
|
6233
|
+
}
|
|
6234
|
+
|
|
6213
6235
|
// src/types.ts
|
|
6214
6236
|
function isStopAllPlayRunsDryRunResult(result) {
|
|
6215
6237
|
return "dryRun" in result && result.dryRun === true;
|
|
@@ -7160,6 +7182,7 @@ var DeeplineClient = class _DeeplineClient {
|
|
|
7160
7182
|
status: (runId) => this.getRunLifecycleStatus(runId),
|
|
7161
7183
|
list: (options2) => this.listRuns(options2),
|
|
7162
7184
|
listPage: (options2) => this.listRunsPage(options2),
|
|
7185
|
+
history: (options2) => this.getRunsHistory(options2),
|
|
7163
7186
|
watch: (runId, options2) => this.watchRunToTerminal(runId, options2),
|
|
7164
7187
|
tail: (runId, options2) => this.tailRun(runId, options2),
|
|
7165
7188
|
logs: (runId, options2) => this.getRunLogs(runId, options2),
|
|
@@ -8237,11 +8260,21 @@ var DeeplineClient = class _DeeplineClient {
|
|
|
8237
8260
|
if (options?.full === true) {
|
|
8238
8261
|
params.set("full", "true");
|
|
8239
8262
|
}
|
|
8263
|
+
if (options?.configuration === true) {
|
|
8264
|
+
params.set("include", "configuration");
|
|
8265
|
+
}
|
|
8240
8266
|
const query = params.size > 0 ? `?${params.toString()}` : "";
|
|
8241
8267
|
const response = await this.http.get(
|
|
8242
8268
|
`/api/v2/runs/${encodeURIComponent(runId)}${query}`,
|
|
8243
8269
|
{ headers: { "x-deepline-run-status": "1" } }
|
|
8244
8270
|
);
|
|
8271
|
+
if (options?.configuration === true && !Object.hasOwn(response, "contract")) {
|
|
8272
|
+
throw new DeeplineError(
|
|
8273
|
+
"This server does not support recorded configuration reads.",
|
|
8274
|
+
void 0,
|
|
8275
|
+
"RUN_CONFIGURATION_UNAVAILABLE"
|
|
8276
|
+
);
|
|
8277
|
+
}
|
|
8245
8278
|
const status = normalizePlayStatus(response);
|
|
8246
8279
|
if (options?.failedLogs !== true || status.status !== "failed") {
|
|
8247
8280
|
return status;
|
|
@@ -8329,6 +8362,33 @@ var DeeplineClient = class _DeeplineClient {
|
|
|
8329
8362
|
async listRuns(options) {
|
|
8330
8363
|
return (await this.listRunsPage(options)).runs;
|
|
8331
8364
|
}
|
|
8365
|
+
/** The same tenant-scoped run history searched by the dashboard and CLI. */
|
|
8366
|
+
async getRunsHistory(options = {}) {
|
|
8367
|
+
const params = new URLSearchParams();
|
|
8368
|
+
const search = options.search?.trim();
|
|
8369
|
+
if (search && search.length > 200) {
|
|
8370
|
+
throw new Error("Run search must be at most 200 characters.");
|
|
8371
|
+
}
|
|
8372
|
+
if (options.type && options.type !== "all" && !search) {
|
|
8373
|
+
throw new Error("runs.history options.type requires options.search.");
|
|
8374
|
+
}
|
|
8375
|
+
if (search) params.set("search", search);
|
|
8376
|
+
if (search && options.type) params.set("type", options.type);
|
|
8377
|
+
if (options.cursor) params.set("cursor", options.cursor);
|
|
8378
|
+
if (options.orgId) params.set("orgId", options.orgId);
|
|
8379
|
+
if (options.limit !== void 0) {
|
|
8380
|
+
if (!Number.isSafeInteger(options.limit) || options.limit < 1) {
|
|
8381
|
+
throw new Error(
|
|
8382
|
+
"runs.history options.limit must be a positive integer."
|
|
8383
|
+
);
|
|
8384
|
+
}
|
|
8385
|
+
params.set("limit", String(options.limit));
|
|
8386
|
+
}
|
|
8387
|
+
return this.http.get(
|
|
8388
|
+
`/api/v2/dashboard/runs-history?${params.toString()}`,
|
|
8389
|
+
{ signal: options.signal }
|
|
8390
|
+
);
|
|
8391
|
+
}
|
|
8332
8392
|
/** Read one run page without discarding server pagination metadata. */
|
|
8333
8393
|
async listRunsPage(options) {
|
|
8334
8394
|
const playName = options.play?.trim();
|
|
@@ -8435,6 +8495,13 @@ var DeeplineClient = class _DeeplineClient {
|
|
|
8435
8495
|
"INVALID_RUN_LOG_VIEW"
|
|
8436
8496
|
);
|
|
8437
8497
|
}
|
|
8498
|
+
if (options?.cursor !== void 0 && options.failed === true) {
|
|
8499
|
+
throw new DeeplineError(
|
|
8500
|
+
"runs.logs cannot combine failed with cursor.",
|
|
8501
|
+
void 0,
|
|
8502
|
+
"INVALID_RUN_LOG_VIEW"
|
|
8503
|
+
);
|
|
8504
|
+
}
|
|
8438
8505
|
if (options?.failed === true) {
|
|
8439
8506
|
const requestedLimit = typeof options.limit === "number" && Number.isFinite(options.limit) && options.limit > 0 ? Math.trunc(options.limit) : RUNS_FAILED_LOG_LIMIT;
|
|
8440
8507
|
const failedLimit = Math.min(RUNS_FAILED_LOG_LIMIT, requestedLimit);
|
|
@@ -8460,6 +8527,7 @@ var DeeplineClient = class _DeeplineClient {
|
|
|
8460
8527
|
...page.logsTruncated ? { logsTruncated: true } : {}
|
|
8461
8528
|
};
|
|
8462
8529
|
}
|
|
8530
|
+
const beforeSequence = options?.cursor !== void 0 ? parseRunLogsCursor(options.cursor) : null;
|
|
8463
8531
|
const limit = options?.all ? Number.MAX_SAFE_INTEGER : typeof options?.limit === "number" && Number.isFinite(options.limit) && options.limit > 0 ? Math.trunc(options.limit) : 200;
|
|
8464
8532
|
const fetchPage = (afterSeq2, pageLimit) => this.http.get(
|
|
8465
8533
|
`/api/v2/runs/${encodeURIComponent(runId)}/logs?afterSeq=${afterSeq2}&limit=${pageLimit}`,
|
|
@@ -8467,24 +8535,33 @@ var DeeplineClient = class _DeeplineClient {
|
|
|
8467
8535
|
);
|
|
8468
8536
|
const probe = await fetchPage(0, 1);
|
|
8469
8537
|
const lastStoredSeq = probe.lastStoredSeq;
|
|
8470
|
-
|
|
8538
|
+
const oldestStoredSeq = probe.entries[0]?.seq ?? null;
|
|
8539
|
+
const upperSeq = beforeSequence === null ? Number.POSITIVE_INFINITY : Math.min(beforeSequence - 1, lastStoredSeq);
|
|
8540
|
+
const windowEndSeq = Math.min(upperSeq, lastStoredSeq);
|
|
8541
|
+
let afterSeq = options?.all ? 0 : Math.max(0, windowEndSeq - limit);
|
|
8471
8542
|
const entries = [];
|
|
8472
|
-
while (entries.length < limit) {
|
|
8543
|
+
while (entries.length < limit && afterSeq < upperSeq) {
|
|
8473
8544
|
const page = await fetchPage(
|
|
8474
8545
|
afterSeq,
|
|
8475
|
-
Math.min(
|
|
8546
|
+
Math.min(
|
|
8547
|
+
RUN_LOGS_PAGE_LIMIT,
|
|
8548
|
+
limit - entries.length,
|
|
8549
|
+
upperSeq - afterSeq
|
|
8550
|
+
)
|
|
8476
8551
|
);
|
|
8477
|
-
|
|
8552
|
+
const inWindow = page.entries.filter((entry) => entry.seq <= upperSeq);
|
|
8553
|
+
if (inWindow.length === 0) {
|
|
8478
8554
|
break;
|
|
8479
8555
|
}
|
|
8480
|
-
entries.push(...
|
|
8481
|
-
afterSeq =
|
|
8482
|
-
if (!page.hasMore) {
|
|
8556
|
+
entries.push(...inWindow);
|
|
8557
|
+
afterSeq = inWindow[inWindow.length - 1].seq;
|
|
8558
|
+
if (!page.hasMore || inWindow.length < page.entries.length) {
|
|
8483
8559
|
break;
|
|
8484
8560
|
}
|
|
8485
8561
|
}
|
|
8486
8562
|
const firstSequence = entries.length > 0 ? entries[0].seq : null;
|
|
8487
8563
|
const lastSequence = entries.length > 0 ? entries[entries.length - 1].seq : null;
|
|
8564
|
+
const olderLinesExist = firstSequence !== null && oldestStoredSeq !== null && firstSequence > oldestStoredSeq;
|
|
8488
8565
|
return {
|
|
8489
8566
|
runId: probe.runId,
|
|
8490
8567
|
totalCount: probe.totalLogCount,
|
|
@@ -8492,7 +8569,8 @@ var DeeplineClient = class _DeeplineClient {
|
|
|
8492
8569
|
firstSequence,
|
|
8493
8570
|
lastSequence,
|
|
8494
8571
|
truncated: entries.length < probe.totalLogCount,
|
|
8495
|
-
hasMore:
|
|
8572
|
+
hasMore: olderLinesExist,
|
|
8573
|
+
nextCursor: olderLinesExist ? encodeRunLogsCursor(firstSequence) : null,
|
|
8496
8574
|
entries: entries.map((entry) => entry.line),
|
|
8497
8575
|
view: options?.all ? "all" : "tail",
|
|
8498
8576
|
...probe.logsTruncated ? { logsTruncated: true } : {}
|
|
@@ -10469,6 +10547,7 @@ var ROOTS = {
|
|
|
10469
10547
|
check: "kind target checked scope name exportName valid stage issues inputSchema outputSchema recognized triggers runtimeLimit limits featureFlags sourceHash artifactHash graphHash toolGetterHints exports actions diagnostics reference origin ownerType activeScheduledPlays command_context",
|
|
10470
10548
|
run: "schemaVersion kind run datasets actions apiVersion dashboardUrl progress rowOutcomes steps errors error warnings result resultState execution command_context diagnostics",
|
|
10471
10549
|
get: "schemaVersion kind run runStatus steps failures errorDetails rowOutcomes warnings failedLogs datasets result resultState actions diagnostics command_context",
|
|
10550
|
+
config: "runId contract command_context",
|
|
10472
10551
|
export: "runId datasets csv_path json_path format source rowCount columns notice metadata_path actions command_context"
|
|
10473
10552
|
};
|
|
10474
10553
|
function parseJsonFields(args, surface) {
|
|
@@ -15814,12 +15893,12 @@ var SECTIONS = [
|
|
|
15814
15893
|
title: "Choose the read",
|
|
15815
15894
|
paragraphs: [
|
|
15816
15895
|
"These commands read existing evidence; they do not start a run or execute a provider. Replace <run-id>, <play-name> and other angle-bracket values with identifiers returned by the CLI.",
|
|
15817
|
-
"Text logs: runs logs <run-id> returns the last 200 retained lines by default. --out writes the full retained stream to a local file. --log-level filters text severity; debug includes all retained levels. --failed reads only a terminal-failed run\u2019s last 20 retained lines and reports retention limitations.",
|
|
15818
|
-
"Event search: omit the run ID, or add any of --since, --until, --play, --kind, --where, --payloads, --
|
|
15896
|
+
"Text logs: runs logs <run-id> returns the last 200 retained lines by default. When older lines exist, hasMore is true and nextCursor continues the next older page with --cursor. --out writes the full retained stream to a local file. --log-level filters text severity; debug includes all retained levels. --failed reads only a terminal-failed run\u2019s last 20 retained lines and reports retention limitations.",
|
|
15897
|
+
"Event search: omit the run ID, or add any of --since, --until, --play, --kind, --where, --payloads, --runtime-namespace or --runtime-backend. A supplied run ID then narrows the search. --cursor continues event search unless it is a returned before:<sequence> text-log cursor. --limit and --json alone do not switch a run\u2019s text logs to event search. Text-only flags --out, --failed and --log-level cannot be combined with event search.",
|
|
15819
15898
|
"Current status and returned output selectors: runs get <run-id> --json. Live observation: runs watch <run-id>. Dataset rows: runs export <run-id> --dataset <returned-selector> --out rows.csv. A referenced tool response: runs receipt <run-id> --key <returned-receipt-key> --json. Read each command\u2019s --help for its options."
|
|
15820
15899
|
],
|
|
15821
15900
|
commands: [
|
|
15822
|
-
"deepline runs logs <run-id> --json",
|
|
15901
|
+
"deepline runs logs <run-id> --cursor before:1201 --json",
|
|
15823
15902
|
"deepline runs logs <run-id> --out run.log --json",
|
|
15824
15903
|
"deepline runs logs --kind run.failed --json",
|
|
15825
15904
|
"deepline runs logs --kind step.failed --payloads --json",
|
|
@@ -18599,24 +18678,31 @@ includes nextCommand when another page is available.
|
|
|
18599
18678
|
|
|
18600
18679
|
// src/cli/commands/plays/run-history.ts
|
|
18601
18680
|
async function handleRunsHistory(options) {
|
|
18602
|
-
|
|
18603
|
-
if (options.
|
|
18604
|
-
|
|
18681
|
+
let limit;
|
|
18682
|
+
if (options.type && !["all", "plays", "monitors"].includes(options.type)) {
|
|
18683
|
+
throw new Error("--type must be all, plays or monitors.");
|
|
18684
|
+
}
|
|
18605
18685
|
if (options.limit !== void 0) {
|
|
18606
|
-
|
|
18686
|
+
limit = Number(options.limit);
|
|
18607
18687
|
if (!/^\d+$/.test(options.limit) || !Number.isSafeInteger(limit) || limit < 1) {
|
|
18608
18688
|
throw new Error("--limit must be a positive integer.");
|
|
18609
18689
|
}
|
|
18610
|
-
query.set("limit", String(limit));
|
|
18611
18690
|
}
|
|
18612
|
-
const
|
|
18613
|
-
|
|
18614
|
-
|
|
18615
|
-
|
|
18691
|
+
const page = await new DeeplineClient().runs.history({
|
|
18692
|
+
cursor: options.cursor,
|
|
18693
|
+
orgId: options.org,
|
|
18694
|
+
search: options.search,
|
|
18695
|
+
type: options.type,
|
|
18696
|
+
limit
|
|
18697
|
+
});
|
|
18616
18698
|
const lines = page.runs.map(
|
|
18617
18699
|
(run) => `${run.workflowName} \xB7 ${run.status} \xB7 ${run.runId}`
|
|
18618
18700
|
);
|
|
18619
|
-
if (lines.length === 0)
|
|
18701
|
+
if (lines.length === 0) {
|
|
18702
|
+
lines.push(
|
|
18703
|
+
options.search && page.hasMore ? "No matches in this page; continue searching with the next cursor." : "No runs found on this page."
|
|
18704
|
+
);
|
|
18705
|
+
}
|
|
18620
18706
|
if (page.hasMore) lines.push(`Next cursor: ${page.nextCursor}`);
|
|
18621
18707
|
printCommandEnvelope(
|
|
18622
18708
|
{ ...page, render: { sections: [{ title: "Run history", lines }] } },
|
|
@@ -18628,6 +18714,12 @@ function registerRunHistoryCommand(runs) {
|
|
|
18628
18714
|
"--cursor <cursor>",
|
|
18629
18715
|
"Opaque nextCursor returned by the previous page"
|
|
18630
18716
|
).option("--limit <count>", "Maximum runs on this page").option(
|
|
18717
|
+
"--search <text>",
|
|
18718
|
+
"Search Play/workflow names, run IDs and statuses"
|
|
18719
|
+
).option(
|
|
18720
|
+
"--type <type>",
|
|
18721
|
+
"Search all, plays or monitors (requires --search)"
|
|
18722
|
+
).option(
|
|
18631
18723
|
"--org <id>",
|
|
18632
18724
|
"Workspace ID (must match the authenticated workspace)"
|
|
18633
18725
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").addHelpText(
|
|
@@ -24357,6 +24449,63 @@ var SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE : resolv
|
|
|
24357
24449
|
import { writeFileSync as writeFileSync9 } from "fs";
|
|
24358
24450
|
import { resolve as resolve10 } from "path";
|
|
24359
24451
|
|
|
24452
|
+
// ../plays/table-csv.ts
|
|
24453
|
+
var TABLE_EXPORT_ERROR_COLUMN = "_error";
|
|
24454
|
+
var UNRECORDED_FAILURE_REASON = "Row failed without a recorded reason.";
|
|
24455
|
+
function tableCellText(value) {
|
|
24456
|
+
if (value === null || value === void 0) return "";
|
|
24457
|
+
if (typeof value === "string") return value;
|
|
24458
|
+
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean")
|
|
24459
|
+
return String(value);
|
|
24460
|
+
if (value instanceof Date) return value.toISOString();
|
|
24461
|
+
if (typeof value === "symbol" || typeof value === "function") return "";
|
|
24462
|
+
try {
|
|
24463
|
+
return JSON.stringify(
|
|
24464
|
+
value,
|
|
24465
|
+
(_key, nested) => typeof nested === "bigint" ? nested.toString() : nested
|
|
24466
|
+
) ?? "";
|
|
24467
|
+
} catch {
|
|
24468
|
+
return String(value);
|
|
24469
|
+
}
|
|
24470
|
+
}
|
|
24471
|
+
function csvField(value) {
|
|
24472
|
+
const text = tableCellText(value);
|
|
24473
|
+
return /[",\r\n]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text;
|
|
24474
|
+
}
|
|
24475
|
+
function csvRecord(values) {
|
|
24476
|
+
return `${values.map(csvField).join(",")}
|
|
24477
|
+
`;
|
|
24478
|
+
}
|
|
24479
|
+
function isFailedRow(row) {
|
|
24480
|
+
return row.status === "failed";
|
|
24481
|
+
}
|
|
24482
|
+
function tableExportHasFailedRows(rows) {
|
|
24483
|
+
for (const row of rows) if (isFailedRow(row)) return true;
|
|
24484
|
+
return false;
|
|
24485
|
+
}
|
|
24486
|
+
function tableExportErrorCell(row) {
|
|
24487
|
+
if (!isFailedRow(row)) return "";
|
|
24488
|
+
const reason = typeof row.error === "string" ? row.error.trim() : "";
|
|
24489
|
+
return reason || UNRECORDED_FAILURE_REASON;
|
|
24490
|
+
}
|
|
24491
|
+
function tableExportColumns(columns, withError) {
|
|
24492
|
+
if (!withError) return [...columns];
|
|
24493
|
+
return [
|
|
24494
|
+
...columns.filter((column) => column !== TABLE_EXPORT_ERROR_COLUMN),
|
|
24495
|
+
TABLE_EXPORT_ERROR_COLUMN
|
|
24496
|
+
];
|
|
24497
|
+
}
|
|
24498
|
+
function tableExportCells(row, columns, withError) {
|
|
24499
|
+
return tableExportColumns(columns, withError).map(
|
|
24500
|
+
(column) => column === TABLE_EXPORT_ERROR_COLUMN && withError ? tableExportErrorCell(row) : Object.hasOwn(row.data, column) ? row.data[column] : void 0
|
|
24501
|
+
);
|
|
24502
|
+
}
|
|
24503
|
+
function tableCsvText(header, records) {
|
|
24504
|
+
let text = csvRecord(header);
|
|
24505
|
+
for (const record5 of records) text += csvRecord(record5);
|
|
24506
|
+
return text;
|
|
24507
|
+
}
|
|
24508
|
+
|
|
24360
24509
|
// src/cli/run-dataset-order.ts
|
|
24361
24510
|
function underscoreKeysLast(keys) {
|
|
24362
24511
|
return [...keys].sort(
|
|
@@ -24405,9 +24554,13 @@ var RunDatasetCsv = class _RunDatasetCsv {
|
|
|
24405
24554
|
}
|
|
24406
24555
|
write(outPath) {
|
|
24407
24556
|
const absolutePath = resolve10(outPath);
|
|
24557
|
+
const { rows, columns } = this.#projection;
|
|
24408
24558
|
writeFileSync9(
|
|
24409
24559
|
absolutePath,
|
|
24410
|
-
|
|
24560
|
+
tableCsvText(
|
|
24561
|
+
columns,
|
|
24562
|
+
rows.map((data) => tableExportCells({ data }, columns, false))
|
|
24563
|
+
),
|
|
24411
24564
|
"utf-8"
|
|
24412
24565
|
);
|
|
24413
24566
|
return absolutePath;
|
|
@@ -32003,7 +32156,20 @@ async function fetchBackingDatasetRows(input2) {
|
|
|
32003
32156
|
}
|
|
32004
32157
|
offset += page.rows.length;
|
|
32005
32158
|
}
|
|
32006
|
-
const
|
|
32159
|
+
const withError = tableExportHasFailedRows(
|
|
32160
|
+
sheetRows.filter(
|
|
32161
|
+
(row) => Boolean(row) && typeof row === "object" && !Array.isArray(row)
|
|
32162
|
+
)
|
|
32163
|
+
);
|
|
32164
|
+
const rows = sheetRows.map((row) => {
|
|
32165
|
+
const data = exportableSheetRow(row);
|
|
32166
|
+
return data && withError ? {
|
|
32167
|
+
...data,
|
|
32168
|
+
[TABLE_EXPORT_ERROR_COLUMN]: tableExportErrorCell(
|
|
32169
|
+
row
|
|
32170
|
+
)
|
|
32171
|
+
} : data;
|
|
32172
|
+
}).filter((row) => Boolean(row));
|
|
32007
32173
|
const hasCompleteSettledPrefix = acceptsSettledRowsAsCompleteExport(input2.status) && settledTotal !== null && // A zero-row run-scoped read is not a settled export when the returned
|
|
32008
32174
|
// Dataset Handle advertised rows. That shape is the replay/reuse case:
|
|
32009
32175
|
// the rows belong to another writer (or the projection has not caught up)
|
|
@@ -33985,9 +34151,12 @@ function renderRunOverviewText(overview, extras = {}) {
|
|
|
33985
34151
|
${renderCommandEnvelopeText({ render: { sections, actions: actions2 } })}`;
|
|
33986
34152
|
}
|
|
33987
34153
|
async function handleRunGet(args) {
|
|
33988
|
-
const selection = parseJsonFields(
|
|
34154
|
+
const selection = parseJsonFields(
|
|
34155
|
+
args,
|
|
34156
|
+
args.includes("--config") ? "config" : "get"
|
|
34157
|
+
);
|
|
33989
34158
|
args = selection.args;
|
|
33990
|
-
const usage2 = "Usage: deepline runs get <run-id> [--json] [--full] [--input] [--log-failed]";
|
|
34159
|
+
const usage2 = "Usage: deepline runs get <run-id> [--json] [--full] [--input] [--config] [--log-failed]";
|
|
33991
34160
|
let runId;
|
|
33992
34161
|
try {
|
|
33993
34162
|
runId = parseRunIdPositional(args, usage2);
|
|
@@ -33996,6 +34165,25 @@ async function handleRunGet(args) {
|
|
|
33996
34165
|
return 1;
|
|
33997
34166
|
}
|
|
33998
34167
|
const client2 = new DeeplineClient();
|
|
34168
|
+
if (args.includes("--config")) {
|
|
34169
|
+
if (args.some((arg) => ["--input", "--full", "--log-failed"].includes(arg))) {
|
|
34170
|
+
console.error(
|
|
34171
|
+
"--config cannot be combined with --input, --full or --log-failed."
|
|
34172
|
+
);
|
|
34173
|
+
return 1;
|
|
34174
|
+
}
|
|
34175
|
+
const status2 = await client2.runs.get(runId, { configuration: true });
|
|
34176
|
+
if (!Object.hasOwn(status2, "contract")) {
|
|
34177
|
+
throw new Error(
|
|
34178
|
+
"This server does not support recorded configuration reads."
|
|
34179
|
+
);
|
|
34180
|
+
}
|
|
34181
|
+
printCommandEnvelope(
|
|
34182
|
+
{ runId, contract: status2.contract ?? null },
|
|
34183
|
+
{ json: true, fields: selection.fields }
|
|
34184
|
+
);
|
|
34185
|
+
return 0;
|
|
34186
|
+
}
|
|
33999
34187
|
if (args.includes("--input")) {
|
|
34000
34188
|
const input2 = await client2.getRunInput(runId);
|
|
34001
34189
|
printCommandEnvelope(input2, { json: true });
|
|
@@ -34501,15 +34689,17 @@ async function handleRunLogs(args) {
|
|
|
34501
34689
|
"--play",
|
|
34502
34690
|
"--kind",
|
|
34503
34691
|
"--where",
|
|
34504
|
-
"--cursor",
|
|
34505
34692
|
"--payloads",
|
|
34506
34693
|
"--runtime-namespace",
|
|
34507
34694
|
"--runtime-backend"
|
|
34508
34695
|
]);
|
|
34509
|
-
|
|
34696
|
+
const cursorIndex = args.indexOf("--cursor");
|
|
34697
|
+
const cursorValue = cursorIndex >= 0 ? args[cursorIndex + 1] : void 0;
|
|
34698
|
+
const continuesEventSearch = cursorIndex >= 0 && !(cursorValue && isRunLogsCursor(cursorValue));
|
|
34699
|
+
if (!args[0] || args[0].startsWith("--") || continuesEventSearch || args.some((arg) => searchFlags.has(arg))) {
|
|
34510
34700
|
return handleRunEventSearch(args);
|
|
34511
34701
|
}
|
|
34512
|
-
const usage2 = "Usage: deepline runs logs <run-id> [--limit 200] [--failed] [--out run.log] [--log-level debug|info|warn|error] [--json]";
|
|
34702
|
+
const usage2 = "Usage: deepline runs logs <run-id> [--limit 200] [--cursor before:<seq>] [--failed] [--out run.log] [--log-level debug|info|warn|error] [--json]";
|
|
34513
34703
|
let runId;
|
|
34514
34704
|
try {
|
|
34515
34705
|
runId = parseRunIdPositional(args, usage2);
|
|
@@ -34519,6 +34709,7 @@ async function handleRunLogs(args) {
|
|
|
34519
34709
|
}
|
|
34520
34710
|
let limit = 200;
|
|
34521
34711
|
let outPath = null;
|
|
34712
|
+
let cursor;
|
|
34522
34713
|
let logLevel = "debug";
|
|
34523
34714
|
let hasExplicitLogLevel = false;
|
|
34524
34715
|
let usesDebugAlias = false;
|
|
@@ -34557,6 +34748,10 @@ async function handleRunLogs(args) {
|
|
|
34557
34748
|
outPath = resolve13(args[++index]);
|
|
34558
34749
|
continue;
|
|
34559
34750
|
}
|
|
34751
|
+
if (arg === "--cursor" && args[index + 1]) {
|
|
34752
|
+
cursor = args[++index];
|
|
34753
|
+
continue;
|
|
34754
|
+
}
|
|
34560
34755
|
if (arg.startsWith("--")) {
|
|
34561
34756
|
console.error(`${arg} is not supported by deepline runs logs.`);
|
|
34562
34757
|
return 1;
|
|
@@ -34575,6 +34770,12 @@ async function handleRunLogs(args) {
|
|
|
34575
34770
|
);
|
|
34576
34771
|
return 1;
|
|
34577
34772
|
}
|
|
34773
|
+
if (cursor !== void 0 && (failed || outPath)) {
|
|
34774
|
+
console.error(
|
|
34775
|
+
"--cursor pages the bounded log tail; it cannot be combined with --failed or --out."
|
|
34776
|
+
);
|
|
34777
|
+
return 1;
|
|
34778
|
+
}
|
|
34578
34779
|
const client2 = new DeeplineClient();
|
|
34579
34780
|
if (outPath) {
|
|
34580
34781
|
const result2 = await client2.runs.logs(runId, { all: true });
|
|
@@ -34608,19 +34809,25 @@ async function handleRunLogs(args) {
|
|
|
34608
34809
|
return 0;
|
|
34609
34810
|
}
|
|
34610
34811
|
const result = await client2.runs.logs(runId, {
|
|
34611
|
-
...failed ? { limit, failed: true } : { all: logLevel !== "debug", limit }
|
|
34612
|
-
|
|
34613
|
-
|
|
34614
|
-
|
|
34615
|
-
|
|
34616
|
-
|
|
34617
|
-
|
|
34812
|
+
...failed ? { limit, failed: true } : { all: logLevel !== "debug", limit },
|
|
34813
|
+
...cursor !== void 0 ? { cursor } : {}
|
|
34814
|
+
});
|
|
34815
|
+
const page = failed ? {
|
|
34816
|
+
entries: result.entries,
|
|
34817
|
+
firstSequence: result.firstSequence,
|
|
34818
|
+
lastSequence: result.lastSequence,
|
|
34819
|
+
truncated: result.truncated,
|
|
34820
|
+
hasMore: result.hasMore,
|
|
34821
|
+
nextCursor: void 0
|
|
34822
|
+
} : selectRunLogTailPage(result, logLevel, limit);
|
|
34823
|
+
const entries = page.entries;
|
|
34824
|
+
const nextPage = page.nextCursor ? `deepline runs logs ${result.runId} --limit ${limit}${logLevel === "debug" ? "" : ` --log-level ${logLevel}`} --cursor ${page.nextCursor} --json` : null;
|
|
34618
34825
|
const filteredResult = {
|
|
34619
34826
|
...result,
|
|
34620
34827
|
entries,
|
|
34621
34828
|
returnedCount: entries.length,
|
|
34622
|
-
truncated:
|
|
34623
|
-
hasMore:
|
|
34829
|
+
truncated: page.truncated,
|
|
34830
|
+
hasMore: page.hasMore,
|
|
34624
34831
|
view: failed ? result.view : "tail",
|
|
34625
34832
|
next: {
|
|
34626
34833
|
...result.next ?? {},
|
|
@@ -34633,10 +34840,11 @@ async function handleRunLogs(args) {
|
|
|
34633
34840
|
runId: result.runId,
|
|
34634
34841
|
totalCount: result.totalCount,
|
|
34635
34842
|
returnedCount: entries.length,
|
|
34636
|
-
firstSequence:
|
|
34637
|
-
lastSequence:
|
|
34843
|
+
firstSequence: page.firstSequence,
|
|
34844
|
+
lastSequence: page.lastSequence,
|
|
34638
34845
|
truncated: filteredResult.truncated,
|
|
34639
34846
|
hasMore: filteredResult.hasMore,
|
|
34847
|
+
...page.nextCursor !== void 0 ? { nextCursor: page.nextCursor } : {},
|
|
34640
34848
|
logLevel,
|
|
34641
34849
|
...result.logsTruncated ? { logsTruncated: true } : {},
|
|
34642
34850
|
entries,
|
|
@@ -34645,6 +34853,7 @@ async function handleRunLogs(args) {
|
|
|
34645
34853
|
...result.warning ? { warning: result.warning } : {},
|
|
34646
34854
|
next: {
|
|
34647
34855
|
...result.next ?? {},
|
|
34856
|
+
...nextPage ? { page: nextPage } : {},
|
|
34648
34857
|
export: `deepline runs logs ${result.runId} --out run.log --log-level ${logLevel} --json`
|
|
34649
34858
|
},
|
|
34650
34859
|
render: { sections: [{ title: "run logs", lines: entries }] }
|
|
@@ -34656,6 +34865,37 @@ async function handleRunLogs(args) {
|
|
|
34656
34865
|
);
|
|
34657
34866
|
return 0;
|
|
34658
34867
|
}
|
|
34868
|
+
function selectRunLogTailPage(result, logLevel, limit) {
|
|
34869
|
+
if (logLevel === "debug") {
|
|
34870
|
+
return {
|
|
34871
|
+
entries: [...result.entries],
|
|
34872
|
+
firstSequence: result.firstSequence,
|
|
34873
|
+
lastSequence: result.lastSequence,
|
|
34874
|
+
truncated: result.truncated,
|
|
34875
|
+
hasMore: result.hasMore,
|
|
34876
|
+
nextCursor: result.nextCursor ?? null
|
|
34877
|
+
};
|
|
34878
|
+
}
|
|
34879
|
+
const first = result.firstSequence;
|
|
34880
|
+
if (result.entries.length > 0 && (first === null || result.lastSequence === null || result.lastSequence - first + 1 !== result.entries.length)) {
|
|
34881
|
+
throw new Error(
|
|
34882
|
+
`Run log window is not contiguous (sequences ${first}..${result.lastSequence} for ${result.entries.length} lines); cannot page by severity.`
|
|
34883
|
+
);
|
|
34884
|
+
}
|
|
34885
|
+
const matching = result.entries.map((line, index) => ({ line, seq: first + index })).filter(
|
|
34886
|
+
(entry) => logLevelReaches(classifyLogLine(entry.line).level, logLevel)
|
|
34887
|
+
);
|
|
34888
|
+
const selected = matching.slice(-limit);
|
|
34889
|
+
const olderMatchesExist = matching.length > selected.length;
|
|
34890
|
+
return {
|
|
34891
|
+
entries: selected.map((entry) => entry.line),
|
|
34892
|
+
firstSequence: selected[0]?.seq ?? null,
|
|
34893
|
+
lastSequence: selected.at(-1)?.seq ?? null,
|
|
34894
|
+
truncated: result.truncated || olderMatchesExist,
|
|
34895
|
+
hasMore: olderMatchesExist,
|
|
34896
|
+
nextCursor: olderMatchesExist ? encodeRunLogsCursor(selected[0].seq) : null
|
|
34897
|
+
};
|
|
34898
|
+
}
|
|
34659
34899
|
async function handleRunEventSearch(args) {
|
|
34660
34900
|
const usage2 = "Usage: deepline runs logs [run-id] [--since ISO] [--until ISO] [--play name] [--kind kind] [--where jsonpath] [--payloads] [--cursor token] [--limit 100] [--json]";
|
|
34661
34901
|
const values = {};
|
|
@@ -34821,6 +35061,14 @@ function buildRunLogsText(result) {
|
|
|
34821
35061
|
}
|
|
34822
35062
|
return `${lines.join("\n")}${lines.length > 0 ? "\n" : ""}`;
|
|
34823
35063
|
}
|
|
35064
|
+
function resolveRunStopState(result) {
|
|
35065
|
+
if (result.state) return result.state;
|
|
35066
|
+
if (result.cancelling === true) return "cancelling";
|
|
35067
|
+
if (result.stopped === false || result.staleSchedulerState === true) {
|
|
35068
|
+
return "failed";
|
|
35069
|
+
}
|
|
35070
|
+
return "stopped";
|
|
35071
|
+
}
|
|
34824
35072
|
async function handleRunStop(args) {
|
|
34825
35073
|
const usage2 = 'Usage: deepline runs stop <run-id> [--reason "text"] [--json]';
|
|
34826
35074
|
let runId;
|
|
@@ -34839,15 +35087,25 @@ async function handleRunStop(args) {
|
|
|
34839
35087
|
}
|
|
34840
35088
|
const client2 = new DeeplineClient();
|
|
34841
35089
|
const result = await client2.runs.stop(runId, { reason });
|
|
34842
|
-
|
|
35090
|
+
const state = resolveRunStopState(result);
|
|
35091
|
+
const hitlCleanupIncomplete = state === "cancelling" && result.hitlCancellationPending === true;
|
|
35092
|
+
if (state === "cancelling" && !hitlCleanupIncomplete) {
|
|
35093
|
+
const {
|
|
35094
|
+
error: _legacyError,
|
|
35095
|
+
staleSchedulerState: _legacyStale,
|
|
35096
|
+
...cancelling
|
|
35097
|
+
} = result;
|
|
34843
35098
|
const lines2 = [
|
|
34844
|
-
`
|
|
35099
|
+
`Cancelling run ${result.runId || runId}; sandbox cleanup and the final run update are pending.`,
|
|
34845
35100
|
...result.hitlCancelledCount > 0 ? [`cancelled HITL waits: ${result.hitlCancelledCount}`] : [],
|
|
34846
35101
|
`inspect: deepline runs get ${runId} --full --json`
|
|
34847
35102
|
];
|
|
34848
35103
|
printCommandEnvelope(
|
|
34849
35104
|
{
|
|
34850
|
-
...
|
|
35105
|
+
...cancelling,
|
|
35106
|
+
state,
|
|
35107
|
+
stopped: false,
|
|
35108
|
+
cancelling: true,
|
|
34851
35109
|
render: {
|
|
34852
35110
|
sections: [
|
|
34853
35111
|
{
|
|
@@ -34861,9 +35119,8 @@ async function handleRunStop(args) {
|
|
|
34861
35119
|
);
|
|
34862
35120
|
return 0;
|
|
34863
35121
|
}
|
|
34864
|
-
|
|
34865
|
-
|
|
34866
|
-
const detail = typeof result.error === "string" && result.error.trim() ? result.error.trim() : result.staleSchedulerState === true ? "scheduler state for the run is stale" : "the server did not confirm the stop";
|
|
35122
|
+
if (state === "failed" || hitlCleanupIncomplete) {
|
|
35123
|
+
const detail = typeof result.error === "string" && result.error.trim() ? result.error.trim() : hitlCleanupIncomplete ? "cancellation is queued, but HITL cleanup is still pending" : result.staleSchedulerState === true ? "scheduler state for the run is stale" : "the server did not confirm the stop";
|
|
34867
35124
|
const lines2 = [
|
|
34868
35125
|
`Failed to stop run ${runId}: ${detail}.`,
|
|
34869
35126
|
...result.hitlCancelledCount > 0 ? [`cancelled HITL waits: ${result.hitlCancelledCount}`] : [],
|
|
@@ -36884,15 +37141,15 @@ Examples:
|
|
|
36884
37141
|
...options.json ? ["--json"] : []
|
|
36885
37142
|
]);
|
|
36886
37143
|
});
|
|
36887
|
-
const runs = program.command("runs").description("Inspect,
|
|
37144
|
+
const runs = program.command("runs").description("Inspect, watch, stop, and export play runs.").addHelpText(
|
|
36888
37145
|
"after",
|
|
36889
37146
|
`
|
|
36890
37147
|
Concepts:
|
|
36891
37148
|
A run is one execution instance of a play. It has status, progress, logs,
|
|
36892
37149
|
returned result, dataset previews, recovery metadata, and optional dataset export.
|
|
36893
37150
|
plays run starts NEW work and follows it by default; --no-wait returns immediately.
|
|
36894
|
-
runs
|
|
36895
|
-
Use
|
|
37151
|
+
runs watch attaches to EXISTING work and follows progress without starting a run.
|
|
37152
|
+
Use watch after a disconnect or --no-wait; do not launch again to reconnect.
|
|
36896
37153
|
get reads the current overview once. logs fetches persisted log history.
|
|
36897
37154
|
stop requests cancellation. rerun starts new work and may spend credits.
|
|
36898
37155
|
|
|
@@ -36906,14 +37163,15 @@ Retrieve results:
|
|
|
36906
37163
|
not JSON rows. For a JSON row file, use --format json --out results.json.
|
|
36907
37164
|
|
|
36908
37165
|
Follow existing work:
|
|
36909
|
-
deepline runs
|
|
36910
|
-
|
|
36911
|
-
|
|
37166
|
+
deepline runs watch <run-id>
|
|
37167
|
+
watch --json waits for one terminal JSON document; --jsonl streams live events.
|
|
37168
|
+
runs tail is an alias of runs watch.
|
|
36912
37169
|
|
|
36913
37170
|
More options:
|
|
36914
37171
|
deepline runs get -h
|
|
36915
37172
|
deepline runs children -h
|
|
36916
37173
|
deepline runs tail -h
|
|
37174
|
+
deepline runs watch -h
|
|
36917
37175
|
deepline runs export -h
|
|
36918
37176
|
deepline plays -h
|
|
36919
37177
|
|
|
@@ -36960,6 +37218,7 @@ Notes:
|
|
|
36960
37218
|
Run activity and status evidence retain provider cooldown and call progress.
|
|
36961
37219
|
Use --input only when you intentionally need the original payload; it can
|
|
36962
37220
|
contain customer data and is never included in ordinary status output.
|
|
37221
|
+
--config reads only the recorded graph and source; it never uses current Play code.
|
|
36963
37222
|
--json run.status,datasets.name,actions selects fields without flattening.
|
|
36964
37223
|
Selection changes stdout only, not the server query. Optional missing paths
|
|
36965
37224
|
are omitted; array positions are preserved. --json diagnostics needs --full.
|
|
@@ -36971,6 +37230,7 @@ Examples:
|
|
|
36971
37230
|
deepline runs get play/my-play/run/20260501t000000-000 --log-failed --json
|
|
36972
37231
|
deepline runs get play/my-play/run/20260501t000000-000 --full --json
|
|
36973
37232
|
deepline runs get play/my-play/run/20260501t000000-000 --input
|
|
37233
|
+
deepline runs get play/my-play/run/20260501t000000-000 --config --json
|
|
36974
37234
|
`
|
|
36975
37235
|
).option(
|
|
36976
37236
|
"--json [fields]",
|
|
@@ -36981,6 +37241,9 @@ Examples:
|
|
|
36981
37241
|
).option(
|
|
36982
37242
|
"--input",
|
|
36983
37243
|
"Explicitly print the original retained input JSON (may contain customer data)"
|
|
37244
|
+
).option(
|
|
37245
|
+
"--config",
|
|
37246
|
+
"Explicitly print the recorded configuration, without full results"
|
|
36984
37247
|
).option(
|
|
36985
37248
|
"--log-failed",
|
|
36986
37249
|
"Attach a bounded terminal-failure log window for failed runs"
|
|
@@ -36990,6 +37253,7 @@ Examples:
|
|
|
36990
37253
|
...jsonFieldArgs(options.json),
|
|
36991
37254
|
...options.full ? ["--full"] : [],
|
|
36992
37255
|
...options.input ? ["--input"] : [],
|
|
37256
|
+
...options.config ? ["--config"] : [],
|
|
36993
37257
|
...options.logFailed ? ["--log-failed"] : []
|
|
36994
37258
|
]);
|
|
36995
37259
|
});
|
|
@@ -37157,7 +37421,10 @@ Examples:
|
|
|
37157
37421
|
).option(
|
|
37158
37422
|
"--payloads",
|
|
37159
37423
|
"Search with canonical eventPayload or receipt payload; max 10 events, 16 MiB"
|
|
37160
|
-
).option(
|
|
37424
|
+
).option(
|
|
37425
|
+
"--cursor <token>",
|
|
37426
|
+
"Continue paging: older run-log lines (nextCursor) or a bounded event search"
|
|
37427
|
+
).option(
|
|
37161
37428
|
"--runtime-namespace <name>",
|
|
37162
37429
|
"Search an explicitly authorized Preview namespace"
|
|
37163
37430
|
).option("--runtime-backend <backend>", "Preview backend: daytona or modal").action(async (runId, options) => {
|