Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 134
feat: ship dbt-tools with altimate-code npm package#312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| #!/usr/bin/env bun | ||
| import { $ } from "bun" | ||
| import fs from "fs" | ||
| import path from "path" | ||
| import pkg from "../package.json" | ||
| import { Script } from "@opencode-ai/script" | ||
| import { fileURLToPath } from "url" | ||
| @@ -43,12 +45,31 @@ for (const filepath of new Bun.Glob("**/package.json").scanSync({ cwd: "./dist" | ||
| console.log("binaries", binaries) | ||
| const version = Object.values(binaries)[0] | ||
| // Build dbt-tools so we can bundle it in the published package. | ||
| // dbt-tools provides the `altimate-dbt` CLI used by the builder agent. | ||
| const dbtToolsDir = "../dbt-tools" | ||
| await $`bun run build`.cwd(dbtToolsDir) | ||
| // Bundle dbt-tools into the wrapper package: bin shim + bundled JS + Python packages. | ||
| // Native .node files are NOT copied — @altimateai/altimate-core is already a runtime | ||
| // dependency and provides them. This keeps the package ~200 MB lighter. | ||
| async function copyDbtTools(destRoot: string) { | ||
| await $`mkdir -p ${destRoot}/dbt-tools/bin` | ||
| await $`mkdir -p ${destRoot}/dbt-tools/dist` | ||
| await $`cp ${dbtToolsDir}/bin/altimate-dbt ${destRoot}/dbt-tools/bin/` | ||
| await $`cp ${dbtToolsDir}/dist/index.js ${destRoot}/dbt-tools/dist/` | ||
| if (fs.existsSync(path.join(dbtToolsDir, "dist/altimate_python_packages"))) { | ||
| await $`cp -r ${dbtToolsDir}/dist/altimate_python_packages ${destRoot}/dbt-tools/dist/` | ||
| } | ||
| } | ||
| await $`mkdir -p ./dist/${pkg.name}` | ||
| await $`cp -r ./bin ./dist/${pkg.name}/bin` | ||
| await $`cp -r ../../.opencode/skills ./dist/${pkg.name}/skills` | ||
| await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs` | ||
| await Bun.file(`./dist/${pkg.name}/LICENSE`).write(await Bun.file("../../LICENSE").text()) | ||
| await Bun.file(`./dist/${pkg.name}/CHANGELOG.md`).write(await Bun.file("../../CHANGELOG.md").text()) | ||
| await copyDbtTools(`./dist/${pkg.name}`) | ||
| await Bun.file(`./dist/${pkg.name}/package.json`).write( | ||
| JSON.stringify( | ||
| @@ -57,6 +78,7 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( | ||
| bin: { | ||
| altimate: "./bin/altimate", | ||
| "altimate-code": "./bin/altimate-code", | ||
| "altimate-dbt": "./dbt-tools/bin/altimate-dbt", | ||
| }, | ||
suryaiyer95 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| scripts: { | ||
| postinstall: "bun ./postinstall.mjs || node ./postinstall.mjs", | ||
| @@ -94,6 +116,7 @@ try { | ||
| await Bun.file(`${unscopedDir}/LICENSE`).write(await Bun.file("../../LICENSE").text()) | ||
| await Bun.file(`${unscopedDir}/CHANGELOG.md`).write(await Bun.file("../../CHANGELOG.md").text()) | ||
| await Bun.file(`${unscopedDir}/README.md`).write(await Bun.file("../../README.md").text()) | ||
| await copyDbtTools(unscopedDir) | ||
| await Bun.file(`${unscopedDir}/package.json`).write( | ||
| JSON.stringify( | ||
| { | ||
| @@ -108,6 +131,7 @@ try { | ||
| bin: { | ||
| altimate: "./bin/altimate", | ||
| "altimate-code": "./bin/altimate-code", | ||
| "altimate-dbt": "./dbt-tools/bin/altimate-dbt", | ||
| }, | ||
| scripts: { | ||
| postinstall: "bun ./postinstall.mjs || node ./postinstall.mjs", | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -17,12 +17,68 @@ import { Shell } from "@/shell/shell" | ||
| import { BashArity } from "@/permission/arity" | ||
| import { Truncate } from "./truncation" | ||
| import { Plugin } from "@/plugin" | ||
| import { existsSync } from "fs" | ||
| const MAX_METADATA_LENGTH = 30_000 | ||
| const DEFAULT_TIMEOUT = Flag.OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS || 2 * 60 * 1000 | ||
| export const log = Log.create({ service: "bash-tool" }) | ||
| const DBT_BINARY_NAMES = | ||
| process.platform === "win32" ? ["altimate-dbt.exe", "altimate-dbt.cmd", "altimate-dbt"] : ["altimate-dbt"] | ||
| function hasDbtBinary(dir: string): boolean { | ||
| return DBT_BINARY_NAMES.some((name) => existsSync(path.join(dir, name))) | ||
suryaiyer95 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| // Resolve dbt-tools/bin so `altimate-dbt` is on PATH when spawning bash commands. | ||
| // Checks: env var → dev source tree → npm-installed wrapper package → walk-up fallback. | ||
| const dbtToolsBin = lazy(() => { | ||
| // 1. Explicit env var override | ||
| if (process.env.ALTIMATE_DBT_TOOLS_BIN && hasDbtBinary(process.env.ALTIMATE_DBT_TOOLS_BIN)) { | ||
| return process.env.ALTIMATE_DBT_TOOLS_BIN | ||
| } | ||
| // 2. Dev mode: resolve from source tree | ||
| // import.meta.dirname = packages/opencode/src/tool → ../../../dbt-tools/bin | ||
| if (import.meta.dirname && !import.meta.dirname.startsWith("/$bunfs")) { | ||
| const devPath = path.resolve(import.meta.dirname, "../../../dbt-tools/bin") | ||
| if (hasDbtBinary(devPath)) return devPath | ||
coderabbitai[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| // 3. npm installed: compiled binary lives in a platform-specific package, | ||
| // dbt-tools ships in the wrapper package alongside it. | ||
| // Binary: node_modules/@altimateai/altimate-code-<platform>/bin/altimate | ||
| // Scoped: node_modules/@altimateai/altimate-code/dbt-tools/bin/altimate-dbt | ||
| // Unscoped: node_modules/altimate-code/dbt-tools/bin/altimate-dbt | ||
| try { | ||
| const binDir = path.dirname(process.execPath) | ||
| // scopeDir = node_modules/@altimateai (for scoped wrapper lookup) | ||
| const scopeDir = path.resolve(binDir, "../..") | ||
suryaiyer95 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| // nodeModulesDir = node_modules (for unscoped wrapper lookup) | ||
| const nodeModulesDir = path.dirname(scopeDir) | ||
| for (const wrapper of ["altimate-code", "opencode"]) { | ||
| const scoped = path.join(scopeDir, wrapper, "dbt-tools", "bin") | ||
| if (hasDbtBinary(scoped)) return scoped | ||
| const unscoped = path.join(nodeModulesDir, wrapper, "dbt-tools", "bin") | ||
| if (hasDbtBinary(unscoped)) return unscoped | ||
| } | ||
| // Walk up for other layouts (global installs, pnpm, monorepos) | ||
| let dir = binDir | ||
| for (let i = 0; i < 8; i++) { | ||
| if (hasDbtBinary(path.join(dir, "dbt-tools", "bin"))) return path.join(dir, "dbt-tools", "bin") | ||
| const parent = path.dirname(dir) | ||
| if (parent === dir) break // reached filesystem root | ||
| dir = parent | ||
| } | ||
| } catch (e) { | ||
| log.debug("dbtToolsBin: failed to resolve from execPath", { error: String(e) }) | ||
| } | ||
| return undefined | ||
| }) | ||
| const DEFAULT_TIMEOUT = Flag.OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS || 2 * 60 * 1000 | ||
| const resolveWasm = (asset: string) => { | ||
| if (asset.startsWith("file://")) return fileURLToPath(asset) | ||
| if (asset.startsWith("/") || /^[a-z]:/i.test(asset)) return asset | ||
| @@ -164,12 +220,17 @@ export const BashTool = Tool.define("bash", async () => { | ||
| { cwd, sessionID: ctx.sessionID, callID: ctx.callID }, | ||
| { env: {} }, | ||
| ) | ||
| const baseEnv: Record<string, string | undefined> = { ...process.env, ...shellEnv.env } | ||
| const extraPath = dbtToolsBin() | ||
| const envPATH = extraPath | ||
| ? `${extraPath}${path.delimiter}${baseEnv.PATH ?? ""}` | ||
| : baseEnv.PATH | ||
suryaiyer95 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| const proc = spawn(params.command, { | ||
| shell, | ||
| cwd, | ||
| env: { | ||
| ...process.env, | ||
| ...shellEnv.env, | ||
| ...baseEnv, | ||
| ...(envPATH ? { PATH: envPATH } : {}), | ||
| }, | ||
suryaiyer95 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| stdio: ["ignore", "pipe", "pipe"], | ||
| detached: process.platform !== "win32", | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.