yamchart 0.10.2 → 0.10.3

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.
Files changed (66) hide show
  1. package/dist/{advisor-5F73GF54.js → advisor-XTJQU7E4.js} +12 -12
  2. package/dist/{chunk-5CRXV5PQ.js → chunk-2XJZJ6IA.js} +2 -2
  3. package/dist/{chunk-X3UG6T3Q.js → chunk-6ELSQNIH.js} +2 -2
  4. package/dist/{chunk-UOSOZT47.js → chunk-KDDO4UII.js} +57 -5
  5. package/dist/chunk-KDDO4UII.js.map +1 -0
  6. package/dist/{chunk-25ES7MGF.js → chunk-ODSPBOJW.js} +4 -4
  7. package/dist/{chunk-7HWFVUGP.js → chunk-OYBI433Z.js} +59 -2
  8. package/dist/chunk-OYBI433Z.js.map +1 -0
  9. package/dist/{chunk-WVSDQNAN.js → chunk-PXFTWXSV.js} +2 -2
  10. package/dist/{chunk-PYVROL7Z.js → chunk-XNMB25GT.js} +4 -4
  11. package/dist/{connection-utils-HNX3473B.js → connection-utils-S7EFPTLY.js} +5 -5
  12. package/dist/{describe-KDGXFPDQ.js → describe-TA2CTODC.js} +6 -6
  13. package/dist/{dev-KOWFGDOP.js → dev-PHFYLJPJ.js} +1336 -796
  14. package/dist/dev-PHFYLJPJ.js.map +1 -0
  15. package/dist/{dist-WMP7BFKP.js → dist-F6TVLP6C.js} +12 -4
  16. package/dist/{dist-YB5RBWCC.js → dist-Q5ETETUU.js} +4 -4
  17. package/dist/{dist-LK3ZG74Q.js → dist-YJOOH65Y.js} +9 -5
  18. package/dist/index.js +26 -26
  19. package/dist/public/assets/DataView-V-E6oxy6.js +9 -0
  20. package/dist/public/assets/{EventManagement-BIkVUSCe.js → EventManagement-Do2xU5lV.js} +1 -1
  21. package/dist/public/assets/{ExplorePage-CeaAulqT.js → ExplorePage-Dg50mvGB.js} +1 -1
  22. package/dist/public/assets/{LoginPage-4WeNcdRi.js → LoginPage-DmYGIXcu.js} +1 -1
  23. package/dist/public/assets/{PublicViewer-CkW-G56D.js → PublicViewer-CJTgc9OF.js} +1 -1
  24. package/dist/public/assets/{SetupWizard-CwTr3PCy.js → SetupWizard-Bo-zmh43.js} +1 -1
  25. package/dist/public/assets/{ShareManagement-DSon6CoC.js → ShareManagement-6Wp6b2Gp.js} +1 -1
  26. package/dist/public/assets/{SourceDetailView-BA4XVKqV.js → SourceDetailView-CTzSXhZc.js} +1 -1
  27. package/dist/public/assets/{UserManagement-BWD2Ugkv.js → UserManagement-DQhB13T0.js} +1 -1
  28. package/dist/public/assets/{index-iR9gLdl9.js → index-CY8xsfQH.js} +31 -31
  29. package/dist/public/assets/{index-Cb4omrVn.css → index-Dkn-tJCT.css} +1 -1
  30. package/dist/public/assets/{index.es-BuEtjxhO.js → index.es-Bc3yys5L.js} +1 -1
  31. package/dist/public/assets/{jspdf.es.min-CScx2_oK.js → jspdf.es.min-D94JEH-J.js} +3 -3
  32. package/dist/public/index.html +2 -2
  33. package/dist/{query-7XHKSZ5H.js → query-AX4BOPMH.js} +5 -5
  34. package/dist/{sample-YNSJ3I3T.js → sample-4NUBJGIL.js} +5 -5
  35. package/dist/{search-NKRXXLRS.js → search-IBVVYN4I.js} +6 -6
  36. package/dist/{semantic-NBAX4WU4.js → semantic-33YIUMUV.js} +3 -3
  37. package/dist/{semantic-DD7P4634.js → semantic-5WGVZ7HY.js} +3 -3
  38. package/dist/{source-resolver-7NY3KEZ2.js → source-resolver-GYXIRIVK.js} +6 -6
  39. package/dist/{sync-warehouse-PK7HXW7U.js → sync-warehouse-5NKENCOZ.js} +5 -5
  40. package/dist/{tables-WQTRZSXR.js → tables-QMZMYYV5.js} +6 -6
  41. package/dist/{test-MKNKUR3N.js → test-6MCPGXJP.js} +5 -5
  42. package/package.json +5 -5
  43. package/dist/chunk-7HWFVUGP.js.map +0 -1
  44. package/dist/chunk-UOSOZT47.js.map +0 -1
  45. package/dist/dev-KOWFGDOP.js.map +0 -1
  46. package/dist/public/assets/DataView-BfwnWnLH.js +0 -9
  47. /package/dist/{advisor-5F73GF54.js.map → advisor-XTJQU7E4.js.map} +0 -0
  48. /package/dist/{chunk-5CRXV5PQ.js.map → chunk-2XJZJ6IA.js.map} +0 -0
  49. /package/dist/{chunk-X3UG6T3Q.js.map → chunk-6ELSQNIH.js.map} +0 -0
  50. /package/dist/{chunk-25ES7MGF.js.map → chunk-ODSPBOJW.js.map} +0 -0
  51. /package/dist/{chunk-WVSDQNAN.js.map → chunk-PXFTWXSV.js.map} +0 -0
  52. /package/dist/{chunk-PYVROL7Z.js.map → chunk-XNMB25GT.js.map} +0 -0
  53. /package/dist/{connection-utils-HNX3473B.js.map → connection-utils-S7EFPTLY.js.map} +0 -0
  54. /package/dist/{describe-KDGXFPDQ.js.map → describe-TA2CTODC.js.map} +0 -0
  55. /package/dist/{dist-LK3ZG74Q.js.map → dist-F6TVLP6C.js.map} +0 -0
  56. /package/dist/{dist-WMP7BFKP.js.map → dist-Q5ETETUU.js.map} +0 -0
  57. /package/dist/{dist-YB5RBWCC.js.map → dist-YJOOH65Y.js.map} +0 -0
  58. /package/dist/{query-7XHKSZ5H.js.map → query-AX4BOPMH.js.map} +0 -0
  59. /package/dist/{sample-YNSJ3I3T.js.map → sample-4NUBJGIL.js.map} +0 -0
  60. /package/dist/{search-NKRXXLRS.js.map → search-IBVVYN4I.js.map} +0 -0
  61. /package/dist/{semantic-NBAX4WU4.js.map → semantic-33YIUMUV.js.map} +0 -0
  62. /package/dist/{semantic-DD7P4634.js.map → semantic-5WGVZ7HY.js.map} +0 -0
  63. /package/dist/{source-resolver-7NY3KEZ2.js.map → source-resolver-GYXIRIVK.js.map} +0 -0
  64. /package/dist/{sync-warehouse-PK7HXW7U.js.map → sync-warehouse-5NKENCOZ.js.map} +0 -0
  65. /package/dist/{tables-WQTRZSXR.js.map → tables-QMZMYYV5.js.map} +0 -0
  66. /package/dist/{test-MKNKUR3N.js.map → test-6MCPGXJP.js.map} +0 -0
@@ -3,7 +3,7 @@ import {
3
3
  createConnector,
4
4
  loadProjectConfig,
5
5
  resolveConnection
6
- } from "./chunk-PYVROL7Z.js";
6
+ } from "./chunk-XNMB25GT.js";
7
7
  import {
8
8
  detail,
9
9
  error,
@@ -14,10 +14,10 @@ import {
14
14
  } from "./chunk-HJVVHYVN.js";
15
15
  import {
16
16
  createProviderForTask
17
- } from "./chunk-UOSOZT47.js";
18
- import "./chunk-5CRXV5PQ.js";
19
- import "./chunk-X3UG6T3Q.js";
20
- import "./chunk-7HWFVUGP.js";
17
+ } from "./chunk-KDDO4UII.js";
18
+ import "./chunk-2XJZJ6IA.js";
19
+ import "./chunk-6ELSQNIH.js";
20
+ import "./chunk-OYBI433Z.js";
21
21
  import "./chunk-7D4SUZUM.js";
22
22
 
23
23
  // src/commands/advisor.ts
@@ -49,7 +49,7 @@ async function getDbtProjectPath(projectDir, override) {
49
49
  return null;
50
50
  }
