altimate-code 0.8.7 → 0.8.8
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/README.md +8 -2
- package/dbt-tools/dist/index.js +136 -52
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -30,13 +30,19 @@ into CI pipelines and orchestration DAGs. Precision data tooling for any LLM.
|
|
|
30
30
|
npm install -g altimate-code
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Or via curl (installs the `altimate` binary to `~/.altimate/bin`):
|
|
33
|
+
Or via curl on macOS/Linux (installs the `altimate` binary to `~/.altimate/bin`):
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
curl -fsSL https://www.altimate.sh/install | bash
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
On Windows, install the same self-contained binary (to `%USERPROFILE%\.altimate\bin`) from PowerShell — no Node required:
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
powershell -c "irm https://www.altimate.sh/install.ps1 | iex"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The standalone install drops a single self-contained binary named `altimate`. The npm install exposes both `altimate` and `altimate-code` on PATH; the standalone install only exposes `altimate`. Alpine Linux (musl) and Windows on ARM64 are not currently supported by the standalone binary — use `apk add gcompat` on Alpine, or use WSL on Windows-on-ARM.
|
|
40
46
|
|
|
41
47
|
For GitHub, [install the Altimate Code App](https://github.com/apps/altimate-code-agent/installations/new)
|
|
42
48
|
to select repositories for interactive agent tasks. Automatic dbt pull-request
|
package/dbt-tools/dist/index.js
CHANGED
|
@@ -321,16 +321,25 @@ function getDbt() {
|
|
|
321
321
|
}
|
|
322
322
|
return resolvedDbt;
|
|
323
323
|
}
|
|
324
|
+
function toExecFileError(e) {
|
|
325
|
+
if (e instanceof Error)
|
|
326
|
+
return e;
|
|
327
|
+
return new Error(String(e));
|
|
328
|
+
}
|
|
324
329
|
function run2(args) {
|
|
325
330
|
const dbt2 = getDbt();
|
|
326
331
|
const env = buildDbtEnv(dbt2);
|
|
327
332
|
const cwd = globalOptions.projectRoot ?? process.cwd();
|
|
328
333
|
return new Promise((resolve4, reject2) => {
|
|
329
334
|
execFile(dbt2.path, args, { timeout: 120000, maxBuffer: 10 * 1024 * 1024, env, cwd }, (err, stdout, stderr) => {
|
|
330
|
-
if (err)
|
|
331
|
-
|
|
332
|
-
|
|
335
|
+
if (err) {
|
|
336
|
+
const execErr = err;
|
|
337
|
+
execErr.stdout = stdout;
|
|
338
|
+
execErr.stderr = stderr;
|
|
339
|
+
reject2(execErr);
|
|
340
|
+
} else {
|
|
333
341
|
resolve4({ stdout, stderr });
|
|
342
|
+
}
|
|
334
343
|
});
|
|
335
344
|
});
|
|
336
345
|
}
|
|
@@ -439,41 +448,43 @@ async function execDbtShow(sql, limit) {
|
|
|
439
448
|
const args = ["show", "--inline", sql, "--output", "json", "--log-format", "json"];
|
|
440
449
|
if (limit !== undefined)
|
|
441
450
|
args.push("--limit", String(limit));
|
|
442
|
-
let
|
|
451
|
+
let primaryRunError;
|
|
452
|
+
let lines = [];
|
|
443
453
|
try {
|
|
444
454
|
const { stdout } = await run2(args);
|
|
445
455
|
lines = parseJsonLines(stdout);
|
|
446
|
-
} catch {
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
rows = parsed;
|
|
456
|
+
} catch (e) {
|
|
457
|
+
primaryRunError = toExecFileError(e);
|
|
458
|
+
}
|
|
459
|
+
if (!primaryRunError) {
|
|
460
|
+
const previewLine = lines.find((l) => l.data?.preview) ?? lines.find((l) => l.data?.rows) ?? lines.find((l) => l.result?.preview) ?? lines.find((l) => l.result?.rows);
|
|
461
|
+
const sqlLine = lines.find((l) => l.data?.sql) ?? lines.find((l) => l.data?.compiled_sql) ?? lines.find((l) => l.result?.sql);
|
|
462
|
+
if (previewLine) {
|
|
463
|
+
const preview = previewLine.data?.preview ?? previewLine.data?.rows ?? previewLine.result?.preview ?? previewLine.result?.rows;
|
|
464
|
+
let rows;
|
|
465
|
+
if (typeof preview === "string") {
|
|
466
|
+
const parsed = safeJsonParse(preview);
|
|
467
|
+
rows = Array.isArray(parsed) ? parsed : [];
|
|
468
|
+
} else if (Array.isArray(preview)) {
|
|
469
|
+
rows = preview;
|
|
458
470
|
} else {
|
|
459
471
|
rows = [];
|
|
460
472
|
}
|
|
461
|
-
} else {
|
|
462
|
-
rows = preview;
|
|
463
|
-
}
|
|
464
|
-
const columnNames = rows.length > 0 && rows[0] ? Object.keys(rows[0]) : [];
|
|
465
|
-
const compiledSql = sqlLine?.data?.sql ?? sqlLine?.data?.compiled_sql ?? sqlLine?.result?.sql ?? sql;
|
|
466
|
-
return { columnNames, columnTypes: columnNames.map(() => "string"), data: rows, rawSql: sql, compiledSql };
|
|
467
|
-
}
|
|
468
|
-
for (const line of lines) {
|
|
469
|
-
const found = deepFind(line, (val) => looksLikeRowData(val));
|
|
470
|
-
if (found) {
|
|
471
|
-
const rows = typeof found === "string" ? JSON.parse(found) : found;
|
|
472
473
|
const columnNames = rows.length > 0 && rows[0] ? Object.keys(rows[0]) : [];
|
|
473
|
-
const compiledSql =
|
|
474
|
+
const compiledSql = sqlLine?.data?.sql ?? sqlLine?.data?.compiled_sql ?? sqlLine?.result?.sql ?? sql;
|
|
474
475
|
return { columnNames, columnTypes: columnNames.map(() => "string"), data: rows, rawSql: sql, compiledSql };
|
|
475
476
|
}
|
|
477
|
+
for (const line of lines) {
|
|
478
|
+
const found = deepFind(line, (val) => looksLikeRowData(val));
|
|
479
|
+
if (found) {
|
|
480
|
+
const rows = typeof found === "string" ? JSON.parse(found) : found;
|
|
481
|
+
const columnNames = rows.length > 0 && rows[0] ? Object.keys(rows[0]) : [];
|
|
482
|
+
const compiledSql = deepFind(line, (val) => looksLikeSql(val)) ?? sql;
|
|
483
|
+
return { columnNames, columnTypes: columnNames.map(() => "string"), data: rows, rawSql: sql, compiledSql };
|
|
484
|
+
}
|
|
485
|
+
}
|
|
476
486
|
}
|
|
487
|
+
let plainRunError;
|
|
477
488
|
try {
|
|
478
489
|
const plainArgs = ["show", "--inline", sql];
|
|
479
490
|
if (limit !== undefined)
|
|
@@ -489,62 +500,135 @@ async function execDbtShow(sql, limit) {
|
|
|
489
500
|
compiledSql: sql
|
|
490
501
|
};
|
|
491
502
|
}
|
|
492
|
-
} catch {
|
|
503
|
+
} catch (e) {
|
|
504
|
+
plainRunError = toExecFileError(e);
|
|
505
|
+
}
|
|
506
|
+
if (primaryRunError) {
|
|
507
|
+
const errorLogLines = parseJsonLines(primaryRunError.stdout?.toString() ?? "");
|
|
508
|
+
const realError = extractDbtError(errorLogLines, primaryRunError, plainRunError);
|
|
509
|
+
if (realError) {
|
|
510
|
+
const hasDbtCategoryPrefix = /^(Compilation|Database|Runtime|Parsing|Validation|Dependency)\s+Error\b/.test(realError);
|
|
511
|
+
throw new Error(hasDbtCategoryPrefix ? realError : `dbt show failed: ${realError}`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (plainRunError) {
|
|
515
|
+
const fallback = extractDbtError([], undefined, plainRunError) ?? fallbackExitMessage(undefined, plainRunError) ?? "unknown error";
|
|
516
|
+
throw new Error(`Could not parse dbt show JSON output, and plain-text fallback failed: ${fallback}`);
|
|
517
|
+
}
|
|
493
518
|
throw new Error("Could not parse dbt show output in any format (JSON, heuristic, or plain text). " + `Got ${lines.length} JSON lines.`);
|
|
494
519
|
}
|
|
520
|
+
function extractDbtError(lines, primary, plain) {
|
|
521
|
+
if (!primary && !plain)
|
|
522
|
+
return;
|
|
523
|
+
const errorMessages = lines.map((l) => {
|
|
524
|
+
const line = l;
|
|
525
|
+
const isError = line.info?.level === "error" || line.level === "error";
|
|
526
|
+
if (!isError)
|
|
527
|
+
return;
|
|
528
|
+
return line.info?.msg ?? line.msg;
|
|
529
|
+
}).filter((m) => typeof m === "string" && m.trim().length > 0);
|
|
530
|
+
const structuredMsg = errorMessages.at(-1);
|
|
531
|
+
const primaryStderr = primary?.stderr?.toString().trim();
|
|
532
|
+
const plainStderr = plain?.stderr?.toString().trim();
|
|
533
|
+
const chosen = (structuredMsg && structuredMsg.length > 0 ? structuredMsg : undefined) ?? (primaryStderr && primaryStderr.length > 0 ? primaryStderr : undefined) ?? (plainStderr && plainStderr.length > 0 ? plainStderr : undefined) ?? fallbackExitMessage(primary, plain);
|
|
534
|
+
return chosen ? stripAnsi(chosen) : undefined;
|
|
535
|
+
}
|
|
536
|
+
function fallbackExitMessage(primary, plain) {
|
|
537
|
+
const err = primary ?? plain;
|
|
538
|
+
if (!err)
|
|
539
|
+
return;
|
|
540
|
+
const looksLikeCommandFailed = typeof err.message === "string" && err.message.startsWith("Command failed:");
|
|
541
|
+
if (!looksLikeCommandFailed)
|
|
542
|
+
return err.message;
|
|
543
|
+
if (typeof err.code === "number")
|
|
544
|
+
return `dbt exited with status ${err.code}`;
|
|
545
|
+
if (err.signal)
|
|
546
|
+
return `dbt killed by signal ${err.signal}`;
|
|
547
|
+
if (typeof err.code === "string")
|
|
548
|
+
return `dbt failed: ${err.code}`;
|
|
549
|
+
return "dbt failed (no exit code reported)";
|
|
550
|
+
}
|
|
551
|
+
function bubbleDbtError(label, primary, plain) {
|
|
552
|
+
const errorLogLines = primary?.stdout ? parseJsonLines(primary.stdout.toString()) : [];
|
|
553
|
+
const real = extractDbtError(errorLogLines, primary, plain);
|
|
554
|
+
if (real) {
|
|
555
|
+
const hasDbtCategoryPrefix = /^(Compilation|Database|Runtime|Parsing|Validation|Dependency)\s+Error\b/.test(real);
|
|
556
|
+
return hasDbtCategoryPrefix ? real : `${label}: ${real}`;
|
|
557
|
+
}
|
|
558
|
+
return `${label}: ${fallbackExitMessage(primary, plain) ?? "unknown error"}`;
|
|
559
|
+
}
|
|
495
560
|
async function execDbtCompile(model) {
|
|
496
561
|
const args = ["compile", "--select", model, "--output", "json", "--log-format", "json"];
|
|
497
|
-
let lines;
|
|
562
|
+
let lines = [];
|
|
563
|
+
let primaryRunError;
|
|
498
564
|
try {
|
|
499
565
|
const { stdout } = await run2(args);
|
|
500
566
|
lines = parseJsonLines(stdout);
|
|
501
|
-
} catch {
|
|
502
|
-
|
|
567
|
+
} catch (e) {
|
|
568
|
+
primaryRunError = toExecFileError(e);
|
|
503
569
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
570
|
+
if (!primaryRunError) {
|
|
571
|
+
const sql = findCompiledSql(lines);
|
|
572
|
+
if (sql)
|
|
573
|
+
return { sql };
|
|
574
|
+
for (const line of lines) {
|
|
575
|
+
const found = deepFind(line, (val) => looksLikeSql(val));
|
|
576
|
+
if (found)
|
|
577
|
+
return { sql: found };
|
|
578
|
+
}
|
|
511
579
|
}
|
|
580
|
+
let manifestRunError;
|
|
512
581
|
try {
|
|
513
582
|
await run2(["compile", "--select", model]);
|
|
514
|
-
} catch {
|
|
583
|
+
} catch (e) {
|
|
584
|
+
manifestRunError = toExecFileError(e);
|
|
585
|
+
}
|
|
515
586
|
const fromManifest = readCompiledFromManifest(model);
|
|
516
587
|
if (fromManifest)
|
|
517
588
|
return { sql: fromManifest };
|
|
589
|
+
let plainRunError;
|
|
518
590
|
try {
|
|
519
591
|
const { stdout: plainOut } = await run2(["compile", "--select", model]);
|
|
520
592
|
return { sql: plainOut.trim() };
|
|
521
593
|
} catch (e) {
|
|
522
|
-
|
|
594
|
+
plainRunError = toExecFileError(e);
|
|
595
|
+
}
|
|
596
|
+
if (primaryRunError || plainRunError || manifestRunError) {
|
|
597
|
+
throw new Error(bubbleDbtError("dbt compile failed", primaryRunError, plainRunError ?? manifestRunError));
|
|
523
598
|
}
|
|
599
|
+
throw new Error(`Could not compile model '${model}' in any format (JSON, heuristic, or manifest).`);
|
|
524
600
|
}
|
|
525
601
|
async function execDbtCompileInline(sql, _model) {
|
|
526
602
|
const args = ["compile", "--inline", sql, "--output", "json", "--log-format", "json"];
|
|
527
|
-
let lines;
|
|
603
|
+
let lines = [];
|
|
604
|
+
let primaryRunError;
|
|
528
605
|
try {
|
|
529
606
|
const { stdout } = await run2(args);
|
|
530
607
|
lines = parseJsonLines(stdout);
|
|
531
|
-
} catch {
|
|
532
|
-
|
|
608
|
+
} catch (e) {
|
|
609
|
+
primaryRunError = toExecFileError(e);
|
|
533
610
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
611
|
+
if (!primaryRunError) {
|
|
612
|
+
const compiled = findCompiledSql(lines);
|
|
613
|
+
if (compiled)
|
|
614
|
+
return { sql: compiled };
|
|
615
|
+
for (const line of lines) {
|
|
616
|
+
const found = deepFind(line, (val) => looksLikeSql(val));
|
|
617
|
+
if (found)
|
|
618
|
+
return { sql: found };
|
|
619
|
+
}
|
|
541
620
|
}
|
|
621
|
+
let plainRunError;
|
|
542
622
|
try {
|
|
543
623
|
const { stdout: plainOut } = await run2(["compile", "--inline", sql]);
|
|
544
624
|
return { sql: plainOut.trim() };
|
|
545
625
|
} catch (e) {
|
|
546
|
-
|
|
626
|
+
plainRunError = toExecFileError(e);
|
|
627
|
+
}
|
|
628
|
+
if (primaryRunError || plainRunError) {
|
|
629
|
+
throw new Error(bubbleDbtError("dbt compile inline failed", primaryRunError, plainRunError));
|
|
547
630
|
}
|
|
631
|
+
throw new Error("Could not compile inline SQL in any format (JSON, heuristic, or plain text).");
|
|
548
632
|
}
|
|
549
633
|
function findCompiledSql(lines) {
|
|
550
634
|
const compiledLine = lines.find((l) => l.data?.compiled) ?? lines.find((l) => l.data?.compiled_code) ?? lines.find((l) => l.result?.node?.compiled_code) ?? lines.find((l) => l.result?.compiled_code) ?? lines.find((l) => l.data?.compiled_sql);
|
package/package.json
CHANGED
|
@@ -14,20 +14,20 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"postinstall": "bun ./postinstall.mjs || node ./postinstall.mjs"
|
|
16
16
|
},
|
|
17
|
-
"version": "0.8.
|
|
17
|
+
"version": "0.8.8",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@altimateai/altimate-core": "0.5.1"
|
|
21
21
|
},
|
|
22
22
|
"optionalDependencies": {
|
|
23
|
-
"@altimateai/altimate-code-linux-x64-baseline": "0.8.
|
|
24
|
-
"@altimateai/altimate-code-windows-x64": "0.8.
|
|
25
|
-
"@altimateai/altimate-code-linux-x64": "0.8.
|
|
26
|
-
"@altimateai/altimate-code-darwin-x64": "0.8.
|
|
27
|
-
"@altimateai/altimate-code-darwin-x64-baseline": "0.8.
|
|
28
|
-
"@altimateai/altimate-code-darwin-arm64": "0.8.
|
|
29
|
-
"@altimateai/altimate-code-windows-x64-baseline": "0.8.
|
|
30
|
-
"@altimateai/altimate-code-linux-arm64": "0.8.
|
|
23
|
+
"@altimateai/altimate-code-linux-x64-baseline": "0.8.8",
|
|
24
|
+
"@altimateai/altimate-code-windows-x64": "0.8.8",
|
|
25
|
+
"@altimateai/altimate-code-linux-x64": "0.8.8",
|
|
26
|
+
"@altimateai/altimate-code-darwin-x64": "0.8.8",
|
|
27
|
+
"@altimateai/altimate-code-darwin-x64-baseline": "0.8.8",
|
|
28
|
+
"@altimateai/altimate-code-darwin-arm64": "0.8.8",
|
|
29
|
+
"@altimateai/altimate-code-windows-x64-baseline": "0.8.8",
|
|
30
|
+
"@altimateai/altimate-code-linux-arm64": "0.8.8"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"pg": ">=8",
|