deepline 0.1.176 → 0.1.177
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/release.ts +5 -4
- package/dist/cli/index.js +454 -55
- package/dist/cli/index.mjs +462 -63
- package/dist/index.js +5 -4
- package/dist/index.mjs +5 -4
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -622,17 +622,18 @@ var SDK_RELEASE = {
|
|
|
622
622
|
// 0.1.111 ships dataset-native tool list getters and result row datasets.
|
|
623
623
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
624
624
|
// fields shipped in 0.1.153.
|
|
625
|
-
|
|
625
|
+
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
626
|
+
version: "0.1.177",
|
|
626
627
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
627
628
|
supportPolicy: {
|
|
628
|
-
latest: "0.1.
|
|
629
|
+
latest: "0.1.177",
|
|
629
630
|
minimumSupported: "0.1.53",
|
|
630
631
|
deprecatedBelow: "0.1.53",
|
|
631
632
|
commandMinimumSupported: [
|
|
632
633
|
{
|
|
633
634
|
command: "enrich",
|
|
634
|
-
minimumSupported: "0.1.
|
|
635
|
-
reason: "Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source."
|
|
635
|
+
minimumSupported: "0.1.175",
|
|
636
|
+
reason: "Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows."
|
|
636
637
|
},
|
|
637
638
|
{
|
|
638
639
|
command: "plays",
|
|
@@ -17839,14 +17840,39 @@ function enrichOutputJson(exportResult) {
|
|
|
17839
17840
|
...exportResult.partial ? { rows: exportResult.rows, partial: true } : {}
|
|
17840
17841
|
};
|
|
17841
17842
|
}
|
|
17843
|
+
function enrichReportJson(report) {
|
|
17844
|
+
if (!report) {
|
|
17845
|
+
return {};
|
|
17846
|
+
}
|
|
17847
|
+
return {
|
|
17848
|
+
...report.jobs.length > 0 ? {
|
|
17849
|
+
failure_report: {
|
|
17850
|
+
path: report.path,
|
|
17851
|
+
jobs: report.jobs.length
|
|
17852
|
+
}
|
|
17853
|
+
} : {},
|
|
17854
|
+
...report.issues.length > 0 ? {
|
|
17855
|
+
enrich_issues: {
|
|
17856
|
+
path: report.path,
|
|
17857
|
+
issues: report.issues.length,
|
|
17858
|
+
items: report.issues
|
|
17859
|
+
}
|
|
17860
|
+
} : {}
|
|
17861
|
+
};
|
|
17862
|
+
}
|
|
17842
17863
|
async function buildEnrichFailureReport(input2) {
|
|
17864
|
+
const fallbackRowsInfo = input2.exportResult ? null : extractCanonicalRowsInfo(input2.status);
|
|
17843
17865
|
return maybeEmitEnrichFailureReport({
|
|
17844
17866
|
config: input2.config,
|
|
17845
17867
|
rows: input2.rows,
|
|
17846
17868
|
rowRange: input2.rowRange,
|
|
17847
17869
|
client: input2.client,
|
|
17848
17870
|
outputPath: input2.reportOutputPath ?? input2.exportResult?.path ?? input2.outputPath ?? null,
|
|
17849
|
-
|
|
17871
|
+
followUpOutputPath: input2.followUpOutputPath,
|
|
17872
|
+
status: input2.status,
|
|
17873
|
+
rowSetComplete: input2.exportResult ? !input2.exportResult.partial : Boolean(
|
|
17874
|
+
fallbackRowsInfo?.complete && input2.rows.length >= fallbackRowsInfo.totalRows
|
|
17875
|
+
)
|
|
17850
17876
|
});
|
|
17851
17877
|
}
|
|
17852
17878
|
function recordField(value, key) {
|
|
@@ -18123,7 +18149,7 @@ function emitPlainBatchRunFailure(input2) {
|
|
|
18123
18149
|
`Batch ${input2.chunkIndex + 1}/${input2.chunkCount} failed for rows ${input2.rows.rowStart}:${input2.rows.rowEnd}.
|
|
18124
18150
|
`
|
|
18125
18151
|
);
|
|
18126
|
-
const runId = extractRunId(input2.status);
|
|
18152
|
+
const runId = extractRunId(input2.status) ?? firstCollectedStringField(input2.status, "runId");
|
|
18127
18153
|
const error = firstCollectedStringField(input2.status, "error") ?? firstCollectedStringField(input2.status, "message");
|
|
18128
18154
|
if (runId) {
|
|
18129
18155
|
process.stderr.write(`Run id: ${runId}
|
|
@@ -18339,6 +18365,38 @@ function collectHardFailureAliasSpecs(config) {
|
|
|
18339
18365
|
}
|
|
18340
18366
|
return aliases;
|
|
18341
18367
|
}
|
|
18368
|
+
function collectWaterfallAliasSpecs(config) {
|
|
18369
|
+
const aliases = [];
|
|
18370
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18371
|
+
for (const command of config.commands) {
|
|
18372
|
+
if (!("with_waterfall" in command)) {
|
|
18373
|
+
continue;
|
|
18374
|
+
}
|
|
18375
|
+
const alias = command.with_waterfall.trim();
|
|
18376
|
+
if (!alias || seen.has(alias)) {
|
|
18377
|
+
continue;
|
|
18378
|
+
}
|
|
18379
|
+
const activeChildren = command.commands.filter(
|
|
18380
|
+
(child) => !("with_waterfall" in child) && !child.disabled
|
|
18381
|
+
);
|
|
18382
|
+
if (activeChildren.length === 0) {
|
|
18383
|
+
continue;
|
|
18384
|
+
}
|
|
18385
|
+
seen.add(alias);
|
|
18386
|
+
const childOperations = activeChildren.map((child) => child.operation?.trim() || child.tool.trim()).filter(Boolean);
|
|
18387
|
+
aliases.push({
|
|
18388
|
+
alias,
|
|
18389
|
+
childAliases: activeChildren.map((child) => child.alias).filter(Boolean),
|
|
18390
|
+
childToolsByAlias: new Map(
|
|
18391
|
+
activeChildren.map(
|
|
18392
|
+
(child) => [child.alias, child.tool.trim()]
|
|
18393
|
+
)
|
|
18394
|
+
),
|
|
18395
|
+
operation: childOperations.length > 0 ? childOperations.join(", ") : void 0
|
|
18396
|
+
});
|
|
18397
|
+
}
|
|
18398
|
+
return aliases;
|
|
18399
|
+
}
|
|
18342
18400
|
function hardFailureOperationByAlias(config) {
|
|
18343
18401
|
const operations = /* @__PURE__ */ new Map();
|
|
18344
18402
|
if (!config) {
|
|
@@ -18351,6 +18409,60 @@ function hardFailureOperationByAlias(config) {
|
|
|
18351
18409
|
}
|
|
18352
18410
|
return operations;
|
|
18353
18411
|
}
|
|
18412
|
+
function isWaterfallResultMeaningful(value) {
|
|
18413
|
+
if (Array.isArray(value)) {
|
|
18414
|
+
return value.some(isWaterfallResultMeaningful);
|
|
18415
|
+
}
|
|
18416
|
+
if (value && typeof value === "object") {
|
|
18417
|
+
const record = value;
|
|
18418
|
+
const status = typeof record.status === "string" ? record.status.trim().toLowerCase() : "";
|
|
18419
|
+
if (status === "error" || status === "failed") {
|
|
18420
|
+
return false;
|
|
18421
|
+
}
|
|
18422
|
+
if (typeof record.error === "string" && record.error.trim()) {
|
|
18423
|
+
return false;
|
|
18424
|
+
}
|
|
18425
|
+
if (Object.prototype.hasOwnProperty.call(record, "matched_result")) {
|
|
18426
|
+
return isWaterfallResultMeaningful(record.matched_result);
|
|
18427
|
+
}
|
|
18428
|
+
for (const key of [
|
|
18429
|
+
"value",
|
|
18430
|
+
"email",
|
|
18431
|
+
"phone",
|
|
18432
|
+
"phone_number",
|
|
18433
|
+
"mobile_phone",
|
|
18434
|
+
"mobile_phone_number",
|
|
18435
|
+
"url",
|
|
18436
|
+
"domain",
|
|
18437
|
+
"name",
|
|
18438
|
+
"result",
|
|
18439
|
+
"data"
|
|
18440
|
+
]) {
|
|
18441
|
+
if (isWaterfallResultMeaningful(record[key])) {
|
|
18442
|
+
return true;
|
|
18443
|
+
}
|
|
18444
|
+
}
|
|
18445
|
+
return Object.entries(record).some(
|
|
18446
|
+
([key, entry]) => !ENRICH_FLATTENED_CONTROL_FIELDS.has(key) && isWaterfallResultMeaningful(entry)
|
|
18447
|
+
);
|
|
18448
|
+
}
|
|
18449
|
+
return isNonEmptyCsvCell(value);
|
|
18450
|
+
}
|
|
18451
|
+
function aliasHasMeaningfulResult(row, alias) {
|
|
18452
|
+
return aliasFailureCellCandidates(row, alias).some(
|
|
18453
|
+
isWaterfallResultMeaningful
|
|
18454
|
+
);
|
|
18455
|
+
}
|
|
18456
|
+
function stableRowSnapshot(value) {
|
|
18457
|
+
if (Array.isArray(value)) {
|
|
18458
|
+
return `[${value.map(stableRowSnapshot).join(",")}]`;
|
|
18459
|
+
}
|
|
18460
|
+
if (value && typeof value === "object") {
|
|
18461
|
+
const record = value;
|
|
18462
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableRowSnapshot(record[key])}`).join(",")}}`;
|
|
18463
|
+
}
|
|
18464
|
+
return JSON.stringify(value);
|
|
18465
|
+
}
|
|
18354
18466
|
function cellFailureError(value) {
|
|
18355
18467
|
const parsed = parseMaybeJsonObject(value);
|
|
18356
18468
|
if (!isRecord7(parsed)) {
|
|
@@ -18496,6 +18608,112 @@ function collectEnrichFailureJobs(input2) {
|
|
|
18496
18608
|
});
|
|
18497
18609
|
return jobs;
|
|
18498
18610
|
}
|
|
18611
|
+
function collectEmptyWaterfallIssues(input2) {
|
|
18612
|
+
const aliases = collectWaterfallAliasSpecs(input2.config);
|
|
18613
|
+
if (aliases.length === 0 || input2.rows.length === 0 || !input2.rowSetComplete) {
|
|
18614
|
+
return [];
|
|
18615
|
+
}
|
|
18616
|
+
const runId = extractRunId(input2.status) ?? firstCollectedStringField(input2.status, "runId");
|
|
18617
|
+
const followUpCommands = collectEnrichFollowUpCommands({
|
|
18618
|
+
status: input2.status,
|
|
18619
|
+
runId,
|
|
18620
|
+
outputPath: input2.followUpOutputPath ?? input2.outputPath
|
|
18621
|
+
});
|
|
18622
|
+
const issues = [];
|
|
18623
|
+
aliases.forEach((spec) => {
|
|
18624
|
+
if (waterfallExecutionSignal(input2.status, spec) === "all_condition_skipped") {
|
|
18625
|
+
return;
|
|
18626
|
+
}
|
|
18627
|
+
const logicalRows = /* @__PURE__ */ new Map();
|
|
18628
|
+
input2.rows.forEach((row, rowIndex) => {
|
|
18629
|
+
const sourceRowId = sourceRowIndexFromEnrichRow(
|
|
18630
|
+
row,
|
|
18631
|
+
0,
|
|
18632
|
+
Number.MAX_SAFE_INTEGER
|
|
18633
|
+
);
|
|
18634
|
+
const rowKey = sourceRowId !== null ? `source:${sourceRowId}` : `snapshot:${stableRowSnapshot(row)}`;
|
|
18635
|
+
const existing = logicalRows.get(rowKey);
|
|
18636
|
+
const hasMeaningfulResult = aliasHasMeaningfulResult(row, spec.alias);
|
|
18637
|
+
logicalRows.set(rowKey, {
|
|
18638
|
+
hasMeaningfulResult: (existing?.hasMeaningfulResult ?? false) || hasMeaningfulResult
|
|
18639
|
+
});
|
|
18640
|
+
});
|
|
18641
|
+
const emptyRows = Array.from(logicalRows.values()).filter(
|
|
18642
|
+
(row) => !row.hasMeaningfulResult
|
|
18643
|
+
);
|
|
18644
|
+
if (emptyRows.length !== logicalRows.size) {
|
|
18645
|
+
return;
|
|
18646
|
+
}
|
|
18647
|
+
const selectedRows = logicalRows.size;
|
|
18648
|
+
const message = `Waterfall ${spec.alias} produced 0 values for ${selectedRows} selected row(s).`;
|
|
18649
|
+
issues.push({
|
|
18650
|
+
issue_id: `${spec.alias}-empty-waterfall`,
|
|
18651
|
+
kind: "empty_waterfall",
|
|
18652
|
+
severity: "needs_attention",
|
|
18653
|
+
column: spec.alias,
|
|
18654
|
+
selected_rows: selectedRows,
|
|
18655
|
+
rows_with_value: 0,
|
|
18656
|
+
rows_without_value: selectedRows,
|
|
18657
|
+
message,
|
|
18658
|
+
next_steps: enrichIssueNextSteps({ runId }),
|
|
18659
|
+
follow_up_commands: followUpCommands,
|
|
18660
|
+
...spec.operation ? { operation: spec.operation } : {},
|
|
18661
|
+
...runId ? { run_id: runId } : {}
|
|
18662
|
+
});
|
|
18663
|
+
});
|
|
18664
|
+
return issues;
|
|
18665
|
+
}
|
|
18666
|
+
function waterfallExecutionSignal(status, spec) {
|
|
18667
|
+
const childAliases = spec.childAliases ?? [];
|
|
18668
|
+
if (childAliases.length === 0) {
|
|
18669
|
+
return "unknown";
|
|
18670
|
+
}
|
|
18671
|
+
const summaries = collectColumnStats(status);
|
|
18672
|
+
let sawChildStats = false;
|
|
18673
|
+
let everyChildStatOnlyConditionSkipped = true;
|
|
18674
|
+
const childAliasesWithStats = /* @__PURE__ */ new Set();
|
|
18675
|
+
for (const childAlias of childAliases) {
|
|
18676
|
+
for (const stat2 of summaries.map((summary) => summary[childAlias]).filter(isRecord7)) {
|
|
18677
|
+
sawChildStats = true;
|
|
18678
|
+
childAliasesWithStats.add(childAlias);
|
|
18679
|
+
const execution = isRecord7(stat2.execution) ? stat2.execution : null;
|
|
18680
|
+
const executedSummary = parseExecutionSummary(
|
|
18681
|
+
execution?.["completed:executed"]
|
|
18682
|
+
);
|
|
18683
|
+
const skippedConditionSummary = parseExecutionSummary(
|
|
18684
|
+
execution?.["skipped:condition"]
|
|
18685
|
+
);
|
|
18686
|
+
const executedCount = executedSummary?.count ?? 0;
|
|
18687
|
+
const skippedConditionCount = skippedConditionSummary?.count ?? 0;
|
|
18688
|
+
const totalCount = executedSummary?.total ?? skippedConditionSummary?.total;
|
|
18689
|
+
const onlyConditionSkips = totalCount !== void 0 && skippedConditionCount >= totalCount && executedCount <= skippedConditionCount;
|
|
18690
|
+
if (executedCount > 0 && !onlyConditionSkips || numericFailedRowSignal(execution?.failed) > 0 || numericFailedRowSignal(stat2.failed) > 0 || numericFailedRowSignal(stat2.failedRows) > 0) {
|
|
18691
|
+
return "executed";
|
|
18692
|
+
}
|
|
18693
|
+
if (!onlyConditionSkips) {
|
|
18694
|
+
everyChildStatOnlyConditionSkipped = false;
|
|
18695
|
+
}
|
|
18696
|
+
}
|
|
18697
|
+
}
|
|
18698
|
+
if (sawChildStats && childAliasesWithStats.size === childAliases.length && everyChildStatOnlyConditionSkipped) {
|
|
18699
|
+
return "all_condition_skipped";
|
|
18700
|
+
}
|
|
18701
|
+
return "unknown";
|
|
18702
|
+
}
|
|
18703
|
+
function mergeEnrichFailureJobs(...jobGroups) {
|
|
18704
|
+
const merged = [];
|
|
18705
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18706
|
+
for (const jobs of jobGroups) {
|
|
18707
|
+
for (const job of jobs) {
|
|
18708
|
+
if (seen.has(job.job_id)) {
|
|
18709
|
+
continue;
|
|
18710
|
+
}
|
|
18711
|
+
seen.add(job.job_id);
|
|
18712
|
+
merged.push(job);
|
|
18713
|
+
}
|
|
18714
|
+
}
|
|
18715
|
+
return merged;
|
|
18716
|
+
}
|
|
18499
18717
|
function collectStatusFailureJobs(input2) {
|
|
18500
18718
|
const aliases = collectHardFailureAliasSpecs(input2.config);
|
|
18501
18719
|
if (aliases.length === 0) {
|
|
@@ -18589,14 +18807,23 @@ function collectCompleteStatusFailureMessages(input2) {
|
|
|
18589
18807
|
return complete;
|
|
18590
18808
|
}
|
|
18591
18809
|
function parseExecutionCount(value) {
|
|
18810
|
+
return parseExecutionSummary(value)?.count ?? null;
|
|
18811
|
+
}
|
|
18812
|
+
function parseExecutionSummary(value) {
|
|
18592
18813
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
18593
|
-
return Math.max(0, Math.trunc(value));
|
|
18814
|
+
return { count: Math.max(0, Math.trunc(value)) };
|
|
18594
18815
|
}
|
|
18595
18816
|
if (typeof value !== "string") {
|
|
18596
18817
|
return null;
|
|
18597
18818
|
}
|
|
18598
|
-
const match = value.trim().match(/^(\d+)\
|
|
18599
|
-
|
|
18819
|
+
const match = value.trim().match(/^(\d+)(?:\s*\/\s*(\d+))?/);
|
|
18820
|
+
if (!match?.[1]) {
|
|
18821
|
+
return null;
|
|
18822
|
+
}
|
|
18823
|
+
return {
|
|
18824
|
+
count: Number.parseInt(match[1], 10),
|
|
18825
|
+
...match[2] ? { total: Number.parseInt(match[2], 10) } : {}
|
|
18826
|
+
};
|
|
18600
18827
|
}
|
|
18601
18828
|
function executionSummaryText(count, total) {
|
|
18602
18829
|
const percent = total > 0 ? Math.round(count / total * 100) : 0;
|
|
@@ -18722,19 +18949,145 @@ function summarizeFailedJobError(value) {
|
|
|
18722
18949
|
const text = String(value ?? "").trim();
|
|
18723
18950
|
return text.length > 500 ? `${text.slice(0, 497)}...` : text;
|
|
18724
18951
|
}
|
|
18952
|
+
function shellSingleQuote2(value) {
|
|
18953
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
18954
|
+
}
|
|
18955
|
+
function addEnrichFollowUpCommand(commands, seen, command) {
|
|
18956
|
+
const normalized = command.command.trim();
|
|
18957
|
+
if (!normalized || seen.has(normalized)) {
|
|
18958
|
+
return;
|
|
18959
|
+
}
|
|
18960
|
+
seen.add(normalized);
|
|
18961
|
+
commands.push({ ...command, command: normalized });
|
|
18962
|
+
}
|
|
18963
|
+
function datasetSelectorForEnrichCommand(record, fallbackPath) {
|
|
18964
|
+
const candidates = [record.path, record.tableNamespace, fallbackPath];
|
|
18965
|
+
for (const candidate of candidates) {
|
|
18966
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
18967
|
+
return candidate.trim();
|
|
18968
|
+
}
|
|
18969
|
+
}
|
|
18970
|
+
return null;
|
|
18971
|
+
}
|
|
18972
|
+
function collectEnrichFollowUpCommands(input2) {
|
|
18973
|
+
const commands = [];
|
|
18974
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18975
|
+
if (input2.runId) {
|
|
18976
|
+
addEnrichFollowUpCommand(commands, seen, {
|
|
18977
|
+
label: "inspect run",
|
|
18978
|
+
command: `deepline runs get ${input2.runId} --full --json`
|
|
18979
|
+
});
|
|
18980
|
+
}
|
|
18981
|
+
collectDatasetFollowUpCommands(input2.status, {
|
|
18982
|
+
runId: input2.runId,
|
|
18983
|
+
outputPath: input2.outputPath,
|
|
18984
|
+
commands,
|
|
18985
|
+
seen,
|
|
18986
|
+
path: "result",
|
|
18987
|
+
depth: 0
|
|
18988
|
+
});
|
|
18989
|
+
if (input2.runId && input2.outputPath && !commands.some((command) => command.label === "export enrich rows")) {
|
|
18990
|
+
addEnrichFollowUpCommand(commands, seen, {
|
|
18991
|
+
label: "export enrich rows",
|
|
18992
|
+
path: GENERATED_ENRICH_ROWS_TABLE_NAMESPACE,
|
|
18993
|
+
command: `deepline runs export ${input2.runId} --dataset ${GENERATED_ENRICH_ROWS_TABLE_NAMESPACE} --out ${shellSingleQuote2(
|
|
18994
|
+
(0, import_node_path12.resolve)(input2.outputPath)
|
|
18995
|
+
)}`
|
|
18996
|
+
});
|
|
18997
|
+
}
|
|
18998
|
+
return commands.slice(0, 8);
|
|
18999
|
+
}
|
|
19000
|
+
function sidecarEnrichRowsExportPath(outputPath) {
|
|
19001
|
+
const resolved = (0, import_node_path12.resolve)(outputPath);
|
|
19002
|
+
const ext = (0, import_node_path12.extname)(resolved) || ".csv";
|
|
19003
|
+
const stem = (0, import_node_path12.basename)(resolved, ext);
|
|
19004
|
+
return (0, import_node_path12.join)((0, import_node_path12.dirname)(resolved), `${stem}.deepline-enrich-rows${ext}`);
|
|
19005
|
+
}
|
|
19006
|
+
function collectDatasetFollowUpCommands(value, state) {
|
|
19007
|
+
if (state.depth > 12 || !value || typeof value !== "object" || state.commands.length >= 8) {
|
|
19008
|
+
return;
|
|
19009
|
+
}
|
|
19010
|
+
if (Array.isArray(value)) {
|
|
19011
|
+
value.slice(0, 50).forEach(
|
|
19012
|
+
(entry, index) => collectDatasetFollowUpCommands(entry, {
|
|
19013
|
+
...state,
|
|
19014
|
+
path: `${state.path}.${index}`,
|
|
19015
|
+
depth: state.depth + 1
|
|
19016
|
+
})
|
|
19017
|
+
);
|
|
19018
|
+
return;
|
|
19019
|
+
}
|
|
19020
|
+
const record = value;
|
|
19021
|
+
const isDataset = record.kind === "dataset";
|
|
19022
|
+
if (isDataset) {
|
|
19023
|
+
const selector = datasetSelectorForEnrichCommand(record, state.path);
|
|
19024
|
+
const labelPath = typeof record.path === "string" && record.path.trim() ? record.path.trim() : selector ?? state.path;
|
|
19025
|
+
if (typeof record.queryDatasetCommand === "string") {
|
|
19026
|
+
addEnrichFollowUpCommand(state.commands, state.seen, {
|
|
19027
|
+
label: `query ${labelPath}`,
|
|
19028
|
+
path: labelPath,
|
|
19029
|
+
command: record.queryDatasetCommand
|
|
19030
|
+
});
|
|
19031
|
+
}
|
|
19032
|
+
const exportCommand = typeof record.slowExportAsCsvCommand === "string" ? record.slowExportAsCsvCommand : typeof record.fullExportCommand === "string" ? record.fullExportCommand : null;
|
|
19033
|
+
if (exportCommand) {
|
|
19034
|
+
addEnrichFollowUpCommand(state.commands, state.seen, {
|
|
19035
|
+
label: `export ${labelPath}`,
|
|
19036
|
+
path: labelPath,
|
|
19037
|
+
command: exportCommand
|
|
19038
|
+
});
|
|
19039
|
+
} else if (state.runId && state.outputPath && selector) {
|
|
19040
|
+
addEnrichFollowUpCommand(state.commands, state.seen, {
|
|
19041
|
+
label: selector === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE ? "export enrich rows" : `export ${labelPath}`,
|
|
19042
|
+
path: selector,
|
|
19043
|
+
command: `deepline runs export ${state.runId} --dataset ${shellSingleQuote2(
|
|
19044
|
+
selector
|
|
19045
|
+
)} --out ${shellSingleQuote2((0, import_node_path12.resolve)(state.outputPath))}`
|
|
19046
|
+
});
|
|
19047
|
+
}
|
|
19048
|
+
}
|
|
19049
|
+
for (const [key, child] of Object.entries(record)) {
|
|
19050
|
+
if (key === "preview" || key === "access") {
|
|
19051
|
+
continue;
|
|
19052
|
+
}
|
|
19053
|
+
collectDatasetFollowUpCommands(child, {
|
|
19054
|
+
...state,
|
|
19055
|
+
path: `${state.path}.${key}`,
|
|
19056
|
+
depth: state.depth + 1
|
|
19057
|
+
});
|
|
19058
|
+
if (state.commands.length >= 8) {
|
|
19059
|
+
return;
|
|
19060
|
+
}
|
|
19061
|
+
}
|
|
19062
|
+
}
|
|
19063
|
+
function enrichIssueNextSteps(input2) {
|
|
19064
|
+
const steps = [
|
|
19065
|
+
"Inspect the run output and returned dataset handles.",
|
|
19066
|
+
"If runs get returns queryDatasetCommand or slowExportAsCsvCommand, run that command to fetch durable rows from the customer DB.",
|
|
19067
|
+
"For provider-backed waterfalls, execute the child provider tool on a sample row to confirm the provider returns the expected field."
|
|
19068
|
+
];
|
|
19069
|
+
if (!input2.runId) {
|
|
19070
|
+
return steps;
|
|
19071
|
+
}
|
|
19072
|
+
return [
|
|
19073
|
+
`Inspect run output: deepline runs get ${input2.runId} --full --json`,
|
|
19074
|
+
...steps.slice(1)
|
|
19075
|
+
];
|
|
19076
|
+
}
|
|
18725
19077
|
function formatFailureReportCommand(reportPath) {
|
|
18726
19078
|
const quoted = reportPath.replace(/'/g, `'\\''`);
|
|
18727
19079
|
return `Inspect failed jobs: jq -r '.jobs[] | [.job_id,.row_id,.col_index,.column,.status,.last_error] | @tsv' '${quoted}'`;
|
|
18728
19080
|
}
|
|
18729
19081
|
async function persistEnrichFailureReport(input2) {
|
|
18730
|
-
if (input2.jobs.length === 0) {
|
|
19082
|
+
if (input2.jobs.length === 0 && input2.issues.length === 0) {
|
|
18731
19083
|
return null;
|
|
18732
19084
|
}
|
|
18733
19085
|
const stateDir = (0, import_node_path12.join)((0, import_node_os8.homedir)(), ".local", "deepline", "runtime", "state");
|
|
19086
|
+
const reportPrefix = input2.jobs.length > 0 ? "run-block-failures" : "enrich-issues";
|
|
18734
19087
|
await (0, import_promises3.mkdir)(stateDir, { recursive: true });
|
|
18735
19088
|
const reportPath = (0, import_node_path12.join)(
|
|
18736
19089
|
stateDir,
|
|
18737
|
-
|
|
19090
|
+
`${reportPrefix}-${Math.floor(Date.now() / 1e3)}-${process.pid}.json`
|
|
18738
19091
|
);
|
|
18739
19092
|
const report = {
|
|
18740
19093
|
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -18749,6 +19102,7 @@ async function persistEnrichFailureReport(input2) {
|
|
|
18749
19102
|
},
|
|
18750
19103
|
jobs: input2.jobs,
|
|
18751
19104
|
failed_jobs: input2.jobs,
|
|
19105
|
+
enrich_issues: input2.issues,
|
|
18752
19106
|
canceled_jobs: [],
|
|
18753
19107
|
pending_jobs: [],
|
|
18754
19108
|
missing_job_ids: []
|
|
@@ -18761,48 +19115,100 @@ async function persistEnrichFailureReport(input2) {
|
|
|
18761
19115
|
return reportPath;
|
|
18762
19116
|
}
|
|
18763
19117
|
async function maybeEmitEnrichFailureReport(input2) {
|
|
19118
|
+
const fallbackRowsInfo = extractCanonicalRowsInfo(input2.status);
|
|
19119
|
+
const rowSetComplete = input2.rowSetComplete ?? Boolean(
|
|
19120
|
+
fallbackRowsInfo?.complete && input2.rows.length >= fallbackRowsInfo.totalRows
|
|
19121
|
+
);
|
|
18764
19122
|
const rowJobs = collectEnrichFailureJobs({
|
|
18765
19123
|
config: input2.config,
|
|
18766
19124
|
rows: input2.rows,
|
|
18767
19125
|
rowStart: input2.rowRange.rowStart
|
|
18768
19126
|
});
|
|
18769
|
-
const
|
|
19127
|
+
const enrichIssues = collectEmptyWaterfallIssues({
|
|
19128
|
+
config: input2.config,
|
|
19129
|
+
rows: input2.rows,
|
|
19130
|
+
status: input2.waterfallStatus ?? input2.status,
|
|
19131
|
+
outputPath: input2.outputPath,
|
|
19132
|
+
followUpOutputPath: input2.followUpOutputPath,
|
|
19133
|
+
rowSetComplete
|
|
19134
|
+
});
|
|
19135
|
+
const statusJobs = input2.status === void 0 || rowJobs.length > 0 ? [] : collectStatusFailureJobs({
|
|
18770
19136
|
config: input2.config,
|
|
18771
19137
|
status: input2.status,
|
|
18772
19138
|
rowRange: input2.statusRowRange ?? input2.rowRange
|
|
18773
19139
|
});
|
|
18774
|
-
|
|
19140
|
+
const jobs = rowJobs.length > 0 || statusJobs.length > 0 || input2.status === void 0 ? mergeEnrichFailureJobs(rowJobs, statusJobs) : [];
|
|
19141
|
+
if (jobs.length === 0 && enrichIssues.length === 0) {
|
|
18775
19142
|
return null;
|
|
18776
19143
|
}
|
|
18777
19144
|
const reportPath = await persistEnrichFailureReport({
|
|
18778
19145
|
jobs,
|
|
19146
|
+
issues: enrichIssues,
|
|
18779
19147
|
apiUrl: input2.client.baseUrl,
|
|
18780
19148
|
outputPath: input2.outputPath,
|
|
18781
19149
|
rows: input2.rowRange
|
|
18782
19150
|
});
|
|
18783
|
-
|
|
18784
|
-
|
|
18785
|
-
|
|
18786
|
-
|
|
18787
|
-
|
|
18788
|
-
|
|
19151
|
+
if (jobs.length > 0) {
|
|
19152
|
+
process.stderr.write("Execution failed.\n");
|
|
19153
|
+
process.stderr.write("Failure preview (up to 5 failed jobs):\n");
|
|
19154
|
+
process.stderr.write("job_id row_id col_index column status error\n");
|
|
19155
|
+
for (const job of jobs.slice(0, 5)) {
|
|
19156
|
+
process.stderr.write(
|
|
19157
|
+
`${job.job_id} ${job.row_id} ${job.col_index} ${job.column} ${job.status} ${summarizeFailedJobError(job.last_error)}
|
|
18789
19158
|
`
|
|
18790
|
-
|
|
19159
|
+
);
|
|
19160
|
+
}
|
|
19161
|
+
if (jobs.length > 5) {
|
|
19162
|
+
process.stderr.write(`Showing 5 of ${jobs.length} failed jobs.
|
|
19163
|
+
`);
|
|
19164
|
+
}
|
|
18791
19165
|
}
|
|
18792
|
-
if (
|
|
18793
|
-
process.stderr.write(
|
|
19166
|
+
if (enrichIssues.length > 0) {
|
|
19167
|
+
process.stderr.write("Enrichment needs attention.\n");
|
|
19168
|
+
process.stderr.write("Issue preview (up to 5 enrichment issues):\n");
|
|
19169
|
+
process.stderr.write(
|
|
19170
|
+
"issue_id column severity selected_rows rows_with_value message\n"
|
|
19171
|
+
);
|
|
19172
|
+
for (const issue of enrichIssues.slice(0, 5)) {
|
|
19173
|
+
process.stderr.write(
|
|
19174
|
+
`${issue.issue_id} ${issue.column} ${issue.severity} ${issue.selected_rows} ${issue.rows_with_value} ${issue.message}
|
|
19175
|
+
`
|
|
19176
|
+
);
|
|
19177
|
+
for (const step of issue.next_steps.slice(0, 2)) {
|
|
19178
|
+
process.stderr.write(`Next: ${step}
|
|
19179
|
+
`);
|
|
19180
|
+
}
|
|
19181
|
+
for (const command of issue.follow_up_commands.slice(0, 4)) {
|
|
19182
|
+
process.stderr.write(`Command: ${command.label}: ${command.command}
|
|
18794
19183
|
`);
|
|
19184
|
+
}
|
|
19185
|
+
}
|
|
19186
|
+
if (enrichIssues.length > 5) {
|
|
19187
|
+
process.stderr.write(
|
|
19188
|
+
`Showing 5 of ${enrichIssues.length} enrichment issues.
|
|
19189
|
+
`
|
|
19190
|
+
);
|
|
19191
|
+
}
|
|
18795
19192
|
}
|
|
18796
19193
|
if (reportPath) {
|
|
18797
|
-
|
|
19194
|
+
if (jobs.length > 0) {
|
|
19195
|
+
process.stderr.write(`Full failure report: ${reportPath}
|
|
18798
19196
|
`);
|
|
18799
|
-
|
|
19197
|
+
process.stderr.write(`${formatFailureReportCommand(reportPath)}
|
|
18800
19198
|
`);
|
|
18801
|
-
|
|
18802
|
-
|
|
19199
|
+
} else {
|
|
19200
|
+
process.stderr.write(`Full enrich report: ${reportPath}
|
|
19201
|
+
`);
|
|
19202
|
+
}
|
|
19203
|
+
process.stderr.write(
|
|
19204
|
+
jobs.length > 0 ? "Enrichment failed. See report above.\n" : "Enrichment produced no values for at least one requested waterfall. See issue preview above.\n"
|
|
19205
|
+
);
|
|
19206
|
+
return { path: reportPath, jobs, issues: enrichIssues };
|
|
18803
19207
|
}
|
|
18804
|
-
process.stderr.write(
|
|
18805
|
-
|
|
19208
|
+
process.stderr.write(
|
|
19209
|
+
jobs.length > 0 ? "Enrichment failed.\n" : "Enrichment needs attention.\n"
|
|
19210
|
+
);
|
|
19211
|
+
return { path: "", jobs, issues: enrichIssues };
|
|
18806
19212
|
}
|
|
18807
19213
|
function mergePreferredColumns(preferredColumns, rows) {
|
|
18808
19214
|
const columns = [];
|
|
@@ -19468,6 +19874,7 @@ function registerEnrichCommand(program) {
|
|
|
19468
19874
|
const inPlaceFinalOutputPath = options.inPlace ? (0, import_node_path12.resolve)(inputCsv) : null;
|
|
19469
19875
|
const inPlaceCommitOutputPath = options.inPlace ? (await (0, import_promises3.lstat)(inputCsv)).isSymbolicLink() ? await (0, import_promises3.realpath)(inputCsv) : inPlaceFinalOutputPath : null;
|
|
19470
19876
|
const failureReportOutputPath = options.inPlace ? inPlaceFinalOutputPath : null;
|
|
19877
|
+
const enrichIssueFollowUpOutputPath = options.inPlace && inPlaceFinalOutputPath ? sidecarEnrichRowsExportPath(inPlaceFinalOutputPath) : null;
|
|
19471
19878
|
let inPlaceCommitted = false;
|
|
19472
19879
|
const commitInPlaceOutput = async (exportResult) => {
|
|
19473
19880
|
if (!inPlaceTempOutputPath || !inPlaceCommitOutputPath || !inPlaceFinalOutputPath) {
|
|
@@ -19556,6 +19963,7 @@ function registerEnrichCommand(program) {
|
|
|
19556
19963
|
}
|
|
19557
19964
|
let workingMergeSourceCsvPath = sourceCsvPath;
|
|
19558
19965
|
let lastStatus = null;
|
|
19966
|
+
const batchStatuses = [];
|
|
19559
19967
|
let finalExportResult = null;
|
|
19560
19968
|
let totalEnrichedRows = 0;
|
|
19561
19969
|
const batchFailureRows = [];
|
|
@@ -19593,6 +20001,7 @@ function registerEnrichCommand(program) {
|
|
|
19593
20001
|
suppressOpen: true
|
|
19594
20002
|
});
|
|
19595
20003
|
lastStatus = chunk.status;
|
|
20004
|
+
batchStatuses.push(chunk.status);
|
|
19596
20005
|
if (chunk.captured.result !== 0) {
|
|
19597
20006
|
if (chunk.exportResult) {
|
|
19598
20007
|
finalExportResult = chunk.exportResult;
|
|
@@ -19612,7 +20021,10 @@ function registerEnrichCommand(program) {
|
|
|
19612
20021
|
statusRowRange: chunkRows,
|
|
19613
20022
|
client: client2,
|
|
19614
20023
|
outputPath: failureReportOutputPath ?? finalExportResult?.path ?? outputPath,
|
|
19615
|
-
|
|
20024
|
+
followUpOutputPath: enrichIssueFollowUpOutputPath,
|
|
20025
|
+
status: chunk.status,
|
|
20026
|
+
waterfallStatus: batchStatuses,
|
|
20027
|
+
...finalExportResult ? { rowSetComplete: !finalExportResult.partial } : {}
|
|
19616
20028
|
});
|
|
19617
20029
|
const committedExportResult2 = finalExportResult ? await commitInPlaceOutput(finalExportResult) : null;
|
|
19618
20030
|
if (options.json) {
|
|
@@ -19634,12 +20046,7 @@ function registerEnrichCommand(program) {
|
|
|
19634
20046
|
partial: true
|
|
19635
20047
|
} : {}
|
|
19636
20048
|
} : null,
|
|
19637
|
-
...failureReport3
|
|
19638
|
-
failure_report: {
|
|
19639
|
-
path: failureReport3.path,
|
|
19640
|
-
jobs: failureReport3.jobs.length
|
|
19641
|
-
}
|
|
19642
|
-
} : {}
|
|
20049
|
+
...enrichReportJson(failureReport3)
|
|
19643
20050
|
});
|
|
19644
20051
|
} else {
|
|
19645
20052
|
if (committedExportResult2) {
|
|
@@ -19678,7 +20085,10 @@ function registerEnrichCommand(program) {
|
|
|
19678
20085
|
},
|
|
19679
20086
|
client: client2,
|
|
19680
20087
|
outputPath: failureReportOutputPath ?? finalExportResult?.path ?? outputPath,
|
|
19681
|
-
|
|
20088
|
+
followUpOutputPath: enrichIssueFollowUpOutputPath,
|
|
20089
|
+
status: lastStatus,
|
|
20090
|
+
waterfallStatus: batchStatuses,
|
|
20091
|
+
...finalExportResult ? { rowSetComplete: !finalExportResult.partial } : {}
|
|
19682
20092
|
});
|
|
19683
20093
|
finalExportResult = await commitInPlaceOutput(finalExportResult);
|
|
19684
20094
|
if (options.json) {
|
|
@@ -19710,12 +20120,7 @@ function registerEnrichCommand(program) {
|
|
|
19710
20120
|
enrichedRows: totalEnrichedRows,
|
|
19711
20121
|
path: finalExportResult.path
|
|
19712
20122
|
} : null,
|
|
19713
|
-
...failureReport2
|
|
19714
|
-
failure_report: {
|
|
19715
|
-
path: failureReport2.path,
|
|
19716
|
-
jobs: failureReport2.jobs.length
|
|
19717
|
-
}
|
|
19718
|
-
} : {}
|
|
20123
|
+
...enrichReportJson(failureReport2)
|
|
19719
20124
|
});
|
|
19720
20125
|
}
|
|
19721
20126
|
if (failureReport2) {
|
|
@@ -19746,6 +20151,7 @@ function registerEnrichCommand(program) {
|
|
|
19746
20151
|
exportResult: committedExportResult2,
|
|
19747
20152
|
outputPath,
|
|
19748
20153
|
reportOutputPath: failureReportOutputPath,
|
|
20154
|
+
followUpOutputPath: enrichIssueFollowUpOutputPath,
|
|
19749
20155
|
status
|
|
19750
20156
|
});
|
|
19751
20157
|
if (options.json) {
|
|
@@ -19753,12 +20159,7 @@ function registerEnrichCommand(program) {
|
|
|
19753
20159
|
ok: false,
|
|
19754
20160
|
run: status,
|
|
19755
20161
|
output: enrichOutputJson(committedExportResult2),
|
|
19756
|
-
...failureReport2
|
|
19757
|
-
failure_report: {
|
|
19758
|
-
path: failureReport2.path,
|
|
19759
|
-
jobs: failureReport2.jobs.length
|
|
19760
|
-
}
|
|
19761
|
-
} : {}
|
|
20162
|
+
...enrichReportJson(failureReport2)
|
|
19762
20163
|
});
|
|
19763
20164
|
}
|
|
19764
20165
|
process.exitCode = failureReport2 ? EXIT_SERVER2 : captured.result;
|
|
@@ -19773,6 +20174,7 @@ function registerEnrichCommand(program) {
|
|
|
19773
20174
|
exportResult,
|
|
19774
20175
|
outputPath,
|
|
19775
20176
|
reportOutputPath: failureReportOutputPath,
|
|
20177
|
+
followUpOutputPath: enrichIssueFollowUpOutputPath,
|
|
19776
20178
|
status
|
|
19777
20179
|
});
|
|
19778
20180
|
const committedExportResult2 = await commitInPlaceOutput(exportResult);
|
|
@@ -19787,12 +20189,7 @@ function registerEnrichCommand(program) {
|
|
|
19787
20189
|
ok: !failureReport2,
|
|
19788
20190
|
run,
|
|
19789
20191
|
output: enrichOutputJson(committedExportResult2),
|
|
19790
|
-
...failureReport2
|
|
19791
|
-
failure_report: {
|
|
19792
|
-
path: failureReport2.path,
|
|
19793
|
-
jobs: failureReport2.jobs.length
|
|
19794
|
-
}
|
|
19795
|
-
} : {}
|
|
20192
|
+
...enrichReportJson(failureReport2)
|
|
19796
20193
|
});
|
|
19797
20194
|
if (failureReport2) {
|
|
19798
20195
|
process.exitCode = EXIT_SERVER2;
|
|
@@ -19805,7 +20202,9 @@ function registerEnrichCommand(program) {
|
|
|
19805
20202
|
rowRange: rows,
|
|
19806
20203
|
client: client2,
|
|
19807
20204
|
outputPath: failureReportOutputPath ?? exportResult?.path ?? null,
|
|
19808
|
-
|
|
20205
|
+
followUpOutputPath: enrichIssueFollowUpOutputPath,
|
|
20206
|
+
status,
|
|
20207
|
+
...exportResult ? { rowSetComplete: !exportResult.partial } : {}
|
|
19809
20208
|
});
|
|
19810
20209
|
const committedExportResult = await commitInPlaceOutput(exportResult);
|
|
19811
20210
|
if (committedExportResult) {
|