@duckcodeailabs/dql-agent 1.6.20 → 1.6.22
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/agent-run-engine.d.ts +287 -0
- package/dist/agent-run-engine.d.ts.map +1 -0
- package/dist/agent-run-engine.js +916 -0
- package/dist/agent-run-engine.js.map +1 -0
- package/dist/agent-run-gates.d.ts +26 -0
- package/dist/agent-run-gates.d.ts.map +1 -0
- package/dist/agent-run-gates.js +170 -0
- package/dist/agent-run-gates.js.map +1 -0
- package/dist/agent-run-planner.d.ts +32 -0
- package/dist/agent-run-planner.d.ts.map +1 -0
- package/dist/agent-run-planner.js +280 -0
- package/dist/agent-run-planner.js.map +1 -0
- package/dist/answer-loop.d.ts +49 -0
- package/dist/answer-loop.d.ts.map +1 -1
- package/dist/answer-loop.js +292 -17
- package/dist/answer-loop.js.map +1 -1
- package/dist/app-builder.d.ts +44 -2
- package/dist/app-builder.d.ts.map +1 -1
- package/dist/app-builder.js +558 -123
- package/dist/app-builder.js.map +1 -1
- package/dist/app-planner.d.ts +78 -0
- package/dist/app-planner.d.ts.map +1 -0
- package/dist/app-planner.js +145 -0
- package/dist/app-planner.js.map +1 -0
- package/dist/embeddings/provider.d.ts +66 -0
- package/dist/embeddings/provider.d.ts.map +1 -0
- package/dist/embeddings/provider.js +105 -0
- package/dist/embeddings/provider.js.map +1 -0
- package/dist/hints/git-store.d.ts +69 -0
- package/dist/hints/git-store.d.ts.map +1 -0
- package/dist/hints/git-store.js +244 -0
- package/dist/hints/git-store.js.map +1 -0
- package/dist/hints/retrieval.d.ts +49 -0
- package/dist/hints/retrieval.d.ts.map +1 -0
- package/dist/hints/retrieval.js +60 -0
- package/dist/hints/retrieval.js.map +1 -0
- package/dist/hints/store.d.ts +39 -0
- package/dist/hints/store.d.ts.map +1 -0
- package/dist/hints/store.js +279 -0
- package/dist/hints/store.js.map +1 -0
- package/dist/hints/types.d.ts +147 -0
- package/dist/hints/types.d.ts.map +1 -0
- package/dist/hints/types.js +92 -0
- package/dist/hints/types.js.map +1 -0
- package/dist/index.d.ts +43 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -3
- package/dist/index.js.map +1 -1
- package/dist/intent-controller.d.ts +63 -0
- package/dist/intent-controller.d.ts.map +1 -0
- package/dist/intent-controller.js +150 -0
- package/dist/intent-controller.js.map +1 -0
- package/dist/kg/build.d.ts.map +1 -1
- package/dist/kg/build.js +2 -0
- package/dist/kg/build.js.map +1 -1
- package/dist/kg/sqlite-fts.js +4 -0
- package/dist/kg/sqlite-fts.js.map +1 -1
- package/dist/kg/types.d.ts +10 -0
- package/dist/kg/types.d.ts.map +1 -1
- package/dist/metadata/catalog.d.ts +81 -4
- package/dist/metadata/catalog.d.ts.map +1 -1
- package/dist/metadata/catalog.js +208 -1
- package/dist/metadata/catalog.js.map +1 -1
- package/dist/metadata/drafts.d.ts +22 -0
- package/dist/metadata/drafts.d.ts.map +1 -1
- package/dist/metadata/drafts.js +126 -2
- package/dist/metadata/drafts.js.map +1 -1
- package/dist/metadata/grain-gate.d.ts +61 -0
- package/dist/metadata/grain-gate.d.ts.map +1 -0
- package/dist/metadata/grain-gate.js +265 -0
- package/dist/metadata/grain-gate.js.map +1 -0
- package/dist/metadata/identity.d.ts +47 -0
- package/dist/metadata/identity.d.ts.map +1 -0
- package/dist/metadata/identity.js +147 -0
- package/dist/metadata/identity.js.map +1 -0
- package/dist/metadata/metric-match.d.ts +93 -0
- package/dist/metadata/metric-match.d.ts.map +1 -0
- package/dist/metadata/metric-match.js +233 -0
- package/dist/metadata/metric-match.js.map +1 -0
- package/dist/metadata/sql-grounding.d.ts +149 -0
- package/dist/metadata/sql-grounding.d.ts.map +1 -0
- package/dist/metadata/sql-grounding.js +397 -0
- package/dist/metadata/sql-grounding.js.map +1 -0
- package/dist/metadata/sql-retrieval.d.ts +29 -0
- package/dist/metadata/sql-retrieval.d.ts.map +1 -0
- package/dist/metadata/sql-retrieval.js +79 -0
- package/dist/metadata/sql-retrieval.js.map +1 -0
- package/dist/narrate.d.ts +52 -0
- package/dist/narrate.d.ts.map +1 -0
- package/dist/narrate.js +263 -0
- package/dist/narrate.js.map +1 -0
- package/dist/propose/build-from-prompt.d.ts +160 -0
- package/dist/propose/build-from-prompt.d.ts.map +1 -0
- package/dist/propose/build-from-prompt.js +815 -0
- package/dist/propose/build-from-prompt.js.map +1 -0
- package/dist/propose/classify.d.ts +55 -0
- package/dist/propose/classify.d.ts.map +1 -0
- package/dist/propose/classify.js +167 -0
- package/dist/propose/classify.js.map +1 -0
- package/dist/propose/config.d.ts +39 -0
- package/dist/propose/config.d.ts.map +1 -0
- package/dist/propose/config.js +52 -0
- package/dist/propose/config.js.map +1 -0
- package/dist/propose/dbt-artifacts.d.ts +134 -0
- package/dist/propose/dbt-artifacts.d.ts.map +1 -0
- package/dist/propose/dbt-artifacts.js +320 -0
- package/dist/propose/dbt-artifacts.js.map +1 -0
- package/dist/propose/edit-block.d.ts +74 -0
- package/dist/propose/edit-block.d.ts.map +1 -0
- package/dist/propose/edit-block.js +133 -0
- package/dist/propose/edit-block.js.map +1 -0
- package/dist/propose/enrich.d.ts +48 -0
- package/dist/propose/enrich.d.ts.map +1 -0
- package/dist/propose/enrich.js +125 -0
- package/dist/propose/enrich.js.map +1 -0
- package/dist/propose/generate-sql.d.ts +61 -0
- package/dist/propose/generate-sql.d.ts.map +1 -0
- package/dist/propose/generate-sql.js +180 -0
- package/dist/propose/generate-sql.js.map +1 -0
- package/dist/propose/index.d.ts +24 -0
- package/dist/propose/index.d.ts.map +1 -0
- package/dist/propose/index.js +15 -0
- package/dist/propose/index.js.map +1 -0
- package/dist/propose/propose.d.ts +226 -0
- package/dist/propose/propose.d.ts.map +1 -0
- package/dist/propose/propose.js +668 -0
- package/dist/propose/propose.js.map +1 -0
- package/dist/propose/reflect-block.d.ts +99 -0
- package/dist/propose/reflect-block.d.ts.map +1 -0
- package/dist/propose/reflect-block.js +220 -0
- package/dist/propose/reflect-block.js.map +1 -0
- package/dist/propose/write-draft.d.ts +90 -0
- package/dist/propose/write-draft.d.ts.map +1 -0
- package/dist/propose/write-draft.js +185 -0
- package/dist/propose/write-draft.js.map +1 -0
- package/dist/providers/claude.d.ts +13 -1
- package/dist/providers/claude.d.ts.map +1 -1
- package/dist/providers/claude.js +20 -2
- package/dist/providers/claude.js.map +1 -1
- package/dist/providers/gemini.d.ts +13 -1
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +24 -3
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/index.d.ts +3 -3
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -3
- package/dist/providers/index.js.map +1 -1
- package/dist/research-loop.d.ts +62 -0
- package/dist/research-loop.d.ts.map +1 -0
- package/dist/research-loop.js +210 -0
- package/dist/research-loop.js.map +1 -0
- package/dist/skills/defaults.d.ts +37 -0
- package/dist/skills/defaults.d.ts.map +1 -0
- package/dist/skills/defaults.js +152 -0
- package/dist/skills/defaults.js.map +1 -0
- package/dist/skills/loader.d.ts +60 -0
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +164 -2
- package/dist/skills/loader.js.map +1 -1
- package/package.json +7 -5
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only readers for dbt build artifacts used by `dql propose`.
|
|
3
|
+
*
|
|
4
|
+
* These parse the raw JSON shapes that dbt writes to `target/`:
|
|
5
|
+
* - `manifest.json` — models, sources, depends_on, tags, schema, description
|
|
6
|
+
* - `catalog.json` — column names + types (from the warehouse)
|
|
7
|
+
* - `semantic_manifest.json` (or manifest.json semantic nodes) — metrics/dimensions
|
|
8
|
+
* - `run_results.json` — per-node execution records (used for run-frequency ranking)
|
|
9
|
+
*
|
|
10
|
+
* We deliberately do NOT reuse the manifest builder's `importDbtManifest`: that
|
|
11
|
+
* function is private and tightly coupled to a full DQL project scan (it walks
|
|
12
|
+
* the DQL-referenced anchor set). `dql propose` runs *before* a DQL layer
|
|
13
|
+
* exists, so it reads the dbt artifacts directly. The field shapes mirror those
|
|
14
|
+
* the builder consumes, so the two stay aligned.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
/**
|
|
19
|
+
* Build the fully-qualified warehouse relation for a node from its
|
|
20
|
+
* `database` / `schema` / relation-name fields. Returns the most-qualified
|
|
21
|
+
* dotted form available (`db.schema.name` → `schema.name` → `name`) so a
|
|
22
|
+
* `FROM` clause always references the REAL relation, never a bare model name.
|
|
23
|
+
*/
|
|
24
|
+
export function buildQualifiedRelation(parts) {
|
|
25
|
+
return [parts.database, parts.schema, parts.name]
|
|
26
|
+
.map((part) => (typeof part === 'string' ? part.trim() : ''))
|
|
27
|
+
.filter((part) => part.length > 0)
|
|
28
|
+
.join('.');
|
|
29
|
+
}
|
|
30
|
+
function asRecord(value) {
|
|
31
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
32
|
+
return {};
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
function firstString(...values) {
|
|
36
|
+
for (const value of values) {
|
|
37
|
+
if (typeof value === 'string' && value.trim())
|
|
38
|
+
return value.trim();
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
function readJson(path) {
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Derive the `models/<folder>/...` segment from a node path, e.g. `marts`. */
|
|
51
|
+
function folderFromPath(path) {
|
|
52
|
+
if (!path)
|
|
53
|
+
return undefined;
|
|
54
|
+
const normalized = path.replace(/\\/g, '/');
|
|
55
|
+
const match = normalized.match(/(?:^|\/)models\/([^/]+)\//);
|
|
56
|
+
if (match)
|
|
57
|
+
return match[1];
|
|
58
|
+
// No `models/` prefix (e.g. already relative) — take the leading segment.
|
|
59
|
+
const parts = normalized.split('/').filter(Boolean);
|
|
60
|
+
return parts.length > 1 ? parts[0] : undefined;
|
|
61
|
+
}
|
|
62
|
+
/** Best-effort domain label from a dbt model node. */
|
|
63
|
+
function domainFromNode(node, folder) {
|
|
64
|
+
const meta = asRecord(node.meta);
|
|
65
|
+
const config = asRecord(node.config);
|
|
66
|
+
const configMeta = asRecord(config.meta);
|
|
67
|
+
const fqn = Array.isArray(node.fqn) ? node.fqn : [];
|
|
68
|
+
return firstString(meta.domain, meta.group, configMeta.domain, configMeta.group, config.group, folder && folder !== 'marts' && folder !== 'staging' && folder !== 'intermediate' ? folder : undefined, fqn.length > 1 ? fqn[1] : undefined);
|
|
69
|
+
}
|
|
70
|
+
function readColumns(node) {
|
|
71
|
+
const columns = asRecord(node.columns);
|
|
72
|
+
const out = [];
|
|
73
|
+
for (const [key, raw] of Object.entries(columns)) {
|
|
74
|
+
const col = asRecord(raw);
|
|
75
|
+
const name = firstString(col.name, key);
|
|
76
|
+
if (!name)
|
|
77
|
+
continue;
|
|
78
|
+
out.push({
|
|
79
|
+
name,
|
|
80
|
+
type: firstString(col.data_type),
|
|
81
|
+
description: firstString(col.description),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Load all dbt artifacts that live alongside `manifest.json` (same `target/`
|
|
88
|
+
* directory). Only `manifest.json` is required; the rest are optional and the
|
|
89
|
+
* loader degrades gracefully when they are missing.
|
|
90
|
+
*/
|
|
91
|
+
export function loadDbtArtifacts(manifestPath) {
|
|
92
|
+
const manifest = readJson(manifestPath);
|
|
93
|
+
if (!manifest) {
|
|
94
|
+
throw new Error(`Could not read or parse dbt manifest at ${manifestPath}`);
|
|
95
|
+
}
|
|
96
|
+
const targetDir = manifestPath.replace(/[\\/][^\\/]+$/, '');
|
|
97
|
+
const projectName = firstString(asRecord(manifest.metadata).project_name);
|
|
98
|
+
const models = [];
|
|
99
|
+
const sources = [];
|
|
100
|
+
const exposures = [];
|
|
101
|
+
for (const [uniqueId, raw] of Object.entries(asRecord(manifest.nodes))) {
|
|
102
|
+
const node = asRecord(raw);
|
|
103
|
+
if (node.resource_type !== 'model')
|
|
104
|
+
continue;
|
|
105
|
+
// `name` is the logical model name (used by `{{ ref() }}`); `alias` is the
|
|
106
|
+
// warehouse relation name. They are usually equal, but when an `alias` is
|
|
107
|
+
// declared the qualified relation must use it, not the model name.
|
|
108
|
+
const modelName = firstString(node.name);
|
|
109
|
+
const alias = firstString(node.alias);
|
|
110
|
+
const name = alias ?? modelName;
|
|
111
|
+
if (!name)
|
|
112
|
+
continue;
|
|
113
|
+
const refName = modelName ?? name;
|
|
114
|
+
const schema = firstString(node.schema);
|
|
115
|
+
const database = firstString(node.database);
|
|
116
|
+
const path = firstString(node.original_file_path, node.path);
|
|
117
|
+
const folder = folderFromPath(path);
|
|
118
|
+
const dependsOn = Array.isArray(asRecord(node.depends_on).nodes)
|
|
119
|
+
? asRecord(node.depends_on).nodes.filter((n) => typeof n === 'string')
|
|
120
|
+
: [];
|
|
121
|
+
models.push({
|
|
122
|
+
uniqueId,
|
|
123
|
+
name,
|
|
124
|
+
resourceType: 'model',
|
|
125
|
+
schema,
|
|
126
|
+
database,
|
|
127
|
+
alias: alias && alias !== modelName ? alias : undefined,
|
|
128
|
+
qualifiedRelation: buildQualifiedRelation({ database, schema, name }),
|
|
129
|
+
refForm: `{{ ref('${refName}') }}`,
|
|
130
|
+
description: firstString(node.description),
|
|
131
|
+
materialized: firstString(asRecord(node.config).materialized),
|
|
132
|
+
tags: Array.isArray(node.tags) ? node.tags.map(String) : [],
|
|
133
|
+
folder,
|
|
134
|
+
domainHint: domainFromNode(node, folder),
|
|
135
|
+
dependsOn,
|
|
136
|
+
columns: readColumns(node),
|
|
137
|
+
meta: asRecord(node.meta),
|
|
138
|
+
config: asRecord(node.config),
|
|
139
|
+
path,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
for (const [uniqueId, raw] of Object.entries(asRecord(manifest.sources))) {
|
|
143
|
+
const node = asRecord(raw);
|
|
144
|
+
const identifier = firstString(node.identifier, node.name);
|
|
145
|
+
if (!identifier)
|
|
146
|
+
continue;
|
|
147
|
+
const schema = firstString(node.schema);
|
|
148
|
+
const database = firstString(node.database);
|
|
149
|
+
const sourceName = firstString(node.source_name);
|
|
150
|
+
sources.push({
|
|
151
|
+
uniqueId,
|
|
152
|
+
name: identifier,
|
|
153
|
+
resourceType: 'source',
|
|
154
|
+
schema,
|
|
155
|
+
database,
|
|
156
|
+
qualifiedRelation: buildQualifiedRelation({ database, schema, name: identifier }),
|
|
157
|
+
refForm: sourceName ? `{{ source('${sourceName}', '${firstString(node.name) ?? identifier}') }}` : undefined,
|
|
158
|
+
description: firstString(node.description),
|
|
159
|
+
tags: Array.isArray(node.tags) ? node.tags.map(String) : [],
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
for (const [uniqueId, raw] of Object.entries(asRecord(manifest.exposures))) {
|
|
163
|
+
const node = asRecord(raw);
|
|
164
|
+
const dependsOn = Array.isArray(asRecord(node.depends_on).nodes)
|
|
165
|
+
? asRecord(node.depends_on).nodes.filter((n) => typeof n === 'string')
|
|
166
|
+
: [];
|
|
167
|
+
exposures.push({
|
|
168
|
+
uniqueId,
|
|
169
|
+
name: firstString(node.name) ?? uniqueId,
|
|
170
|
+
dependsOn,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
projectName,
|
|
175
|
+
models,
|
|
176
|
+
sources,
|
|
177
|
+
exposures,
|
|
178
|
+
catalogColumns: loadCatalog(join(targetDir, 'catalog.json')),
|
|
179
|
+
runCounts: loadRunResults(join(targetDir, 'run_results.json')),
|
|
180
|
+
...loadSemantic(manifest, join(targetDir, 'semantic_manifest.json')),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/** catalog.json carries warehouse-resolved column types keyed by node uniqueId. */
|
|
184
|
+
function loadCatalog(catalogPath) {
|
|
185
|
+
const out = new Map();
|
|
186
|
+
if (!existsSync(catalogPath))
|
|
187
|
+
return out;
|
|
188
|
+
const catalog = readJson(catalogPath);
|
|
189
|
+
if (!catalog)
|
|
190
|
+
return out;
|
|
191
|
+
for (const [uniqueId, raw] of Object.entries(asRecord(catalog.nodes))) {
|
|
192
|
+
const node = asRecord(raw);
|
|
193
|
+
const columns = asRecord(node.columns);
|
|
194
|
+
const cols = [];
|
|
195
|
+
for (const [key, colRaw] of Object.entries(columns)) {
|
|
196
|
+
const col = asRecord(colRaw);
|
|
197
|
+
const name = firstString(col.name, key);
|
|
198
|
+
if (!name)
|
|
199
|
+
continue;
|
|
200
|
+
cols.push({ name, type: firstString(col.type), description: firstString(col.comment) });
|
|
201
|
+
}
|
|
202
|
+
if (cols.length > 0)
|
|
203
|
+
out.set(uniqueId, cols);
|
|
204
|
+
}
|
|
205
|
+
return out;
|
|
206
|
+
}
|
|
207
|
+
/** run_results.json lists one result per executed node; count occurrences. */
|
|
208
|
+
function loadRunResults(runResultsPath) {
|
|
209
|
+
const out = new Map();
|
|
210
|
+
if (!existsSync(runResultsPath))
|
|
211
|
+
return out;
|
|
212
|
+
const runResults = readJson(runResultsPath);
|
|
213
|
+
if (!runResults)
|
|
214
|
+
return out;
|
|
215
|
+
const results = Array.isArray(runResults.results) ? runResults.results : [];
|
|
216
|
+
for (const raw of results) {
|
|
217
|
+
const result = asRecord(raw);
|
|
218
|
+
const uniqueId = firstString(result.unique_id);
|
|
219
|
+
if (!uniqueId)
|
|
220
|
+
continue;
|
|
221
|
+
out.set(uniqueId, (out.get(uniqueId) ?? 0) + 1);
|
|
222
|
+
}
|
|
223
|
+
return out;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Load semantic metric references, preferring `semantic_manifest.json` and
|
|
227
|
+
* falling back to semantic nodes embedded in `manifest.json`. Returns a flag so
|
|
228
|
+
* the caller can decide whether to attempt metric-wrapper drafts.
|
|
229
|
+
*/
|
|
230
|
+
function loadSemantic(manifest, semanticManifestPath) {
|
|
231
|
+
let source = null;
|
|
232
|
+
if (existsSync(semanticManifestPath)) {
|
|
233
|
+
source = readJson(semanticManifestPath);
|
|
234
|
+
}
|
|
235
|
+
// `semantic_manifest.json` carries metrics/semantic_models as ARRAYS, while
|
|
236
|
+
// the inline `manifest.json` carries them as keyed RECORDS — normalize both to
|
|
237
|
+
// a flat list of nodes so the loader works on either source.
|
|
238
|
+
const metricsList = collectionValues(source?.metrics ?? manifest.metrics);
|
|
239
|
+
const semanticModelsList = collectionValues(source?.semantic_models ?? manifest.semantic_models);
|
|
240
|
+
// measure name -> model name, so a metric referencing a measure can resolve a
|
|
241
|
+
// model. A semantic model's underlying dbt model is the alias in its
|
|
242
|
+
// `node_relation` (MetricFlow shape), else its `name`. Also collect the
|
|
243
|
+
// measure's agg + expr so a metric can build real aggregation SQL.
|
|
244
|
+
const measureToModel = new Map();
|
|
245
|
+
const measureMeta = new Map();
|
|
246
|
+
const semanticModels = new Map();
|
|
247
|
+
for (const raw of semanticModelsList) {
|
|
248
|
+
const semanticModel = asRecord(raw);
|
|
249
|
+
const modelName = firstString(asRecord(semanticModel.node_relation).alias, semanticModel.name);
|
|
250
|
+
if (!modelName)
|
|
251
|
+
continue;
|
|
252
|
+
const entities = (Array.isArray(semanticModel.entities) ? semanticModel.entities : [])
|
|
253
|
+
.map((e) => asRecord(e));
|
|
254
|
+
const entityNames = entities
|
|
255
|
+
.map((e) => firstString(e.expr, e.name))
|
|
256
|
+
.filter((v) => Boolean(v));
|
|
257
|
+
const primaryEntity = firstString(...entities.filter((e) => e.type === 'primary').map((e) => firstString(e.expr, e.name) ?? ''));
|
|
258
|
+
const dimensions = (Array.isArray(semanticModel.dimensions) ? semanticModel.dimensions : [])
|
|
259
|
+
.map((d) => asRecord(d));
|
|
260
|
+
const dimensionNames = dimensions
|
|
261
|
+
.map((d) => firstString(d.name))
|
|
262
|
+
.filter((v) => Boolean(v));
|
|
263
|
+
const timeDimensions = dimensions
|
|
264
|
+
.filter((d) => d.type === 'time')
|
|
265
|
+
.map((d) => firstString(d.name))
|
|
266
|
+
.filter((v) => Boolean(v));
|
|
267
|
+
semanticModels.set(modelName, {
|
|
268
|
+
model: modelName,
|
|
269
|
+
dimensions: dimensionNames,
|
|
270
|
+
primaryEntity: primaryEntity || undefined,
|
|
271
|
+
entities: entityNames,
|
|
272
|
+
timeDimensions,
|
|
273
|
+
});
|
|
274
|
+
for (const measureRaw of Array.isArray(semanticModel.measures) ? semanticModel.measures : []) {
|
|
275
|
+
const measure = asRecord(measureRaw);
|
|
276
|
+
const measureName = firstString(measure.name);
|
|
277
|
+
if (!measureName)
|
|
278
|
+
continue;
|
|
279
|
+
measureToModel.set(measureName, modelName);
|
|
280
|
+
measureMeta.set(measureName, {
|
|
281
|
+
agg: firstString(measure.agg),
|
|
282
|
+
expr: firstString(measure.expr),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const semanticMetrics = [];
|
|
287
|
+
for (const raw of metricsList) {
|
|
288
|
+
const metric = asRecord(raw);
|
|
289
|
+
const name = firstString(metric.name);
|
|
290
|
+
if (!name)
|
|
291
|
+
continue;
|
|
292
|
+
const typeParams = asRecord(metric.type_params);
|
|
293
|
+
// `type_params.measure` is sometimes a string, sometimes an object { name }.
|
|
294
|
+
const measure = firstString(typeParams.measure, asRecord(typeParams.measure).name);
|
|
295
|
+
const meta = measure ? measureMeta.get(measure) : undefined;
|
|
296
|
+
semanticMetrics.push({
|
|
297
|
+
name,
|
|
298
|
+
description: firstString(metric.description),
|
|
299
|
+
model: measure ? measureToModel.get(measure) : undefined,
|
|
300
|
+
measure,
|
|
301
|
+
agg: meta?.agg,
|
|
302
|
+
expr: meta?.expr,
|
|
303
|
+
metricType: firstString(metric.type),
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
hasSemantic: semanticMetrics.length > 0 || semanticModelsList.length > 0,
|
|
308
|
+
semanticMetrics,
|
|
309
|
+
semanticModels,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
/** Flatten a metrics/semantic_models collection that may be an array OR a record. */
|
|
313
|
+
function collectionValues(value) {
|
|
314
|
+
if (Array.isArray(value))
|
|
315
|
+
return value;
|
|
316
|
+
if (value && typeof value === 'object')
|
|
317
|
+
return Object.values(value);
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=dbt-artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dbt-artifacts.js","sourceRoot":"","sources":["../../src/propose/dbt-artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edit-an-existing-block (spec 17, part A).
|
|
3
|
+
*
|
|
4
|
+
* The create path always writes a NEW deduped draft. Users also need to MODIFY
|
|
5
|
+
* one specific block — add a missed table/column, change the grain — and have it
|
|
6
|
+
* update the SAME file. `editBlock` loads the block at `blockPath`, asks the
|
|
7
|
+
* model for the UPDATED block applying the user's change, re-grounds/validates
|
|
8
|
+
* the SQL via spec-15, and writes the result BACK to the same path. It NEVER
|
|
9
|
+
* forks a new draft.
|
|
10
|
+
*
|
|
11
|
+
* Locked principle (AI drafts, humans certify): the block's status is preserved.
|
|
12
|
+
* A draft stays `draft`; an already-certified block stays `certified` (the human
|
|
13
|
+
* must re-certify after an edit). We never silently downgrade or auto-certify.
|
|
14
|
+
*/
|
|
15
|
+
/** Block metadata + SQL loaded from an existing `.dql` file. */
|
|
16
|
+
export interface LoadedBlock {
|
|
17
|
+
/** Absolute path on disk. */
|
|
18
|
+
absPath: string;
|
|
19
|
+
/** Path exactly as supplied by the caller (project-relative or absolute). */
|
|
20
|
+
requestedPath: string;
|
|
21
|
+
name: string;
|
|
22
|
+
blockType: 'semantic' | 'custom';
|
|
23
|
+
domain?: string;
|
|
24
|
+
owner?: string;
|
|
25
|
+
status?: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
grain?: string;
|
|
28
|
+
pattern?: string;
|
|
29
|
+
entities?: string[];
|
|
30
|
+
outputs?: string[];
|
|
31
|
+
tags?: string[];
|
|
32
|
+
llmContext?: string;
|
|
33
|
+
invariants?: string[];
|
|
34
|
+
sourceSystems?: string[];
|
|
35
|
+
/** The block's current SQL body (raw, with `{{ ref() }}` intact). */
|
|
36
|
+
sql: string;
|
|
37
|
+
/** The full original file text (so non-modeled content can be preserved). */
|
|
38
|
+
rawFile: string;
|
|
39
|
+
}
|
|
40
|
+
/** Parse the existing block file into its SQL + governance metadata. */
|
|
41
|
+
export declare function loadBlockForEdit(projectRoot: string, blockPath: string): LoadedBlock;
|
|
42
|
+
/**
|
|
43
|
+
* The status the edited block should carry (spec 17, part A locked principle).
|
|
44
|
+
* Certified stays certified (human must re-certify); everything else stays as-is
|
|
45
|
+
* or defaults to `draft`. We never auto-certify and never downgrade.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveEditedStatus(original?: string): string;
|
|
48
|
+
export interface EditedBlockFields {
|
|
49
|
+
name: string;
|
|
50
|
+
blockType: 'semantic' | 'custom';
|
|
51
|
+
status: string;
|
|
52
|
+
domain?: string;
|
|
53
|
+
owner?: string;
|
|
54
|
+
description?: string;
|
|
55
|
+
grain?: string;
|
|
56
|
+
pattern?: string;
|
|
57
|
+
entities?: string[];
|
|
58
|
+
outputs?: string[];
|
|
59
|
+
tags?: string[];
|
|
60
|
+
llmContext?: string;
|
|
61
|
+
invariants?: string[];
|
|
62
|
+
sourceSystems?: string[];
|
|
63
|
+
sql: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Render the edited block back to canonical DQL text. Preserves name, owner,
|
|
67
|
+
* domain, grain, and status; updates the SQL + any modeled metadata. A small
|
|
68
|
+
* header notes the in-place edit (no review verdict is asserted — the human
|
|
69
|
+
* re-certifies).
|
|
70
|
+
*/
|
|
71
|
+
export declare function renderEditedBlock(fields: EditedBlockFields): string;
|
|
72
|
+
/** Write the edited block back to its original path. Returns the path written. */
|
|
73
|
+
export declare function writeEditedBlock(absPath: string, content: string): string;
|
|
74
|
+
//# sourceMappingURL=edit-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-block.d.ts","sourceRoot":"","sources":["../../src/propose/edit-block.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,UAAU,GAAG,QAAQ,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,CAuCpF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,UAAU,GAAG,QAAQ,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;CACb;AAmBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAiCnE;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGzE"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edit-an-existing-block (spec 17, part A).
|
|
3
|
+
*
|
|
4
|
+
* The create path always writes a NEW deduped draft. Users also need to MODIFY
|
|
5
|
+
* one specific block — add a missed table/column, change the grain — and have it
|
|
6
|
+
* update the SAME file. `editBlock` loads the block at `blockPath`, asks the
|
|
7
|
+
* model for the UPDATED block applying the user's change, re-grounds/validates
|
|
8
|
+
* the SQL via spec-15, and writes the result BACK to the same path. It NEVER
|
|
9
|
+
* forks a new draft.
|
|
10
|
+
*
|
|
11
|
+
* Locked principle (AI drafts, humans certify): the block's status is preserved.
|
|
12
|
+
* A draft stays `draft`; an already-certified block stays `certified` (the human
|
|
13
|
+
* must re-certify after an edit). We never silently downgrade or auto-certify.
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
+
import { isAbsolute, join } from 'node:path';
|
|
17
|
+
import { Parser } from '@duckcodeailabs/dql-core';
|
|
18
|
+
function resolveAbs(projectRoot, blockPath) {
|
|
19
|
+
return isAbsolute(blockPath) ? blockPath : join(projectRoot, blockPath);
|
|
20
|
+
}
|
|
21
|
+
/** Parse the existing block file into its SQL + governance metadata. */
|
|
22
|
+
export function loadBlockForEdit(projectRoot, blockPath) {
|
|
23
|
+
const absPath = resolveAbs(projectRoot, blockPath);
|
|
24
|
+
if (!existsSync(absPath)) {
|
|
25
|
+
throw new Error(`Block file not found for edit: ${blockPath}`);
|
|
26
|
+
}
|
|
27
|
+
const rawFile = readFileSync(absPath, 'utf-8');
|
|
28
|
+
const ast = new Parser(rawFile, blockPath).parse();
|
|
29
|
+
const block = ast.statements.find((stmt) => stmt.kind === 'BlockDecl');
|
|
30
|
+
if (!block) {
|
|
31
|
+
throw new Error(`No block declaration found in ${blockPath}`);
|
|
32
|
+
}
|
|
33
|
+
const asStr = (v) => typeof v === 'string' && v.trim() ? v.trim() : undefined;
|
|
34
|
+
const asArr = (v) => Array.isArray(v) ? v.filter((x) => typeof x === 'string') : undefined;
|
|
35
|
+
const query = block.query;
|
|
36
|
+
return {
|
|
37
|
+
absPath,
|
|
38
|
+
requestedPath: blockPath,
|
|
39
|
+
name: asStr(block.name) ?? 'block',
|
|
40
|
+
blockType: block.blockType === 'semantic' ? 'semantic' : 'custom',
|
|
41
|
+
domain: asStr(block.domain),
|
|
42
|
+
owner: asStr(block.owner),
|
|
43
|
+
status: asStr(block.status),
|
|
44
|
+
description: asStr(block.description),
|
|
45
|
+
grain: asStr(block.grain),
|
|
46
|
+
pattern: asStr(block.pattern),
|
|
47
|
+
entities: asArr(block.entities),
|
|
48
|
+
outputs: asArr(block.outputs),
|
|
49
|
+
tags: asArr(block.tags),
|
|
50
|
+
llmContext: asStr(block.llmContext),
|
|
51
|
+
invariants: asArr(block.invariants),
|
|
52
|
+
sourceSystems: asArr(block.sourceSystems),
|
|
53
|
+
sql: (query?.rawSQL ?? '').trim(),
|
|
54
|
+
rawFile,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The status the edited block should carry (spec 17, part A locked principle).
|
|
59
|
+
* Certified stays certified (human must re-certify); everything else stays as-is
|
|
60
|
+
* or defaults to `draft`. We never auto-certify and never downgrade.
|
|
61
|
+
*/
|
|
62
|
+
export function resolveEditedStatus(original) {
|
|
63
|
+
const status = (original ?? '').trim().toLowerCase();
|
|
64
|
+
if (status === 'certified')
|
|
65
|
+
return 'certified';
|
|
66
|
+
if (status)
|
|
67
|
+
return status;
|
|
68
|
+
return 'draft';
|
|
69
|
+
}
|
|
70
|
+
function escapeString(value) {
|
|
71
|
+
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
72
|
+
}
|
|
73
|
+
function stringArrayLine(name, values) {
|
|
74
|
+
if (!values || values.length === 0)
|
|
75
|
+
return '';
|
|
76
|
+
return `\n ${name} = [${values.map((v) => `"${escapeString(v)}"`).join(', ')}]`;
|
|
77
|
+
}
|
|
78
|
+
function indent(text, spaces) {
|
|
79
|
+
const pad = ' '.repeat(spaces);
|
|
80
|
+
return text
|
|
81
|
+
.split('\n')
|
|
82
|
+
.map((line) => (line.length > 0 ? pad + line : line))
|
|
83
|
+
.join('\n');
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Render the edited block back to canonical DQL text. Preserves name, owner,
|
|
87
|
+
* domain, grain, and status; updates the SQL + any modeled metadata. A small
|
|
88
|
+
* header notes the in-place edit (no review verdict is asserted — the human
|
|
89
|
+
* re-certifies).
|
|
90
|
+
*/
|
|
91
|
+
export function renderEditedBlock(fields) {
|
|
92
|
+
const lines = [`block "${escapeString(fields.name)}" {`];
|
|
93
|
+
lines.push(` type = "${fields.blockType}"`);
|
|
94
|
+
if (fields.domain)
|
|
95
|
+
lines.push(` domain = "${escapeString(fields.domain)}"`);
|
|
96
|
+
lines.push(` status = "${escapeString(fields.status)}"`);
|
|
97
|
+
if (fields.description)
|
|
98
|
+
lines.push(` description = "${escapeString(fields.description)}"`);
|
|
99
|
+
if (fields.owner)
|
|
100
|
+
lines.push(` owner = "${escapeString(fields.owner)}"`);
|
|
101
|
+
if (fields.pattern)
|
|
102
|
+
lines.push(` pattern = "${escapeString(fields.pattern)}"`);
|
|
103
|
+
if (fields.grain)
|
|
104
|
+
lines.push(` grain = "${escapeString(fields.grain)}"`);
|
|
105
|
+
const arrays = [
|
|
106
|
+
stringArrayLine('entities', fields.entities),
|
|
107
|
+
stringArrayLine('outputs', fields.outputs),
|
|
108
|
+
stringArrayLine('sourceSystems', fields.sourceSystems),
|
|
109
|
+
stringArrayLine('tags', fields.tags),
|
|
110
|
+
stringArrayLine('invariants', fields.invariants),
|
|
111
|
+
].join('');
|
|
112
|
+
if (fields.llmContext)
|
|
113
|
+
lines.push(` llmContext = "${escapeString(fields.llmContext)}"`);
|
|
114
|
+
const body = [
|
|
115
|
+
'// dql-format: 1',
|
|
116
|
+
`// Updated in place by AI build (edit mode). status preserved as "${fields.status}".`,
|
|
117
|
+
`// AI drafts, humans certify — review the change${fields.status === 'certified' ? ', then re-certify this block.' : '.'}`,
|
|
118
|
+
lines.join('\n') + arrays,
|
|
119
|
+
'',
|
|
120
|
+
' query = """',
|
|
121
|
+
indent(fields.sql, 4),
|
|
122
|
+
' """',
|
|
123
|
+
'}',
|
|
124
|
+
'',
|
|
125
|
+
];
|
|
126
|
+
return body.join('\n');
|
|
127
|
+
}
|
|
128
|
+
/** Write the edited block back to its original path. Returns the path written. */
|
|
129
|
+
export function writeEditedBlock(absPath, content) {
|
|
130
|
+
writeFileSync(absPath, content, 'utf-8');
|
|
131
|
+
return absPath;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=edit-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-block.js","sourceRoot":"","sources":["../../src/propose/edit-block.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional AI enrichment for proposed draft blocks.
|
|
3
|
+
*
|
|
4
|
+
* Principle (spec 13): **structure deterministic, content AI-optional.** The
|
|
5
|
+
* propose engine (`propose.ts`) is fully deterministic — classification, grain,
|
|
6
|
+
* outputs, SQL, ranking, selection. This module is the *only* place an LLM is
|
|
7
|
+
* used, and only to improve human-facing *content* — `description`, `llmContext`,
|
|
8
|
+
* and example questions — for the bounded set the human approved.
|
|
9
|
+
*
|
|
10
|
+
* It is best-effort and isolated: every call has a timeout, any failure (no
|
|
11
|
+
* provider, network, bad JSON, timeout) returns `null` and the caller keeps the
|
|
12
|
+
* deterministic dbt-derived content. The engine consumes the result as plain
|
|
13
|
+
* data (`ProposeOptions.enrichedBySlug`); it never calls a provider itself.
|
|
14
|
+
*/
|
|
15
|
+
import type { AgentProvider } from '../providers/types.js';
|
|
16
|
+
export interface EnrichFacts {
|
|
17
|
+
slug: string;
|
|
18
|
+
model: string;
|
|
19
|
+
domain: string;
|
|
20
|
+
/** dbt model description, when present. */
|
|
21
|
+
description?: string;
|
|
22
|
+
grain?: string;
|
|
23
|
+
pattern: string;
|
|
24
|
+
/** Output column names. */
|
|
25
|
+
columns: string[];
|
|
26
|
+
entities: string[];
|
|
27
|
+
/** Semantic metric the model backs, when any. */
|
|
28
|
+
metric?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface EnrichedContent {
|
|
31
|
+
description?: string;
|
|
32
|
+
llmContext?: string;
|
|
33
|
+
examples?: string[];
|
|
34
|
+
}
|
|
35
|
+
export interface EnrichOptions {
|
|
36
|
+
/** Per-call timeout in ms (default 25s — local models are slow). */
|
|
37
|
+
timeoutMs?: number;
|
|
38
|
+
/** Max concurrent provider calls (default 4). */
|
|
39
|
+
concurrency?: number;
|
|
40
|
+
}
|
|
41
|
+
/** Enrich a single proposal. Best-effort: returns null on any failure/timeout. */
|
|
42
|
+
export declare function enrichProposal(facts: EnrichFacts, provider: AgentProvider, options?: EnrichOptions): Promise<EnrichedContent | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Enrich many proposals with bounded concurrency. Always resolves (best-effort);
|
|
45
|
+
* proposals that fail simply stay deterministic. Keyed by slug.
|
|
46
|
+
*/
|
|
47
|
+
export declare function enrichProposals(items: EnrichFacts[], provider: AgentProvider, options?: EnrichOptions): Promise<Map<string, EnrichedContent>>;
|
|
48
|
+
//# sourceMappingURL=enrich.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrich.d.ts","sourceRoot":"","sources":["../../src/propose/enrich.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2ED,kFAAkF;AAClF,wBAAsB,cAAc,CAClC,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAcjC;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,WAAW,EAAE,EACpB,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAavC"}
|