51
51
  async function buildContext(projectDir, options) {
52
- const { parseModelMetadata } = await import("./dist-YB5RBWCC.js");
52
+ const { parseModelMetadata } = await import("./dist-Q5ETETUU.js");
53
53
  const modelsDir = join(projectDir, "models");
54
54
  const yamchartModels = [];
55
55
  try {
@@ -145,7 +145,7 @@ async function buildContext(projectDir, options) {
145
145
  };
146
146
  if (dbtPath) {
147
147
  try {
148
- const { detectConventions, listDbtModels } = await import("./dist-LK3ZG74Q.js");
148
+ const { detectConventions, listDbtModels } = await import("./dist-YJOOH65Y.js");
149
149
  const dbtProjectYml = await readFile(join(dbtPath, "dbt_project.yml"), "utf-8");
150
150
  const dbtConfig = parseYaml(dbtProjectYml);
151
151
  const conventions = await detectConventions(dbtPath);
@@ -246,7 +246,7 @@ async function runAdvisor(projectDir, questionOrMode, options) {
246
246
  `warehouse: ${context.warehouse ? `connected (${context.warehouse.connectionType})` : "not connected"}`
247
247
  );
248
248
  console.log("");
249
- const { AdvisorAgent, buildModelPath } = await import("./dist-LK3ZG74Q.js");
249
+ const { AdvisorAgent, buildModelPath } = await import("./dist-YJOOH65Y.js");
250
250
  const provider = createProviderForTask(projectAi, "advisor", process.env);
251
251
  const agent = new AdvisorAgent(provider);
252
252
  const isAudit = questionOrMode === "audit";
@@ -291,7 +291,7 @@ ${pc.bold(`[${i + 1}]`)} ${formatProposal(proposal, context.dbt.conventions, bui
291
291
  spin2.stop();
292
292
  console.log(result.response);
293
293
  if (result.proposals.length > 0) {
294
- const { buildModelPath: bmp } = await import("./dist-LK3ZG74Q.js");
294
+ const { buildModelPath: bmp } = await import("./dist-YJOOH65Y.js");
295
295
  for (const proposal of result.proposals) {
296
296
  console.log(
297
297
  `
@@ -332,7 +332,7 @@ ${formatProposal(proposal, context.dbt.conventions, bmp)}`
332
332
  conversationHistory.length = 0;
333
333
  conversationHistory.push(...result.messages);
334
334
  if (result.proposals.length > 0) {
335
- const { buildModelPath: bmp } = await import("./dist-LK3ZG74Q.js");
335
+ const { buildModelPath: bmp } = await import("./dist-YJOOH65Y.js");
336
336
  for (const proposal of result.proposals) {
337
337
  console.log(
338
338
  `
@@ -350,7 +350,7 @@ async function offerApply(context, proposals) {
350
350
  return;
351
351
  }
352
352
  const { confirm } = await import("@inquirer/prompts");
353
- const { writeDbtModel, buildModelPath, formatModelSql, updateSchemaYml } = await import("./dist-LK3ZG74Q.js");
353
+ const { writeDbtModel, buildModelPath, formatModelSql, updateSchemaYml } = await import("./dist-YJOOH65Y.js");
354
354
  for (const proposal of proposals) {
355
355
  console.log("");
356
356
  const shouldApply = await confirm({
@@ -389,4 +389,4 @@ async function offerApply(context, proposals) {
389
389
  export {
390
390
  runAdvisor
391
391
  };
392
- //# sourceMappingURL=advisor-5F73GF54.js.map
392
+ //# sourceMappingURL=advisor-XTJQU7E4.js.map
@@ -7,7 +7,7 @@ import {
7
7
  isCustomDateRange,
8
8
  isDatePreset,
9
9
  isRelativeDateRange
10
- } from "./chunk-X3UG6T3Q.js";
10
+ } from "./chunk-6ELSQNIH.js";
11
11
  import {
12
12
  __require
13
13
  } from "./chunk-7D4SUZUM.js";
@@ -1624,4 +1624,4 @@ export {
1624
1624
  isReadOnlySql,
1625
1625
  VERSION
1626
1626
  };
1627
- //# sourceMappingURL=chunk-5CRXV5PQ.js.map
1627
+ //# sourceMappingURL=chunk-2XJZJ6IA.js.map
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __yamchartCreateRequire } from 'module'; if (!globalThis.require) globalThis.require = __yamchartCreateRequire(import.meta.url);
2
2
  import {
3
3
  SemanticDefinitionSchema
4
- } from "./chunk-7HWFVUGP.js";
4
+ } from "./chunk-OYBI433Z.js";
5
5
 
6
6
  // ../../packages/query/dist/semantic/field-classifier.js
7
7
  var DIMENSION_ID_PATTERN = /(_id|_key|_code)$/i;
@@ -916,4 +916,4 @@ export {
916
916
  getDialect,
917
917
  compileMetricQuery
918
918
  };
919
- //# sourceMappingURL=chunk-X3UG6T3Q.js.map
919
+ //# sourceMappingURL=chunk-6ELSQNIH.js.map
@@ -2,7 +2,7 @@ import { createRequire as __yamchartCreateRequire } from 'module'; if (!globalTh
2
2
  import {
3
3
  SemanticModelBuilder,
4
4
  SemanticQueryCompiler
5
- } from "./chunk-X3UG6T3Q.js";
5
+ } from "./chunk-6ELSQNIH.js";
6
6
 
7
7
  // ../../packages/advisor/dist/dbt/knowledge.js
8
8
  import { readFile } from "fs/promises";
@@ -831,11 +831,17 @@ function resolveKey(c, env) {
831
831
  return env.OPENAI_API_KEY ?? "not-needed";
832
832
  }
833
833
  }
834
+ function resolveBatchSize(c) {
835
+ if (c.batch_size && c.batch_size > 0)
836
+ return c.batch_size;
837
+ return c.provider === "gemini" ? 1 : Infinity;
838
+ }
834
839
  function createEmbedder(cfg, env) {
835
840
  const c = cfg ?? { provider: "ollama", model: "nomic-embed-text" };
836
841
  const model = c.model ?? "nomic-embed-text";
837
842
  const baseURL = c.base_url ?? PRESET_BASE[c.provider] ?? "http://localhost:11434/v1";
838
843
  const apiKey = resolveKey(c, env);
844
+ const batchSize = resolveBatchSize(c);
839
845
  const client = new OpenAI2({ baseURL, apiKey });
840
846
  return {
841
847
  model,
@@ -845,8 +851,16 @@ function createEmbedder(cfg, env) {
845
851
  async embed(texts) {
846
852
  if (texts.length === 0)
847
853
  return [];
848
- const res = await this.client.embeddings.create({ model, input: texts });
849
- return res.data.map((d) => d.embedding);
854
+ const openai = this.client;
855
+ const out = [];
856
+ for (let i = 0; i < texts.length; i += batchSize) {
857
+ const chunk = texts.slice(i, i + batchSize);
858
+ const input = chunk.length === 1 ? chunk[0] : chunk;
859
+ const res = await openai.embeddings.create({ model, input });
860
+ for (const d of res.data)
861
+ out.push(d.embedding);
862
+ }
863
+ return out;
850
864
  }
851
865
  };
852
866
  }
@@ -942,6 +956,42 @@ async function updateSchemaYml(projectPath, schemaPath, entry) {
942
956
  return fullPath;
943
957
  }
944
958
 
959
+ // ../../packages/advisor/dist/dbt/scaffold.js
960
+ import { stringify as stringifyYaml2 } from "yaml";
961
+ var MODEL_NAME_RE = /^[a-zA-Z0-9_]+$/;
962
+ function scaffoldModelSql(sm) {
963
+ const header = [
964
+ `-- ${sm.description}`,
965
+ `--`,
966
+ `-- Why this model: ${sm.rationale}`,
967
+ `--`,
968
+ `-- TODO: implement the query. This stub was scaffolded from an accepted opportunity blindspot.`,
969
+ ``
970
+ ];
971
+ const cols = sm.columns.length ? sm.columns.map((c, i) => ` ${c.name}${i < sm.columns.length - 1 ? "," : ""}${c.description ? ` -- ${c.description}` : ""}`) : [" *"];
972
+ return [...header, "select", ...cols, "from {{ ref('TODO_upstream_model') }}"].join("\n");
973
+ }
974
+ function buildMartFiles(sm, opts) {
975
+ if (!MODEL_NAME_RE.test(sm.name)) {
976
+ throw new Error(`Invalid model name "${sm.name}": must match ${MODEL_NAME_RE.source}`);
977
+ }
978
+ const base = opts.modelsPath.replace(/\/+$/, "");
979
+ const yml = stringifyYaml2({
980
+ version: 2,
981
+ models: [
982
+ {
983
+ name: sm.name,
984
+ description: sm.description,
985
+ columns: sm.columns.map((c) => c.description ? { name: c.name, description: c.description } : { name: c.name })
986
+ }
987
+ ]
988
+ }, { indent: 2 });
989
+ return [
990
+ { relPath: `${base}/${sm.name}.sql`, content: scaffoldModelSql(sm) },
991
+ { relPath: `${base}/${sm.name}.yml`, content: yml }
992
+ ];
993
+ }
994
+
945
995
  export {
946
996
  KNOWLEDGE_TOPICS,
947
997
  loadKnowledge,
@@ -961,6 +1011,8 @@ export {
961
1011
  formatModelSql,
962
1012
  buildSchemaYmlEntry,
963
1013
  writeDbtModel,
964
- updateSchemaYml
1014
+ updateSchemaYml,
1015
+ scaffoldModelSql,
1016
+ buildMartFiles
965
1017
  };
966
- //# sourceMappingURL=chunk-UOSOZT47.js.map
1018
+ //# sourceMappingURL=chunk-KDDO4UII.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../packages/advisor/src/dbt/knowledge.ts","../../../packages/advisor/src/dbt/project.ts","../../../packages/advisor/src/tools.ts","../../../packages/advisor/src/agent.ts","../../../packages/advisor/src/providers/anthropic.ts","../../../packages/advisor/src/providers/openai-compatible.ts","../../../packages/advisor/src/providers/factory.ts","../../../packages/advisor/src/providers/embedder.ts","../../../packages/advisor/src/dbt/writer.ts","../../../packages/advisor/src/dbt/scaffold.ts"],"sourcesContent":["import { readFile } from 'fs/promises';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst KNOWLEDGE_DIR = join(__dirname, '..', 'knowledge');\n\nexport const KNOWLEDGE_TOPICS = [\n 'materializations',\n 'incremental',\n 'macros',\n 'testing',\n 'naming',\n 'performance',\n 'sources',\n] as const;\n\nexport type KnowledgeTopic = (typeof KNOWLEDGE_TOPICS)[number];\n\nexport async function loadKnowledge(topic: string): Promise<string> {\n if (!KNOWLEDGE_TOPICS.includes(topic as KnowledgeTopic)) {\n return `Unknown topic: \"${topic}\". Available topics: ${KNOWLEDGE_TOPICS.join(', ')}`;\n }\n\n const filePath = join(KNOWLEDGE_DIR, `${topic}.md`);\n return readFile(filePath, 'utf-8');\n}\n\nexport function getKnowledgeOverview(): string {\n return `You have access to a dbt knowledge base via the get_knowledge tool. Available topics:\n${KNOWLEDGE_TOPICS.map((t) => `- ${t}`).join('\\n')}\n\nUse get_knowledge when you need specifics on materializations, incremental strategies, Jinja macros, testing, naming conventions, or performance optimization.`;\n}\n","import { readFile } from 'fs/promises';\nimport { join, basename, relative, dirname } from 'path';\nimport fg from 'fast-glob';\nimport { parse as parseYaml } from 'yaml';\n\nexport interface DbtConventions {\n folderStructure: string[];\n namingPrefixes: Record<string, string>;\n commonMaterializations: Record<string, string>;\n schemaYmlPattern: 'per-folder' | 'per-model' | 'single-file';\n testPatterns: string[];\n}\n\nexport interface DbtModelInfo {\n name: string;\n path: string;\n layer: string;\n materialization: string;\n folder: string;\n}\n\ninterface DbtProjectYml {\n name: string;\n 'model-paths'?: string[];\n model_paths?: string[];\n}\n\nasync function getModelPaths(projectPath: string): Promise<string[]> {\n const content = await readFile(join(projectPath, 'dbt_project.yml'), 'utf-8');\n const parsed = parseYaml(content) as DbtProjectYml;\n return parsed['model-paths'] ?? parsed.model_paths ?? ['models'];\n}\n\nfunction extractMaterialization(sql: string): string {\n const match = sql.match(/materialized\\s*=\\s*['\"](\\w+)['\"]/);\n return match?.[1] ?? 'view';\n}\n\nfunction detectLayer(relativePath: string): string {\n const parts = relativePath.split('/');\n return parts[0] ?? 'unknown';\n}\n\nfunction detectPrefix(\n models: Array<{ name: string; layer: string }>\n): Record<string, string> {\n const prefixesByLayer = new Map<string, Map<string, number>>();\n\n for (const model of models) {\n const underscoreIdx = model.name.indexOf('_');\n if (underscoreIdx === -1) continue;\n const prefix = model.name.slice(0, underscoreIdx + 1);\n\n if (!prefixesByLayer.has(model.layer)) {\n prefixesByLayer.set(model.layer, new Map());\n }\n const counts = prefixesByLayer.get(model.layer)!;\n counts.set(prefix, (counts.get(prefix) ?? 0) + 1);\n }\n\n const result: Record<string, string> = {};\n for (const [layer, counts] of prefixesByLayer) {\n let maxCount = 0;\n let maxPrefix = '';\n for (const [prefix, count] of counts) {\n if (count > maxCount) {\n maxCount = count;\n maxPrefix = prefix;\n }\n }\n if (maxPrefix && maxCount >= 2) {\n result[layer] = maxPrefix;\n }\n }\n\n return result;\n}\n\nfunction detectMaterializations(\n models: Array<{ layer: string; materialization: string }>\n): Record<string, string> {\n const matByLayer = new Map<string, Map<string, number>>();\n\n for (const model of models) {\n if (!matByLayer.has(model.layer)) {\n matByLayer.set(model.layer, new Map());\n }\n const counts = matByLayer.get(model.layer)!;\n counts.set(model.materialization, (counts.get(model.materialization) ?? 0) + 1);\n }\n\n const result: Record<string, string> = {};\n for (const [layer, counts] of matByLayer) {\n let maxCount = 0;\n let maxMat = '';\n for (const [mat, count] of counts) {\n if (count > maxCount) {\n maxCount = count;\n maxMat = mat;\n }\n }\n if (maxMat) result[layer] = maxMat;\n }\n\n return result;\n}\n\nasync function detectSchemaYmlPattern(\n projectPath: string,\n modelPaths: string[]\n): Promise<'per-folder' | 'per-model' | 'single-file'> {\n const ymlFiles: string[] = [];\n for (const mp of modelPaths) {\n const pattern = join(projectPath, mp, '**/*.yml');\n const files = await fg(pattern, { ignore: ['**/node_modules/**'] });\n ymlFiles.push(...files);\n }\n\n if (ymlFiles.length === 0) return 'per-folder';\n if (ymlFiles.length === 1) return 'single-file';\n\n const dirs = new Set(ymlFiles.map((f) => dirname(f)));\n return dirs.size > 1 ? 'per-folder' : 'single-file';\n}\n\nexport async function detectConventions(projectPath: string): Promise<DbtConventions> {\n const modelPaths = await getModelPaths(projectPath);\n const models = await listDbtModels(projectPath);\n\n const folders = [...new Set(models.map((m) => m.layer))].filter((l) => l !== 'unknown');\n\n return {\n folderStructure: folders,\n namingPrefixes: detectPrefix(models),\n commonMaterializations: detectMaterializations(models),\n schemaYmlPattern: await detectSchemaYmlPattern(projectPath, modelPaths),\n testPatterns: [],\n };\n}\n\nexport async function listDbtModels(projectPath: string): Promise<DbtModelInfo[]> {\n const modelPaths = await getModelPaths(projectPath);\n const models: DbtModelInfo[] = [];\n\n for (const mp of modelPaths) {\n const pattern = join(projectPath, mp, '**/*.sql');\n const files = await fg(pattern, { ignore: ['**/node_modules/**'] });\n\n for (const file of files) {\n const relPath = relative(join(projectPath, mp), file);\n const name = basename(file, '.sql');\n const sql = await readFile(file, 'utf-8');\n const materialization = extractMaterialization(sql);\n const layer = detectLayer(relPath);\n const folder = dirname(relPath);\n\n models.push({ name, path: relPath, layer, materialization, folder });\n }\n }\n\n return models;\n}\n\nexport async function readDbtModel(\n projectPath: string,\n modelName: string\n): Promise<string | null> {\n const models = await listDbtModels(projectPath);\n const model = models.find((m) => m.name === modelName);\n if (!model) return null;\n\n const modelPaths = await getModelPaths(projectPath);\n for (const mp of modelPaths) {\n const fullPath = join(projectPath, mp, model.path);\n try {\n return await readFile(fullPath, 'utf-8');\n } catch {\n continue;\n }\n }\n return null;\n}\n","import type { ToolDefinition } from './providers/types.js';\nimport type { AdvisorContext } from './context.js';\nimport { loadKnowledge } from './dbt/knowledge.js';\nimport { readDbtModel } from './dbt/project.js';\nimport { SemanticModelBuilder, SemanticQueryCompiler } from '@yamchart/query';\nimport type { SemanticFilter } from '@yamchart/schema';\n\nexport type { AdvisorContext } from './context.js';\n\nexport const TOOL_DEFINITIONS: ToolDefinition[] = [\n // Read-only tools\n {\n name: 'list_yamchart_models',\n description: 'List all yamchart SQL models with names, descriptions, parameters, and return columns',\n parameters: { type: 'object', properties: {}, required: [] },\n },\n {\n name: 'list_charts',\n description: 'List all yamchart charts showing which models they reference and their chart type',\n parameters: { type: 'object', properties: {}, required: [] },\n },\n {\n name: 'get_catalog',\n description: 'Get the dbt catalog (.yamchart/catalog.md) with upstream table schemas and column metadata',\n parameters: { type: 'object', properties: {}, required: [] },\n },\n {\n name: 'get_warehouse_table',\n description: 'Get detailed column metadata and sample rows for a specific warehouse table from the cached catalog. Instant — reads from local catalog, no live query. Use the fully-qualified name (e.g. RAW.PAYMENTS).',\n parameters: {\n type: 'object',\n properties: {\n table: { type: 'string', description: 'Fully-qualified table name (e.g. RAW.PAYMENTS, STAGING.CUSTOMERS)' },\n },\n required: ['table'],\n },\n },\n {\n name: 'get_warehouse_tables',\n description: 'Get detailed metadata for multiple warehouse tables at once from the cached catalog.',\n parameters: {\n type: 'object',\n properties: {\n tables: { type: 'array', items: { type: 'string' }, description: 'List of fully-qualified table names' },\n },\n required: ['tables'],\n },\n },\n {\n name: 'introspect_warehouse',\n description: 'Query the live warehouse. Use for discovering raw tables not yet modeled in dbt.',\n parameters: {\n type: 'object',\n properties: {\n sql: { type: 'string', description: 'SQL query to execute (e.g. SHOW TABLES, SELECT * FROM information_schema.columns)' },\n },\n required: ['sql'],\n },\n },\n {\n name: 'sample_data',\n description: 'Preview rows from a table in the warehouse',\n parameters: {\n type: 'object',\n properties: {\n table: { type: 'string', description: 'Table name (can be schema-qualified)' },\n limit: { type: 'number', description: 'Number of rows to return (default: 5)' },\n },\n required: ['table'],\n },\n },\n {\n name: 'read_dbt_model',\n description: 'Read the full SQL source of an existing dbt model',\n parameters: {\n type: 'object',\n properties: {\n model_name: { type: 'string', description: 'Name of the dbt model to read' },\n },\n required: ['model_name'],\n },\n },\n {\n name: 'list_dbt_models',\n description: 'List all dbt models with their layer (staging/intermediate/marts), materialization, and folder',\n parameters: { type: 'object', properties: {}, required: [] },\n },\n {\n name: 'get_knowledge',\n description: 'Look up dbt reference documentation on a topic: materializations, incremental, macros, testing, naming, performance',\n parameters: {\n type: 'object',\n properties: {\n topic: { type: 'string', description: 'Topic name: materializations, incremental, macros, testing, naming, performance' },\n },\n required: ['topic'],\n },\n },\n {\n name: 'list_semantic_entities',\n description: 'List all semantic entities (auto-generated from the catalog) with their measures and dimensions. Use this to understand what data is available for structured queries without writing SQL.',\n parameters: { type: 'object', properties: {}, required: [] },\n },\n {\n name: 'semantic_query',\n description: 'Run a structured query against the semantic layer. Specify an entity, measures to aggregate, and optional dimensions to group by. Returns the compiled SQL.',\n parameters: {\n type: 'object',\n properties: {\n entity: { type: 'string', description: 'Entity name (e.g. fct_revenue)' },\n measures: { type: 'array', items: { type: 'string' }, description: 'Measure names to aggregate' },\n dimensions: { type: 'array', items: { type: 'string' }, description: 'Dimension names to group by (optional)' },\n filters: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n dimension: { type: 'string' },\n operator: { type: 'string', description: 'equals, not_equals, contains, gt, gte, lt, lte, in, not_in' },\n value: { description: 'Filter value (string, number, or array for in/not_in)' },\n },\n required: ['dimension', 'operator', 'value'],\n },\n description: 'Optional filters',\n },\n limit: { type: 'number', description: 'Row limit (default: 100)' },\n },\n required: ['entity', 'measures'],\n },\n },\n\n // Action tools\n {\n name: 'propose_model',\n description: 'Propose a new dbt model. Call this when you have a suggestion to present to the user.',\n parameters: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Model name (snake_case)' },\n description: { type: 'string', description: 'One-line description of what this model does' },\n sql: { type: 'string', description: 'Full SQL for the model (may include Jinja)' },\n layer: { type: 'string', description: 'dbt layer: staging, intermediate, or marts' },\n materialization: { type: 'string', description: 'Materialization: view, table, or incremental' },\n explanation: { type: 'string', description: 'Why this model is useful (2-3 sentences)' },\n subfolder: { type: 'string', description: 'Optional subfolder within the layer (e.g. \"stripe\", \"core\")' },\n columns: {\n type: 'array',\n description: 'Column definitions for schema.yml',\n items: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n description: { type: 'string' },\n tests: { type: 'array', items: { type: 'string' } },\n },\n required: ['name'],\n },\n },\n },\n required: ['name', 'description', 'sql', 'layer', 'materialization', 'explanation'],\n },\n },\n {\n name: 'write_dbt_model',\n description: 'Write a proposed dbt model SQL file to the dbt project. Only call after proposing and user confirmation.',\n parameters: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Model name (must match a previous proposal)' },\n },\n required: ['name'],\n },\n },\n {\n name: 'update_schema_yml',\n description: 'Add or update the model entry in the appropriate schema.yml file. Only call after writing the model.',\n parameters: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Model name (must match a written model)' },\n },\n required: ['name'],\n },\n },\n];\n\nexport async function executeToolCall(\n context: AdvisorContext,\n toolName: string,\n input: Record<string, unknown>\n): Promise<string> {\n switch (toolName) {\n case 'list_yamchart_models':\n return JSON.stringify(\n context.yamchart.models.map((m) => ({\n name: m.name,\n description: m.description,\n params: m.params,\n returns: m.returns,\n }))\n );\n\n case 'list_charts':\n return JSON.stringify(\n context.yamchart.charts.map((c) => ({\n name: c.name,\n title: c.title,\n model: c.model,\n type: c.type,\n }))\n );\n\n case 'get_catalog':\n return context.yamchart.catalog ?? 'No dbt catalog found. Run `yamchart sync-dbt` to create one.';\n\n case 'get_warehouse_table': {\n if (!context.yamchart.catalogJson) {\n return 'Warehouse catalog not available. Run `yamchart sync-warehouse` to populate it.';\n }\n const tableName = (input.table as string).toUpperCase();\n const match = context.yamchart.catalogJson.models.find(\n (m) => (m.table || '').toUpperCase() === tableName || m.name.toUpperCase() === tableName\n );\n if (!match) {\n return JSON.stringify({ error: `Table not found in catalog: ${input.table}. Use get_catalog to see available tables.` });\n }\n return JSON.stringify({\n name: match.name,\n table: match.table,\n tableType: match.tableType,\n source: match.source,\n columns: match.columns,\n sampleRows: match.sampleRows || [],\n });\n }\n\n case 'get_warehouse_tables': {\n if (!context.yamchart.catalogJson) {\n return 'Warehouse catalog not available. Run `yamchart sync-warehouse` to populate it.';\n }\n const tableNames = (input.tables as string[]).map((t) => t.toUpperCase());\n const results = tableNames.map((name) => {\n const match = context.yamchart.catalogJson!.models.find(\n (m) => (m.table || '').toUpperCase() === name || m.name.toUpperCase() === name\n );\n if (!match) {\n return { error: `Not found: ${name}` };\n }\n return {\n name: match.name,\n table: match.table,\n tableType: match.tableType,\n source: match.source,\n columns: match.columns,\n sampleRows: match.sampleRows || [],\n };\n });\n return JSON.stringify(results);\n }\n\n case 'introspect_warehouse': {\n if (!context.warehouse) {\n return 'Warehouse introspection not available. No database connection configured.';\n }\n const sql = input.sql as string;\n try {\n const result = await context.warehouse.executeSql(sql);\n return JSON.stringify(result);\n } catch (err) {\n return JSON.stringify({ error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n case 'sample_data': {\n if (!context.warehouse) {\n return 'Warehouse not available. No database connection configured.';\n }\n const table = input.table as string;\n const limit = (input.limit as number) ?? 5;\n try {\n const result = await context.warehouse.executeSql(\n `SELECT * FROM ${table} LIMIT ${limit}`\n );\n return JSON.stringify(result);\n } catch (err) {\n return JSON.stringify({ error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n case 'read_dbt_model': {\n const modelName = input.model_name as string;\n const sql = await readDbtModel(context.dbt.projectPath, modelName);\n if (!sql) {\n return JSON.stringify({ error: `Model not found: ${modelName}` });\n }\n return JSON.stringify({ name: modelName, sql });\n }\n\n case 'list_dbt_models':\n return JSON.stringify(\n context.dbt.models.map((m) => ({\n name: m.name,\n path: m.path,\n layer: m.layer,\n materialization: m.materialization,\n folder: m.folder,\n }))\n );\n\n case 'get_knowledge': {\n const topic = input.topic as string;\n return loadKnowledge(topic);\n }\n\n case 'list_semantic_entities': {\n if (!context.yamchart.catalogJson) {\n return 'No catalog available. Run `yamchart sync-warehouse` or `yamchart sync-dbt` to populate it.';\n }\n const builder = new SemanticModelBuilder();\n const model = builder.build({ catalog: { models: context.yamchart.catalogJson.models } });\n return JSON.stringify(\n model.entities.map((e) => ({\n name: e.name,\n source_table: e.source_table,\n description: e.description,\n measures: e.measures.map((m) => ({ name: m.name, type: m.type })),\n dimensions: e.dimensions.map((d) => ({ name: d.name, type: d.type })),\n }))\n );\n }\n\n case 'semantic_query': {\n if (!context.yamchart.catalogJson) {\n return JSON.stringify({ error: 'No catalog available. Run `yamchart sync-warehouse` or `yamchart sync-dbt` to populate it.' });\n }\n try {\n const builder = new SemanticModelBuilder();\n const model = builder.build({ catalog: { models: context.yamchart.catalogJson.models } });\n const compiler = new SemanticQueryCompiler();\n const sql = compiler.compile(model, {\n model: input.entity as string,\n measures: (input.measures as string[]) || [],\n dimensions: (input.dimensions as string[]) || [],\n filters: (input.filters as SemanticFilter[]) || [],\n limit: (input.limit as number) || 100,\n });\n return JSON.stringify({ sql, entity: input.entity });\n } catch (err) {\n return JSON.stringify({ error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n case 'propose_model':\n return JSON.stringify({\n status: 'proposed',\n name: input.name,\n description: input.description,\n sql: input.sql,\n layer: input.layer,\n materialization: input.materialization,\n explanation: input.explanation,\n subfolder: input.subfolder,\n columns: input.columns,\n });\n\n case 'write_dbt_model':\n // Actual writing happens in the CLI command, not here.\n // The agent tool just signals intent — the CLI confirms with the user.\n return JSON.stringify({\n status: 'pending_confirmation',\n name: input.name,\n message: 'Model write requested. Waiting for user confirmation.',\n });\n\n case 'update_schema_yml':\n return JSON.stringify({\n status: 'pending_confirmation',\n name: input.name,\n message: 'Schema.yml update requested. Waiting for user confirmation.',\n });\n\n default:\n return JSON.stringify({ error: `Unknown tool: ${toolName}` });\n }\n}\n","import type {\n LLMProvider,\n Message,\n ContentBlock,\n TextBlock,\n ToolUseBlock,\n ToolResultBlock,\n} from './providers/types.js';\nimport type { AdvisorContext } from './context.js';\nimport { TOOL_DEFINITIONS, executeToolCall } from './tools.js';\nimport { getKnowledgeOverview } from './dbt/knowledge.js';\n\nexport interface Proposal {\n name: string;\n description: string;\n sql: string;\n layer: string;\n materialization: string;\n explanation: string;\n subfolder?: string;\n columns?: Array<{ name: string; description?: string; tests?: string[] }>;\n}\n\nexport interface AgentResult {\n response: string;\n proposals: Proposal[];\n messages: Message[];\n}\n\nexport const SYSTEM_PROMPT = `You are a dbt advisor for yamchart projects. You analyze the BI layer (yamchart models, charts, dashboards) and the data engineering layer (dbt models, warehouse tables) to suggest improvements to dbt models.\n\nThink like a senior data engineer. Your goals:\n- Understand what the BI layer needs (charts, filters, drill-downs, date ranges)\n- Identify gaps in the dbt project (missing models, incomplete staging, opportunities for pre-aggregation)\n- Suggest new dbt models that serve the BI layer better\n- Follow the project's existing conventions (folder structure, naming, materializations)\n\nWhen proposing models:\n- Match the project's naming conventions (detect and follow existing prefixes like stg_, fct_, dim_)\n- Place models in the correct layer and folder\n- Choose appropriate materializations\n- Include column descriptions and tests in proposals\n- Explain WHY the model helps, not just WHAT it does\n- Use ref() and source() macros correctly\n\nWhen working with cross-database tables:\n- If a table lives outside the primary analytics database, recommend creating a dbt source definition in sources.yml\n- Follow the pattern: source → staging model → downstream refs\n- Use get_knowledge('sources') for detailed source patterns\n- Check the warehouse catalog (get_warehouse_tables) to identify tables in other databases\n\nWhen in audit mode:\n- Evaluate: coverage gaps, convention violations, materialization mismatches, missing tests\n- Rank suggestions by impact\n- Be concise — focus on actionable improvements\n\n${getKnowledgeOverview()}\n\nWhen you have a suggestion, call propose_model with the full SQL and metadata. Do NOT call write_dbt_model or update_schema_yml directly — the user will be prompted to confirm before writing.`;\n\nconst MAX_TOOL_ROUNDS = 15;\n\nexport class AdvisorAgent {\n private provider: LLMProvider;\n\n constructor(provider: LLMProvider) {\n this.provider = provider;\n }\n\n async run(\n context: AdvisorContext,\n userMessages: Message[]\n ): Promise<AgentResult> {\n const proposals: Proposal[] = [];\n const messages: Message[] = [...userMessages];\n\n // Build context-specific system prompt\n const systemPrompt = this.buildSystemPrompt(context);\n\n for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {\n const response = await this.provider.chat({\n system: systemPrompt,\n messages,\n tools: TOOL_DEFINITIONS,\n });\n\n const textBlocks = response.content.filter(\n (b): b is TextBlock => b.type === 'text'\n );\n const toolUseBlocks = response.content.filter(\n (b): b is ToolUseBlock => b.type === 'tool_use'\n );\n\n // No tool calls — return final text response\n if (toolUseBlocks.length === 0) {\n const responseText = textBlocks.map((b) => b.text).join('\\n');\n return { response: responseText, proposals, messages };\n }\n\n // Add assistant message with tool calls\n messages.push({ role: 'assistant', content: response.content });\n\n // Execute each tool call\n const toolResults: ContentBlock[] = [];\n for (const toolUse of toolUseBlocks) {\n const result = await executeToolCall(context, toolUse.name, toolUse.input);\n\n // Collect proposals\n if (toolUse.name === 'propose_model') {\n const parsed = JSON.parse(result) as Record<string, unknown>;\n proposals.push({\n name: parsed.name as string,\n description: parsed.description as string,\n sql: toolUse.input.sql as string,\n layer: toolUse.input.layer as string,\n materialization: toolUse.input.materialization as string,\n explanation: toolUse.input.explanation as string,\n subfolder: toolUse.input.subfolder as string | undefined,\n columns: toolUse.input.columns as Proposal['columns'],\n });\n }\n\n toolResults.push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: result,\n } as ToolResultBlock);\n }\n\n // Add tool results as user message\n messages.push({ role: 'user', content: toolResults });\n }\n\n // Hit max rounds — return what we have\n return {\n response: 'Reached maximum tool call rounds. Here are the suggestions gathered so far.',\n proposals,\n messages,\n };\n }\n\n private buildSystemPrompt(context: AdvisorContext): string {\n const parts = [SYSTEM_PROMPT];\n\n // Add project summary\n parts.push(`\\n## Current Project Summary`);\n parts.push(`- Yamchart: ${context.yamchart.models.length} SQL models, ${context.yamchart.charts.length} charts, ${context.yamchart.dashboards.length} dashboards`);\n parts.push(`- dbt project: \"${context.dbt.projectName}\" at ${context.dbt.projectPath}`);\n parts.push(`- dbt models: ${context.dbt.models.length} (layers: ${context.dbt.conventions.folderStructure.join(', ') || 'none detected'})`);\n\n if (Object.keys(context.dbt.conventions.namingPrefixes).length > 0) {\n const prefixes = Object.entries(context.dbt.conventions.namingPrefixes)\n .map(([layer, prefix]) => `${layer}: ${prefix}`)\n .join(', ');\n parts.push(`- Naming prefixes: ${prefixes}`);\n }\n\n if (Object.keys(context.dbt.conventions.commonMaterializations).length > 0) {\n const mats = Object.entries(context.dbt.conventions.commonMaterializations)\n .map(([layer, mat]) => `${layer}: ${mat}`)\n .join(', ');\n parts.push(`- Materializations: ${mats}`);\n }\n\n parts.push(`- Schema.yml pattern: ${context.dbt.conventions.schemaYmlPattern}`);\n parts.push(`- Catalog: ${context.yamchart.catalog ? 'available' : 'not synced'}`);\n parts.push(`- Warehouse: ${context.warehouse ? `connected (${context.warehouse.connectionType})` : 'not connected'}`);\n\n return parts.join('\\n');\n }\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport type {\n LLMProvider,\n LLMResponse,\n Message,\n ToolDefinition,\n ContentBlock,\n TextBlock,\n ToolUseBlock,\n} from './types.js';\n\nexport class AnthropicProvider implements LLMProvider {\n private client: Anthropic;\n private model: string;\n\n constructor(apiKey: string, model: string = 'claude-sonnet-4-5-20250929') {\n this.client = new Anthropic({ apiKey });\n this.model = model;\n }\n\n async chat(options: {\n system: string;\n messages: Message[];\n tools: ToolDefinition[];\n maxTokens?: number;\n }): Promise<LLMResponse> {\n const tools: Anthropic.Tool[] = options.tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: {\n type: 'object' as const,\n properties: t.parameters.properties,\n required: t.parameters.required ?? [],\n },\n }));\n\n const messages: Anthropic.MessageParam[] = options.messages.map((m) => {\n if (typeof m.content === 'string') {\n return { role: m.role, content: m.content };\n }\n const blocks: Anthropic.ContentBlockParam[] = m.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: (block as TextBlock).text };\n }\n if (block.type === 'tool_use') {\n const tu = block as ToolUseBlock;\n return { type: 'tool_use' as const, id: tu.id, name: tu.name, input: tu.input };\n }\n if (block.type === 'tool_result') {\n const tr = block as { type: 'tool_result'; tool_use_id: string; content: string };\n return { type: 'tool_result' as const, tool_use_id: tr.tool_use_id, content: tr.content };\n }\n throw new Error(`Unknown block type: ${block.type}`);\n });\n return { role: m.role, content: blocks };\n });\n\n const response = await this.client.messages.create({\n model: this.model,\n max_tokens: options.maxTokens ?? 4096,\n system: options.system,\n tools,\n messages,\n });\n\n const content: ContentBlock[] = response.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text', text: block.text } as TextBlock;\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use',\n id: block.id,\n name: block.name,\n input: block.input as Record<string, unknown>,\n } as ToolUseBlock;\n }\n throw new Error(`Unexpected block type: ${block.type}`);\n });\n\n return {\n content,\n stopReason: response.stop_reason === 'tool_use' ? 'tool_use' : 'end',\n };\n }\n}\n","// packages/advisor/src/providers/openai-compatible.ts\nimport OpenAI from 'openai';\nimport type {\n LLMProvider,\n LLMResponse,\n Message,\n ToolDefinition,\n ContentBlock,\n TextBlock,\n ToolUseBlock,\n} from './types.js';\n\nexport interface OpenAICompatibleOptions {\n baseURL: string;\n apiKey?: string;\n model: string;\n}\n\nexport class OpenAICompatibleProvider implements LLMProvider {\n private client: OpenAI;\n private model: string;\n\n constructor(opts: OpenAICompatibleOptions) {\n this.client = new OpenAI({ baseURL: opts.baseURL, apiKey: opts.apiKey ?? 'not-needed' });\n this.model = opts.model;\n }\n\n async chat(options: {\n system: string;\n messages: Message[];\n tools: ToolDefinition[];\n maxTokens?: number;\n }): Promise<LLMResponse> {\n const tools = options.tools.map((t) => ({\n type: 'function' as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: {\n type: 'object',\n properties: t.parameters.properties,\n required: t.parameters.required ?? [],\n },\n },\n }));\n\n const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [\n { role: 'system', content: options.system },\n ];\n\n for (const m of options.messages) {\n if (typeof m.content === 'string') {\n messages.push({ role: m.role, content: m.content });\n continue;\n }\n // Anthropic-style content blocks → OpenAI shape.\n const text = m.content\n .filter((b): b is TextBlock => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n const toolUses = m.content.filter((b): b is ToolUseBlock => b.type === 'tool_use');\n const toolResults = m.content.filter(\n (b): b is { type: 'tool_result'; tool_use_id: string; content: string } =>\n b.type === 'tool_result',\n );\n\n if (m.role === 'assistant' && toolUses.length) {\n messages.push({\n role: 'assistant',\n content: text || null,\n tool_calls: toolUses.map((tu) => ({\n id: tu.id,\n type: 'function',\n function: { name: tu.name, arguments: JSON.stringify(tu.input) },\n })),\n });\n } else if (toolResults.length) {\n // tool results become separate `tool` messages\n for (const tr of toolResults) {\n messages.push({ role: 'tool', tool_call_id: tr.tool_use_id, content: tr.content });\n }\n if (text) messages.push({ role: m.role, content: text });\n } else {\n messages.push({ role: m.role, content: text });\n }\n }\n\n const response = await this.client.chat.completions.create({\n model: this.model,\n max_tokens: options.maxTokens ?? 4096,\n messages,\n ...(tools.length ? { tools } : {}),\n });\n\n const choice = response.choices[0];\n const msg = choice?.message;\n const content: ContentBlock[] = [];\n\n if (msg?.content) {\n content.push({ type: 'text', text: msg.content } as TextBlock);\n }\n\n for (const tc of msg?.tool_calls ?? []) {\n let input: Record<string, unknown> = {};\n try {\n input = JSON.parse(tc.function.arguments || '{}');\n } catch {\n input = {};\n }\n content.push({ type: 'tool_use', id: tc.id, name: tc.function.name, input } as ToolUseBlock);\n }\n\n return {\n content,\n stopReason: choice?.finish_reason === 'tool_calls' ? 'tool_use' : 'end',\n };\n }\n}\n","// packages/advisor/src/providers/factory.ts\nimport type { LLMProvider } from './types.js';\nimport { AnthropicProvider } from './anthropic.js';\nimport { OpenAICompatibleProvider } from './openai-compatible.js';\n\nexport type ProviderKind = 'anthropic' | 'openai' | 'gemini' | 'ollama' | 'ollama_cloud' | 'openai_compatible';\nexport interface ProviderConfig { provider: ProviderKind; model?: string; base_url?: string; api_key_var?: string; api_key?: string; batch_size?: number; }\nexport interface AiConfig { default?: string; providers?: Record<string, ProviderConfig>; tasks?: Record<string, string>; }\nexport type AiTask = 'hunch_generation' | 'advisor' | 'blindspot_scan' | 'blindspot_reconcile' | 'knowledge_bootstrap' | 'answer' | 'text_generation';\n\nfunction requireKey(env: NodeJS.ProcessEnv, name: string): string {\n const v = env[name];\n if (!v) throw new Error(`Missing ${name} for the configured LLM provider.`);\n return v;\n}\nfunction requireModel(cfg: ProviderConfig): string {\n if (!cfg.model) throw new Error(`The \"${cfg.provider}\" provider requires a model.`);\n return cfg.model;\n}\nfunction resolveProviderKey(cfg: ProviderConfig, env: NodeJS.ProcessEnv, defaultVar: string): string {\n if (cfg.api_key) return cfg.api_key;\n return requireKey(env, cfg.api_key_var ?? defaultVar);\n}\n\nexport function buildProvider(cfg: ProviderConfig, env: NodeJS.ProcessEnv): LLMProvider {\n switch (cfg.provider) {\n case 'anthropic':\n return new AnthropicProvider(resolveProviderKey(cfg, env, 'ANTHROPIC_API_KEY'), cfg.model);\n case 'openai':\n return new OpenAICompatibleProvider({ baseURL: cfg.base_url ?? 'https://api.openai.com/v1', apiKey: resolveProviderKey(cfg, env, 'OPENAI_API_KEY'), model: requireModel(cfg) });\n case 'gemini':\n return new OpenAICompatibleProvider({ baseURL: cfg.base_url ?? 'https://generativelanguage.googleapis.com/v1beta/openai/', apiKey: resolveProviderKey(cfg, env, env.GEMINI_API_KEY ? 'GEMINI_API_KEY' : 'GOOGLE_API_KEY'), model: requireModel(cfg) });\n case 'ollama':\n return new OpenAICompatibleProvider({ baseURL: cfg.base_url ?? 'http://localhost:11434/v1', apiKey: cfg.api_key ?? 'ollama', model: requireModel(cfg) });\n case 'ollama_cloud':\n return new OpenAICompatibleProvider({ baseURL: cfg.base_url ?? 'https://ollama.com/v1', apiKey: resolveProviderKey(cfg, env, 'OLLAMA_API_KEY'), model: requireModel(cfg) });\n case 'openai_compatible':\n if (!cfg.base_url) throw new Error('openai_compatible requires base_url.');\n return new OpenAICompatibleProvider({ baseURL: cfg.base_url, apiKey: cfg.api_key ?? (cfg.api_key_var ? requireKey(env, cfg.api_key_var) : 'not-needed'), model: requireModel(cfg) });\n }\n}\n\nexport function createProviderForTask(config: AiConfig | undefined, task: AiTask, env: NodeJS.ProcessEnv): LLMProvider {\n if (!config) return new AnthropicProvider(requireKey(env, 'ANTHROPIC_API_KEY'));\n const name = config.tasks?.[task] ?? config.default;\n const cfg = name ? config.providers?.[name] : undefined;\n if (!cfg) return new AnthropicProvider(requireKey(env, 'ANTHROPIC_API_KEY'));\n return buildProvider(cfg, env);\n}\n","import OpenAI from 'openai';\nimport type { ProviderConfig } from './factory.js';\n\nexport interface Embedder { model: string; baseURL: string; embed(texts: string[]): Promise<number[][]>; }\n\nconst PRESET_BASE: Record<string, string> = {\n ollama: 'http://localhost:11434/v1',\n ollama_cloud: 'https://ollama.com/v1',\n openai: 'https://api.openai.com/v1',\n gemini: 'https://generativelanguage.googleapis.com/v1beta/openai/',\n};\n\n// Resolve the API key per provider, mirroring buildProvider's preset logic so\n// e.g. Gemini reads GEMINI_API_KEY (not OPENAI_API_KEY). Ollama (local) needs no key.\nfunction resolveKey(c: ProviderConfig, env: NodeJS.ProcessEnv): string {\n if (c.api_key) return c.api_key;\n if (c.api_key_var) return env[c.api_key_var] ?? 'not-needed';\n switch (c.provider) {\n case 'ollama': return 'ollama';\n case 'gemini': return env.GEMINI_API_KEY ?? env.GOOGLE_API_KEY ?? 'not-needed';\n case 'ollama_cloud': return env.OLLAMA_API_KEY ?? 'not-needed';\n case 'openai': return env.OPENAI_API_KEY ?? 'not-needed';\n default: return env.OPENAI_API_KEY ?? 'not-needed';\n }\n}\n\n// Gemini's OpenAI-compat embeddings endpoint accepts only ONE input per request;\n// a multi-item array drops the connection (\"Premature close\"). Default Gemini to a\n// batch size of 1; other providers send the whole array in a single request unless\n// an explicit `batch_size` is configured.\nfunction resolveBatchSize(c: ProviderConfig): number {\n if (c.batch_size && c.batch_size > 0) return c.batch_size;\n return c.provider === 'gemini' ? 1 : Infinity;\n}\n\nexport function createEmbedder(cfg: ProviderConfig | undefined, env: NodeJS.ProcessEnv): Embedder | undefined {\n const c = cfg ?? { provider: 'ollama' as const, model: 'nomic-embed-text' };\n const model = c.model ?? 'nomic-embed-text';\n const baseURL = c.base_url ?? PRESET_BASE[c.provider] ?? 'http://localhost:11434/v1';\n const apiKey = resolveKey(c, env);\n const batchSize = resolveBatchSize(c);\n const client = new OpenAI({ baseURL, apiKey });\n return {\n model, baseURL, client, // `client` is internal; cast in tests\n async embed(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n const openai = (this as unknown as { client: OpenAI }).client;\n const out: number[][] = [];\n for (let i = 0; i < texts.length; i += batchSize) {\n const chunk = texts.slice(i, i + batchSize);\n // Send a single string for size-1 chunks (Gemini rejects arrays), an array otherwise.\n const input = chunk.length === 1 ? chunk[0]! : chunk;\n const res = await openai.embeddings.create({ model, input });\n for (const d of res.data) out.push(d.embedding as number[]);\n }\n return out;\n },\n } as Embedder & { client: OpenAI };\n}\n","import { readFile, writeFile, mkdir, access } from 'fs/promises';\nimport { join, dirname } from 'path';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport type { DbtConventions } from './project.js';\n\nexport function buildModelPath(\n modelName: string,\n layer: string | undefined,\n conventions: DbtConventions,\n subfolder?: string\n): string {\n const effectiveLayer = layer ?? (conventions.folderStructure.includes('marts') ? 'marts' : conventions.folderStructure[0] ?? 'models');\n const parts = ['models', effectiveLayer];\n if (subfolder) parts.push(subfolder);\n parts.push(`${modelName}.sql`);\n return parts.join('/');\n}\n\nexport function formatModelSql(options: {\n materialization: string;\n tags?: string[];\n sql: string;\n description?: string;\n}): string {\n const lines: string[] = [];\n\n // Only add config block for non-default materializations\n if (options.materialization !== 'view') {\n const configParts: string[] = [`materialized='${options.materialization}'`];\n if (options.tags && options.tags.length > 0) {\n configParts.push(`tags=[${options.tags.map((t) => `'${t}'`).join(', ')}]`);\n }\n lines.push(`{{\\n config(\\n ${configParts.join(',\\n ')}\\n )\\n}}\\n`);\n }\n\n lines.push(options.sql);\n return lines.join('\\n');\n}\n\nexport interface SchemaColumn {\n name: string;\n description?: string;\n tests?: string[];\n}\n\nexport function buildSchemaYmlEntry(options: {\n name: string;\n description: string;\n columns?: SchemaColumn[];\n}): string {\n const model: Record<string, unknown> = {\n name: options.name,\n description: options.description,\n };\n\n if (options.columns && options.columns.length > 0) {\n model.columns = options.columns.map((col) => {\n const entry: Record<string, unknown> = { name: col.name };\n if (col.description) entry.description = col.description;\n if (col.tests && col.tests.length > 0) entry.tests = col.tests;\n return entry;\n });\n }\n\n return stringifyYaml({ models: [model] }, { indent: 2 });\n}\n\nexport async function writeDbtModel(\n projectPath: string,\n modelPath: string,\n sql: string\n): Promise<string> {\n const fullPath = join(projectPath, modelPath);\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, sql + '\\n', 'utf-8');\n return fullPath;\n}\n\nexport async function updateSchemaYml(\n projectPath: string,\n schemaPath: string,\n entry: { name: string; description: string; columns?: SchemaColumn[] }\n): Promise<string> {\n const fullPath = join(projectPath, schemaPath);\n\n let existing: { version?: number; models?: Array<Record<string, unknown>> } = {\n version: 2,\n models: [],\n };\n\n try {\n await access(fullPath);\n const content = await readFile(fullPath, 'utf-8');\n existing = parseYaml(content) as typeof existing;\n if (!existing.models) existing.models = [];\n } catch {\n // File doesn't exist, start fresh\n await mkdir(dirname(fullPath), { recursive: true });\n }\n\n // Check if model already exists\n const idx = existing.models!.findIndex(\n (m) => m.name === entry.name\n );\n\n const modelEntry: Record<string, unknown> = {\n name: entry.name,\n description: entry.description,\n };\n if (entry.columns && entry.columns.length > 0) {\n modelEntry.columns = entry.columns.map((col) => {\n const c: Record<string, unknown> = { name: col.name };\n if (col.description) c.description = col.description;\n if (col.tests && col.tests.length > 0) c.tests = col.tests;\n return c;\n });\n }\n\n if (idx >= 0) {\n existing.models![idx] = modelEntry;\n } else {\n existing.models!.push(modelEntry);\n }\n\n await writeFile(fullPath, stringifyYaml(existing, { indent: 2 }), 'utf-8');\n return fullPath;\n}\n","import type { SuggestedModel } from '@yamchart/schema';\nimport { stringify as stringifyYaml } from 'yaml';\n\n/** A single file to write into a repo (relative path + UTF-8 content). Mirrors repo-writer's FileWrite. */\nexport interface FileWrite {\n relPath: string;\n content: string;\n}\n\n/** dbt model names: letters, digits, underscores only (path-traversal guard from OSS PR #73). */\nconst MODEL_NAME_RE = /^[a-zA-Z0-9_]+$/;\n\n/**\n * Build a LLM-free SQL skeleton stub for a suggested model.\n * (Lifted verbatim from apps/server/src/services/scaffold-model.ts so the OSS\n * and managed surfaces share one implementation.)\n */\nexport function scaffoldModelSql(sm: SuggestedModel): string {\n const header = [\n `-- ${sm.description}`,\n `--`,\n `-- Why this model: ${sm.rationale}`,\n `--`,\n `-- TODO: implement the query. This stub was scaffolded from an accepted opportunity blindspot.`,\n ``,\n ];\n const cols = sm.columns.length\n ? sm.columns.map(\n (c, i) =>\n ` ${c.name}${i < sm.columns.length - 1 ? ',' : ''}${c.description ? ` -- ${c.description}` : ''}`,\n )\n : [' *'];\n return [...header, 'select', ...cols, \"from {{ ref('TODO_upstream_model') }}\"].join('\\n');\n}\n\n/**\n * Turn a suggested model into dbt file writes: a `.sql` stub and a dedicated\n * `.yml` schema doc beside it. Throws if the model name is unsafe.\n */\nexport function buildMartFiles(sm: SuggestedModel, opts: { modelsPath: string }): FileWrite[] {\n if (!MODEL_NAME_RE.test(sm.name)) {\n throw new Error(`Invalid model name \"${sm.name}\": must match ${MODEL_NAME_RE.source}`);\n }\n const base = opts.modelsPath.replace(/\\/+$/, '');\n const yml = stringifyYaml(\n {\n version: 2,\n models: [\n {\n name: sm.name,\n description: sm.description,\n columns: sm.columns.map((c) =>\n c.description ? { name: c.name, description: c.description } : { name: c.name },\n ),\n },\n ],\n },\n { indent: 2 },\n );\n return [\n { relPath: `${base}/${sm.name}.sql`, content: scaffoldModelSql(sm) },\n { relPath: `${base}/${sm.name}.yml`, content: yml },\n ];\n}\n"],"mappings":"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","names":["readFile","join","dirname","OpenAI","readFile","join","dirname","parseYaml","stringifyYaml"]}
@@ -1,14 +1,14 @@
1
1
  import { createRequire as __yamchartCreateRequire } from 'module'; if (!globalThis.require) globalThis.require = __yamchartCreateRequire(import.meta.url);
2
2
  import {
3
3
  parseModelMetadata
4
- } from "./chunk-5CRXV5PQ.js";
4
+ } from "./chunk-2XJZJ6IA.js";
5
5
  import {
6
6
  ChartSchema,
7
7
  ConnectionSchema,
8
8
  DashboardSchema,
9
9
  ProjectSchema,
10
10
  ScheduleSchema
11
- } from "./chunk-7HWFVUGP.js";
11
+ } from "./chunk-OYBI433Z.js";
12
12
 
13
13
  // src/commands/validate.ts
14
14
  import { readFile, readdir, access } from "fs/promises";
@@ -278,7 +278,7 @@ function levenshtein(a, b) {
278
278
  return matrix[b.length][a.length];
279
279
  }
280
280
  async function dryRunValidation(projectDir, config, connectionName, errors) {
281
- const { DuckDBConnector } = await import("./dist-YB5RBWCC.js");
281
+ const { DuckDBConnector } = await import("./dist-Q5ETETUU.js");
282
282
  let passed = 0;
283
283
  let failed = 0;
284
284
  const connName = connectionName || config.project?.defaults?.connection;
@@ -361,4 +361,4 @@ export {
361
361
  findProjectRoot,
362
362
  loadEnvFile
363
363
  };
364
- //# sourceMappingURL=chunk-25ES7MGF.js.map
364
+ //# sourceMappingURL=chunk-ODSPBOJW.js.map
@@ -1008,6 +1008,7 @@ var ScheduleSchema = z8.discriminatedUnion("type", [
1008
1008
  // ../../packages/schema/dist/events.js
1009
1009
  import { z as z9 } from "zod";
1010
1010
  var EventSchema = z9.object({
1011
+ id: z9.string().optional(),
1011
1012
  date: z9.string(),
1012
1013
  endDate: z9.string().optional(),
1013
1014
  label: z9.string(),
@@ -1099,6 +1100,7 @@ var NewHunchSchema = z12.object({
1099
1100
  var HunchSchema = NewHunchSchema.extend({
1100
1101
  id: z12.string(),
1101
1102
  status: HunchStatusSchema,
1103
+ autoConfirmed: z12.boolean().default(false),
1102
1104
  lastRunSample: HunchSampleSchema.optional(),
1103
1105
  createdAt: z12.string(),
1104
1106
  updatedAt: z12.string()
@@ -1156,6 +1158,8 @@ var BlindspotSchema = z13.object({
1156
1158
  confidence: z13.number().optional(),
1157
1159
  status: BlindspotStatusSchema,
1158
1160
  answer: z13.string().optional(),
1161
+ prUrl: z13.string().optional(),
1162
+ resolvedByKnowledge: z13.boolean().default(false),
1159
1163
  createdAt: z13.string(),
1160
1164
  updatedAt: z13.string()
1161
1165
  });
@@ -1166,7 +1170,7 @@ var NewKnowledgeDocSchema = z14.object({
1166
1170
  connection: z14.string(),
1167
1171
  title: z14.string().min(1),
1168
1172
  content: z14.string().min(1),
1169
- source: z14.enum(["ui", "file"]).default("ui")
1173
+ source: z14.enum(["ui", "file", "website"]).default("ui")
1170
1174
  });
1171
1175
  var KnowledgeDocSchema = NewKnowledgeDocSchema.extend({
1172
1176
  id: z14.string(),
@@ -1174,6 +1178,55 @@ var KnowledgeDocSchema = NewKnowledgeDocSchema.extend({
1174
1178
  updatedAt: z14.string()
1175
1179
  });
1176
1180
 
1181
+ // ../../packages/schema/dist/slug.js
1182
+ var SLUG_REGEX = /^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])$/;
1183
+ var RESERVED_SLUGS = /* @__PURE__ */ new Set([
1184
+ "api",
1185
+ "auth",
1186
+ "app",
1187
+ "www",
1188
+ "admin",
1189
+ "login",
1190
+ "signup",
1191
+ "onboarding",
1192
+ "settings",
1193
+ "dashboard",
1194
+ "dashboards",
1195
+ "charts",
1196
+ "data",
1197
+ "ask",
1198
+ "mcp",
1199
+ "account",
1200
+ "billing",
1201
+ "help",
1202
+ "org",
1203
+ "orgs",
1204
+ "static",
1205
+ "assets",
1206
+ "public",
1207
+ "health",
1208
+ "well-known",
1209
+ "callback",
1210
+ "events"
1211
+ ]);
1212
+ function validateSlug(slug) {
1213
+ if (slug.length < 2 || slug.length > 32)
1214
+ return { ok: false, reason: "invalid" };
1215
+ if (!SLUG_REGEX.test(slug))
1216
+ return { ok: false, reason: "invalid" };
1217
+ if (RESERVED_SLUGS.has(slug))
1218
+ return { ok: false, reason: "reserved" };
1219
+ return { ok: true };
1220
+ }
1221
+ function deriveSlug(input) {
1222
+ let s = (input ?? "").trim().toLowerCase();
1223
+ if (!s)
1224
+ return "";
1225
+ if (s.includes(".") && !s.includes(" "))
1226
+ s = s.split(".")[0] ?? s;
1227
+ return s.replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32).replace(/-+$/g, "");
1228
+ }
1229
+
1177
1230
  // ../../packages/schema/dist/index.js
1178
1231
  var VERSION = "0.1.0";
1179
1232
 
@@ -1234,6 +1287,10 @@ export {
1234
1287
  BlindspotSchema,
1235
1288
  NewKnowledgeDocSchema,
1236
1289
  KnowledgeDocSchema,
1290
+ SLUG_REGEX,
1291
+ RESERVED_SLUGS,
1292
+ validateSlug,
1293
+ deriveSlug,
1237
1294
  VERSION
1238
1295
  };
1239
- //# sourceMappingURL=chunk-7HWFVUGP.js.map
1296
+ //# sourceMappingURL=chunk-OYBI433Z.js.map