-
Notifications
You must be signed in to change notification settings - Fork 56
Expand file tree
/
Copy pathdbt-manifest.ts
More file actions
78 lines (70 loc) · 2.96 KB
/
dbt-manifest.ts
File metadata and controls
78 lines (70 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import z from "zod"
import { Tool } from "../../tool/tool"
import { Dispatcher } from "../native"
import type { DbtManifestResult } from "../native/types"
export const DbtManifestTool = Tool.define("dbt_manifest", {
description:
"Parse a dbt manifest.json file to extract models, sources, tests, and dependencies. Useful for understanding project structure and lineage.",
parameters: z.object({
path: z.string().describe("Path to the dbt manifest.json file (e.g. target/manifest.json)"),
}),
async execute(args, ctx) {
try {
const result = await Dispatcher.call("dbt.manifest", { path: args.path })
return {
title: `Manifest: ${result.model_count ?? 0} models, ${result.source_count ?? 0} sources`,
metadata: {
model_count: result.model_count,
source_count: result.source_count,
test_count: result.test_count,
snapshot_count: result.snapshot_count,
seed_count: result.seed_count,
},
output: formatManifest(result),
}
} catch (e) {
const msg = e instanceof Error ? e.message : String(e)
return {
title: "Manifest: ERROR",
metadata: { model_count: 0, source_count: 0, test_count: 0, snapshot_count: 0, seed_count: 0, error: msg },
output: `Failed to parse manifest: ${msg}\n\nEnsure the manifest.json exists and the dispatcher is running.`,
}
}
},
})
function formatManifest(result: DbtManifestResult): string {
const lines: string[] = []
lines.push("=== Project Summary ===")
lines.push(`Models: ${result.model_count ?? 0}`)
lines.push(`Sources: ${result.source_count ?? 0}`)
lines.push(`Tests: ${result.test_count ?? 0}`)
lines.push(`Snapshots: ${result.snapshot_count ?? 0}`)
lines.push(`Seeds: ${result.seed_count ?? 0}`)
const models = result.models ?? []
const sources = result.sources ?? []
if (models.length > 0) {
lines.push("")
lines.push("=== Models ===")
lines.push("Name | Schema | Materialized | Dependencies | Columns")
lines.push("-----|--------|-------------|-------------|--------")
for (const model of models) {
const depsArr = model.depends_on ?? []
const colsArr = model.columns ?? []
const deps = depsArr.length > 0 ? depsArr.map((d) => d.split(".").pop()).join(", ") : "-"
const cols = colsArr.length > 0 ? colsArr.map((c) => c.name).join(", ") : "-"
lines.push(`${model.name} | ${model.schema_name ?? "-"} | ${model.materialized ?? "-"} | ${deps} | ${cols}`)
}
}
if (sources.length > 0) {
lines.push("")
lines.push("=== Sources ===")
lines.push("Source | Table | Schema | Columns")
lines.push("-------|-------|--------|--------")
for (const source of sources) {
const sourceCols = source.columns ?? []
const cols = sourceCols.length > 0 ? sourceCols.map((c) => c.name).join(", ") : "-"
lines.push(`${source.source_name} | ${source.name} | ${source.schema_name ?? "-"} | ${cols}`)
}
}
return lines.join("\n")
}