@duckcodeailabs/dql-mcp 1.5.2 → 1.6.0
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/context.d.ts +17 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +21 -1
- package/dist/context.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +34 -6
- package/dist/server.js.map +1 -1
- package/dist/tools/__tests__/_helpers.d.ts +4 -0
- package/dist/tools/__tests__/_helpers.d.ts.map +1 -0
- package/dist/tools/__tests__/_helpers.js +34 -0
- package/dist/tools/__tests__/_helpers.js.map +1 -0
- package/dist/tools/list-proposals.d.ts +37 -0
- package/dist/tools/list-proposals.d.ts.map +1 -0
- package/dist/tools/list-proposals.js +101 -0
- package/dist/tools/list-proposals.js.map +1 -0
- package/dist/tools/query-via-block.d.ts.map +1 -1
- package/dist/tools/query-via-block.js +15 -0
- package/dist/tools/query-via-block.js.map +1 -1
- package/dist/tools/query-via-metadata.d.ts +101 -0
- package/dist/tools/query-via-metadata.d.ts.map +1 -0
- package/dist/tools/query-via-metadata.js +246 -0
- package/dist/tools/query-via-metadata.js.map +1 -0
- package/package.json +6 -6
package/dist/context.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { SemanticLayer, LineageGraph, type DQLManifest } from '@duckcodeailabs/dql-core';
|
|
1
|
+
import { DataLexContractRegistry, SemanticLayer, LineageGraph, type DQLManifest } from '@duckcodeailabs/dql-core';
|
|
2
2
|
export interface DQLContextOptions {
|
|
3
3
|
projectRoot: string;
|
|
4
4
|
dqlVersion?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Optional override for the DataLex manifest path. Defaults to
|
|
7
|
+
* `<projectRoot>/datalex-manifest.json`. The registry is consulted by
|
|
8
|
+
* tools that enforce datalex_contract bindings (e.g. query-via-block).
|
|
9
|
+
*/
|
|
10
|
+
datalexManifestPath?: string;
|
|
5
11
|
}
|
|
6
12
|
/**
|
|
7
13
|
* Shared read-only view over a DQL project.
|
|
@@ -12,13 +18,23 @@ export interface DQLContextOptions {
|
|
|
12
18
|
export declare class DQLContext {
|
|
13
19
|
readonly projectRoot: string;
|
|
14
20
|
private readonly dqlVersion;
|
|
21
|
+
private readonly datalexManifestPath;
|
|
15
22
|
private _manifest;
|
|
16
23
|
private _semanticLayer;
|
|
17
24
|
private _lineage;
|
|
25
|
+
private _datalexRegistry;
|
|
18
26
|
constructor(options: DQLContextOptions);
|
|
19
27
|
get manifest(): DQLManifest;
|
|
20
28
|
get semanticLayer(): SemanticLayer;
|
|
21
29
|
get lineageGraph(): LineageGraph;
|
|
30
|
+
/**
|
|
31
|
+
* Lazily-loaded registry of DataLex contracts for enforcing
|
|
32
|
+
* `datalex_contract` references on certified blocks. Tools call
|
|
33
|
+
* `registry.isLoaded()` to check whether a manifest was found before
|
|
34
|
+
* gating on resolution; that lets MCP work in projects that haven't
|
|
35
|
+
* adopted DataLex yet.
|
|
36
|
+
*/
|
|
37
|
+
get datalexRegistry(): DataLexContractRegistry;
|
|
22
38
|
refresh(): void;
|
|
23
39
|
}
|
|
24
40
|
/** Walk up from `startDir` until a `dql.config.json` is found, else return `startDir`. */
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,uBAAuB,EAGvB,aAAa,EAEb,YAAY,EACZ,KAAK,WAAW,EAIjB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,gBAAgB,CAAwC;gBAEpD,OAAO,EAAE,iBAAiB;IAOtC,IAAI,QAAQ,IAAI,WAAW,CAG1B;IAED,IAAI,aAAa,IAAI,aAAa,CAGjC;IAED,IAAI,YAAY,IAAI,YAAY,CAG/B;IAED;;;;;;OAMG;IACH,IAAI,eAAe,IAAI,uBAAuB,CAO7C;IAED,OAAO,IAAI,IAAI;CA6BhB;AA6BD,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQxD"}
|
package/dist/context.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { dirname, join, resolve } from 'node:path';
|
|
3
|
-
import { buildManifest, loadProjectConfig, resolveDbtManifestPath, SemanticLayer, resolveSemanticLayerWithDiagnostics, LineageGraph, } from '@duckcodeailabs/dql-core';
|
|
3
|
+
import { buildManifest, DataLexContractRegistry, loadProjectConfig, resolveDbtManifestPath, SemanticLayer, resolveSemanticLayerWithDiagnostics, LineageGraph, } from '@duckcodeailabs/dql-core';
|
|
4
4
|
/**
|
|
5
5
|
* Shared read-only view over a DQL project.
|
|
6
6
|
*
|
|
@@ -10,12 +10,16 @@ import { buildManifest, loadProjectConfig, resolveDbtManifestPath, SemanticLayer
|
|
|
10
10
|
export class DQLContext {
|
|
11
11
|
projectRoot;
|
|
12
12
|
dqlVersion;
|
|
13
|
+
datalexManifestPath;
|
|
13
14
|
_manifest = null;
|
|
14
15
|
_semanticLayer = null;
|
|
15
16
|
_lineage = null;
|
|
17
|
+
_datalexRegistry = null;
|
|
16
18
|
constructor(options) {
|
|
17
19
|
this.projectRoot = options.projectRoot;
|
|
18
20
|
this.dqlVersion = options.dqlVersion ?? 'mcp';
|
|
21
|
+
this.datalexManifestPath =
|
|
22
|
+
options.datalexManifestPath ?? join(options.projectRoot, 'datalex-manifest.json');
|
|
19
23
|
}
|
|
20
24
|
get manifest() {
|
|
21
25
|
if (!this._manifest)
|
|
@@ -32,6 +36,21 @@ export class DQLContext {
|
|
|
32
36
|
this._lineage = buildGraphFromManifest(this.manifest);
|
|
33
37
|
return this._lineage;
|
|
34
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Lazily-loaded registry of DataLex contracts for enforcing
|
|
41
|
+
* `datalex_contract` references on certified blocks. Tools call
|
|
42
|
+
* `registry.isLoaded()` to check whether a manifest was found before
|
|
43
|
+
* gating on resolution; that lets MCP work in projects that haven't
|
|
44
|
+
* adopted DataLex yet.
|
|
45
|
+
*/
|
|
46
|
+
get datalexRegistry() {
|
|
47
|
+
if (!this._datalexRegistry) {
|
|
48
|
+
this._datalexRegistry = new DataLexContractRegistry({
|
|
49
|
+
manifestPath: this.datalexManifestPath,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return this._datalexRegistry;
|
|
53
|
+
}
|
|
35
54
|
refresh() {
|
|
36
55
|
const dbtManifestPath = resolveDbtManifestPath(this.projectRoot) ?? undefined;
|
|
37
56
|
this._manifest = buildManifest({
|
|
@@ -59,6 +78,7 @@ export class DQLContext {
|
|
|
59
78
|
this._semanticLayer = new SemanticLayer();
|
|
60
79
|
}
|
|
61
80
|
this._lineage = null;
|
|
81
|
+
this._datalexRegistry?.reload();
|
|
62
82
|
}
|
|
63
83
|
}
|
|
64
84
|
function buildGraphFromManifest(manifest) {
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,mCAAmC,EACnC,YAAY,GAKb,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAapE,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,SAAS,CAyG/E"}
|
package/dist/server.js
CHANGED
|
@@ -7,24 +7,52 @@ import { listMetrics, listMetricsInput, listDimensions, listDimensionsInput } fr
|
|
|
7
7
|
import { lineageImpact, lineageImpactInput } from './tools/lineage-impact.js';
|
|
8
8
|
import { certify, certifyInput } from './tools/certify.js';
|
|
9
9
|
import { suggestBlock, suggestBlockInput } from './tools/suggest-block.js';
|
|
10
|
+
import { queryViaMetadata, queryViaMetadataInput } from './tools/query-via-metadata.js';
|
|
11
|
+
import { listProposals, listProposalsInput } from './tools/list-proposals.js';
|
|
10
12
|
import { kgSearch, kgSearchInput, feedbackRecord, feedbackRecordInput } from './tools/kg.js';
|
|
11
13
|
export function createDQLMCPServer(options = {}) {
|
|
12
14
|
const projectRoot = options.projectRoot ?? findProjectRoot(process.cwd());
|
|
13
15
|
const ctx = new DQLContext({ projectRoot, dqlVersion: options.version });
|
|
14
16
|
const server = new McpServer({ name: 'dql-mcp', version: options.version ?? '0.1.0' }, {
|
|
15
|
-
instructions: 'DQL exposes certified, git-versioned analytics blocks
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
17
|
+
instructions: 'DQL exposes certified, git-versioned analytics blocks under graduated trust:\n' +
|
|
18
|
+
' Tier 1 — Always try `query_via_block` first. It only serves blocks that are ' +
|
|
19
|
+
'`status = "certified"` AND have a resolved `datalex_contract`. The answer is ' +
|
|
20
|
+
'safe to ship to dashboards.\n' +
|
|
21
|
+
' Tier 2 — When no certified block matches, call `query_via_metadata` with the ' +
|
|
22
|
+
'SQL you inferred from the manifest + dbt schema. The result is returned with ' +
|
|
23
|
+
'`uncertified: true` — surface that flag to the user verbatim. The proposal is ' +
|
|
24
|
+
'auto-saved as a draft block under blocks/_drafts/ for human certification.\n' +
|
|
25
|
+
' Tier 3 — If the question is unanswerable from the available data, refuse and ' +
|
|
26
|
+
'tell the user why.\n' +
|
|
27
|
+
'Other tools support the loop: `search_blocks` / `get_block` to discover Tier-1 ' +
|
|
28
|
+
'matches, `list_proposals` to see the review queue, `suggest_block` to propose ' +
|
|
29
|
+
'a new block source-of-truth, `certify` to evaluate governance rules, ' +
|
|
30
|
+
'`lineage_impact` to trace upstream/downstream, `list_metrics` / ' +
|
|
31
|
+
'`list_dimensions` for the semantic layer. Never fabricate SQL outside ' +
|
|
32
|
+
'`query_via_metadata` — it captures provenance the human needs to certify.',
|
|
19
33
|
});
|
|
20
34
|
server.registerTool('search_blocks', { description: 'Find certified DQL blocks by keyword, domain, or status.', inputSchema: searchBlocksInput }, async (args) => wrap(await searchBlocks(ctx, args)));
|
|
21
35
|
server.registerTool('get_block', { description: 'Return full metadata, dependencies, and SQL for a block.', inputSchema: getBlockInput }, async (args) => wrap(await getBlock(ctx, args)));
|
|
22
|
-
server.registerTool('query_via_block', {
|
|
36
|
+
server.registerTool('query_via_block', {
|
|
37
|
+
description: 'Tier-1 of graduated trust. Execute a certified block against the local DQL runtime. Refuses non-certified blocks AND certified blocks whose datalex_contract reference is unresolved. Always try this first; fall back to query_via_metadata only when this returns "no block named".',
|
|
38
|
+
inputSchema: queryViaBlockInput,
|
|
39
|
+
}, async (args) => wrap(await queryViaBlock(ctx, args)));
|
|
40
|
+
server.registerTool('query_via_metadata', {
|
|
41
|
+
description: 'Tier-2 of graduated trust. Use ONLY when query_via_block has no matching certified block. Provide the SQL you inferred from the manifest + dbt schema; the runtime executes it and returns the result with `uncertified: true`. The proposal is auto-saved as a draft block under blocks/_drafts/. Surface the `uncertified` flag verbatim and tell the user about the `dql certify --from-draft` command if they want the answer certified for next time.',
|
|
42
|
+
inputSchema: queryViaMetadataInput,
|
|
43
|
+
}, async (args) => wrap(await queryViaMetadata(ctx, args)));
|
|
44
|
+
server.registerTool('list_proposals', {
|
|
45
|
+
description: 'List Tier-2 draft proposals from blocks/_drafts/ ordered by askedTimes DESC. Filter with askedAtLeastTimes / since. Use this to surface "questions that get asked repeatedly are good certify candidates" — the prioritization signal for the human review queue.',
|
|
46
|
+
inputSchema: listProposalsInput,
|
|
47
|
+
}, async (args) => wrap(listProposals(ctx, args)));
|
|
23
48
|
server.registerTool('list_metrics', { description: 'List semantic-layer metrics, optionally filtered by domain.', inputSchema: listMetricsInput }, async (args) => wrap(await listMetrics(ctx, args)));
|
|
24
49
|
server.registerTool('list_dimensions', { description: 'List semantic-layer dimensions, optionally filtered by domain.', inputSchema: listDimensionsInput }, async (args) => wrap(await listDimensions(ctx, args)));
|
|
25
50
|
server.registerTool('lineage_impact', { description: 'Return upstream/downstream lineage for a block, metric, or model.', inputSchema: lineageImpactInput }, async (args) => wrap(await lineageImpact(ctx, args)));
|
|
26
51
|
server.registerTool('certify', { description: 'Run governance rules against a block and report pass/fail.', inputSchema: certifyInput }, async (args) => wrap(await certify(ctx, args)));
|
|
27
|
-
server.registerTool('suggest_block', {
|
|
52
|
+
server.registerTool('suggest_block', {
|
|
53
|
+
description: 'Write a curated proposed block to blocks/_drafts/ with a hand-shaped name + structure, plus the governance gate result. Use when proposing a SHARED building block on top of multiple Tier-2 proposals. For one-shot ad-hoc Tier-2 captures, use `query_via_metadata` instead — it auto-saves the draft.',
|
|
54
|
+
inputSchema: suggestBlockInput,
|
|
55
|
+
}, async (args) => wrap(await suggestBlock(ctx, args)));
|
|
28
56
|
server.registerTool('kg_search', { description: 'Search the agent knowledge graph (FTS5) over blocks, metrics, dimensions, dashboards, apps.', inputSchema: kgSearchInput }, async (args) => wrap(kgSearch(ctx, args)));
|
|
29
57
|
server.registerTool('feedback_record', { description: 'Record thumbs-up/down feedback on an answer; feeds self-learning + promotion suggestions.', inputSchema: feedbackRecordInput }, async (args) => wrap(feedbackRecord(ctx, args)));
|
|
30
58
|
return server;
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAO7F,MAAM,UAAU,kBAAkB,CAAC,UAA+B,EAAE;IAClE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEzE,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO,EAAE,EACxD;QACE,YAAY,EACV,gFAAgF;YAChF
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DQLContext } from '../../context.js';
|
|
2
|
+
export declare function makeManifestBlock(overrides?: Record<string, unknown>): Record<string, unknown>;
|
|
3
|
+
export declare function makeCtx(blocks?: Record<string, unknown>, extra?: Partial<DQLContext>): DQLContext;
|
|
4
|
+
//# sourceMappingURL=_helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_helpers.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,wBAAgB,iBAAiB,CAAC,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAWlE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC7B;AAeD,wBAAgB,OAAO,CAAC,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,KAAK,GAAE,OAAO,CAAC,UAAU,CAAM,GAAG,UAAU,CAOzG"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function makeManifestBlock(overrides = {}) {
|
|
2
|
+
return {
|
|
3
|
+
name: 'My Block',
|
|
4
|
+
status: 'certified',
|
|
5
|
+
type: 'custom',
|
|
6
|
+
domain: 'finance',
|
|
7
|
+
filePath: 'blocks/my-block.dql',
|
|
8
|
+
description: 'Stub block used by tests.',
|
|
9
|
+
owner: 'tests@example.com',
|
|
10
|
+
tags: [],
|
|
11
|
+
...overrides,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Default registry stub: `isLoaded()` returns false so query-via-block's
|
|
16
|
+
* datalex_contract check is skipped, matching the "DataLex not yet adopted"
|
|
17
|
+
* path. Specific tests pass a real registry via `extra.datalexRegistry`.
|
|
18
|
+
*/
|
|
19
|
+
const skipRegistry = {
|
|
20
|
+
isLoaded: () => false,
|
|
21
|
+
resolve: () => ({ ok: false, reason: 'not_found', message: '', requestedRef: '' }),
|
|
22
|
+
list: () => [],
|
|
23
|
+
reload: () => undefined,
|
|
24
|
+
loadDiagnostics: () => [],
|
|
25
|
+
};
|
|
26
|
+
export function makeCtx(blocks = {}, extra = {}) {
|
|
27
|
+
return {
|
|
28
|
+
projectRoot: '/test/project',
|
|
29
|
+
manifest: { blocks },
|
|
30
|
+
datalexRegistry: skipRegistry,
|
|
31
|
+
...extra,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=_helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_helpers.js","sourceRoot":"","sources":["../../../src/tools/__tests__/_helpers.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB,CAAC,YAAqC,EAAE;IACvE,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,WAAW;QACnB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,qBAAqB;QAC/B,WAAW,EAAE,2BAA2B;QACxC,KAAK,EAAE,mBAAmB;QAC1B,IAAI,EAAE,EAAE;QACR,GAAG,SAAS;KACc,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,YAAY,GAAG;IACnB,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;IACrB,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAClF,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE;IACd,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS;IACvB,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE;CAC1B,CAAC;AAEF,MAAM,UAAU,OAAO,CAAC,SAAkC,EAAE,EAAE,QAA6B,EAAE;IAC3F,OAAO;QACL,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,EAAE,MAAM,EAAE;QACpB,eAAe,EAAE,YAAY;QAC7B,GAAG,KAAK;KACgB,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { DQLContext } from '../context.js';
|
|
3
|
+
export declare const listProposalsInput: {
|
|
4
|
+
askedAtLeastTimes: z.ZodOptional<z.ZodNumber>;
|
|
5
|
+
since: z.ZodOptional<z.ZodString>;
|
|
6
|
+
};
|
|
7
|
+
export interface ProposalSummary {
|
|
8
|
+
draftPath: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
question: string;
|
|
11
|
+
askedTimes: number;
|
|
12
|
+
firstAsked: string;
|
|
13
|
+
lastAsked: string;
|
|
14
|
+
proposedContractId: string;
|
|
15
|
+
proposedDomain: string;
|
|
16
|
+
proposedEntity: string;
|
|
17
|
+
upstreamRefs: string[];
|
|
18
|
+
certifyHint: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The OSS-side review queue for the Tier-2 promotion loop. Reads
|
|
22
|
+
* `blocks/_drafts/*.dql` from the project, parses the `_proposed { ... }`
|
|
23
|
+
* provenance block out of each, and returns a list ranked by `askedTimes`
|
|
24
|
+
* descending — questions that get asked repeatedly are the strongest
|
|
25
|
+
* candidates for certification.
|
|
26
|
+
*
|
|
27
|
+
* Multi-user team queues (RBAC, assignments, deadlines, audit logs) are
|
|
28
|
+
* commercial-overlay features. This OSS tool reads files from disk and
|
|
29
|
+
* commits to git when humans certify them. That's the shared store.
|
|
30
|
+
*/
|
|
31
|
+
export declare function listProposals(ctx: DQLContext, args?: {
|
|
32
|
+
askedAtLeastTimes?: number;
|
|
33
|
+
since?: string;
|
|
34
|
+
}): {
|
|
35
|
+
proposals: ProposalSummary[];
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=list-proposals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-proposals.d.ts","sourceRoot":"","sources":["../../src/tools/list-proposals.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;CAa9B,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxD;IAAE,SAAS,EAAE,eAAe,EAAE,CAAA;CAAE,CAwBlC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export const listProposalsInput = {
|
|
5
|
+
askedAtLeastTimes: z
|
|
6
|
+
.number()
|
|
7
|
+
.int()
|
|
8
|
+
.min(1)
|
|
9
|
+
.optional()
|
|
10
|
+
.describe('Filter to drafts asked at least N times (defaults to 1).'),
|
|
11
|
+
since: z
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe('ISO 8601 timestamp; only return drafts whose last_asked is on or after this. Useful for "what got asked this week?".'),
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* The OSS-side review queue for the Tier-2 promotion loop. Reads
|
|
18
|
+
* `blocks/_drafts/*.dql` from the project, parses the `_proposed { ... }`
|
|
19
|
+
* provenance block out of each, and returns a list ranked by `askedTimes`
|
|
20
|
+
* descending — questions that get asked repeatedly are the strongest
|
|
21
|
+
* candidates for certification.
|
|
22
|
+
*
|
|
23
|
+
* Multi-user team queues (RBAC, assignments, deadlines, audit logs) are
|
|
24
|
+
* commercial-overlay features. This OSS tool reads files from disk and
|
|
25
|
+
* commits to git when humans certify them. That's the shared store.
|
|
26
|
+
*/
|
|
27
|
+
export function listProposals(ctx, args = {}) {
|
|
28
|
+
const draftDir = join(ctx.projectRoot, 'blocks', '_drafts');
|
|
29
|
+
if (!existsSync(draftDir))
|
|
30
|
+
return { proposals: [] };
|
|
31
|
+
const minTimes = args.askedAtLeastTimes ?? 1;
|
|
32
|
+
const sinceMs = args.since ? Date.parse(args.since) : null;
|
|
33
|
+
const proposals = [];
|
|
34
|
+
for (const entry of readdirSync(draftDir)) {
|
|
35
|
+
if (!entry.endsWith('.dql'))
|
|
36
|
+
continue;
|
|
37
|
+
const path = join(draftDir, entry);
|
|
38
|
+
const summary = parseProposal(readFileSync(path, 'utf-8'), entry, ctx.projectRoot);
|
|
39
|
+
if (!summary)
|
|
40
|
+
continue;
|
|
41
|
+
if (summary.askedTimes < minTimes)
|
|
42
|
+
continue;
|
|
43
|
+
if (sinceMs !== null && Date.parse(summary.lastAsked) < sinceMs)
|
|
44
|
+
continue;
|
|
45
|
+
proposals.push(summary);
|
|
46
|
+
}
|
|
47
|
+
proposals.sort((a, b) => {
|
|
48
|
+
if (b.askedTimes !== a.askedTimes)
|
|
49
|
+
return b.askedTimes - a.askedTimes;
|
|
50
|
+
return Date.parse(b.lastAsked) - Date.parse(a.lastAsked);
|
|
51
|
+
});
|
|
52
|
+
return { proposals };
|
|
53
|
+
}
|
|
54
|
+
function parseProposal(content, filename, projectRoot) {
|
|
55
|
+
const slug = filename.replace(/\.dql$/, '');
|
|
56
|
+
const question = pickStringField(content, 'description') ?? slug;
|
|
57
|
+
const askedTimes = pickIntField(content, 'asked_times', 1);
|
|
58
|
+
const firstAsked = pickStringField(content, 'first_asked') ?? '';
|
|
59
|
+
const lastAsked = pickStringField(content, 'last_asked') ?? '';
|
|
60
|
+
const proposedContractId = pickStringField(content, 'proposed_contract_id') ?? '';
|
|
61
|
+
const proposedDomain = pickStringField(content, 'proposed_domain') ?? '';
|
|
62
|
+
const proposedEntity = pickStringField(content, 'proposed_entity') ?? '';
|
|
63
|
+
const upstreamRefs = pickArrayField(content, 'upstream_refs');
|
|
64
|
+
const draftPath = relativeTo(projectRoot, `blocks/_drafts/${filename}`);
|
|
65
|
+
const certifyHint = `dql certify --from-draft ${draftPath} --domain ${proposedDomain || '<domain>'} --contract ${proposedContractId || '<id>'}@1 --owner <you@example.com>`;
|
|
66
|
+
return {
|
|
67
|
+
draftPath,
|
|
68
|
+
slug,
|
|
69
|
+
question,
|
|
70
|
+
askedTimes,
|
|
71
|
+
firstAsked,
|
|
72
|
+
lastAsked,
|
|
73
|
+
proposedContractId,
|
|
74
|
+
proposedDomain,
|
|
75
|
+
proposedEntity,
|
|
76
|
+
upstreamRefs,
|
|
77
|
+
certifyHint,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function pickStringField(content, key) {
|
|
81
|
+
const m = content.match(new RegExp(`${key}\\s*=\\s*"([^"]*)"`)) ||
|
|
82
|
+
content.match(new RegExp(`${key}\\s*=\\s*"""([\\s\\S]*?)"""`));
|
|
83
|
+
return m?.[1]?.trim();
|
|
84
|
+
}
|
|
85
|
+
function pickIntField(content, key, defaultValue) {
|
|
86
|
+
const m = content.match(new RegExp(`${key}\\s*=\\s*(\\d+)`));
|
|
87
|
+
return m ? Number.parseInt(m[1], 10) : defaultValue;
|
|
88
|
+
}
|
|
89
|
+
function pickArrayField(content, key) {
|
|
90
|
+
const m = content.match(new RegExp(`${key}\\s*=\\s*\\[([^\\]]*)\\]`));
|
|
91
|
+
if (!m)
|
|
92
|
+
return [];
|
|
93
|
+
return m[1]
|
|
94
|
+
.split(',')
|
|
95
|
+
.map((s) => s.trim().replace(/^"|"$/g, ''))
|
|
96
|
+
.filter((s) => s.length > 0);
|
|
97
|
+
}
|
|
98
|
+
function relativeTo(root, relPath) {
|
|
99
|
+
return relPath.startsWith('/') ? relPath : relPath;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=list-proposals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-proposals.js","sourceRoot":"","sources":["../../src/tools/list-proposals.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-via-block.d.ts","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;CAS9B,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;cA+
|
|
1
|
+
{"version":3,"file":"query-via-block.d.ts","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;CAS9B,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;cA+D9B,MAAM;eAAS,MAAM;;;;GAiBlD"}
|
|
@@ -23,6 +23,21 @@ export async function queryViaBlock(ctx, args) {
|
|
|
23
23
|
error: `Block "${args.name}" is "${block.status ?? 'draft'}" — only certified blocks can be executed via MCP.`,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
// v1.6 — DataLex contract enforcement (the wedge).
|
|
27
|
+
// When a certified block declares datalex_contract, refuse the call if
|
|
28
|
+
// the reference doesn't resolve in the project's loaded DataLex
|
|
29
|
+
// manifest. We do NOT fail when no manifest is loaded — projects that
|
|
30
|
+
// haven't adopted DataLex still work; the analyzer separately surfaces a
|
|
31
|
+
// warning at compile time so the user is aware.
|
|
32
|
+
const datalexContract = block.datalexContract;
|
|
33
|
+
if (datalexContract && ctx.datalexRegistry.isLoaded()) {
|
|
34
|
+
const resolution = ctx.datalexRegistry.resolve(datalexContract);
|
|
35
|
+
if (!resolution.ok) {
|
|
36
|
+
return {
|
|
37
|
+
error: `Block "${args.name}" references DataLex contract "${datalexContract}" which ${resolution.reason === 'not_found' ? 'is not in the loaded DataLex manifest' : resolution.reason === 'version_mismatch' ? `pins a version that does not exist (available: ${(resolution.availableVersions ?? []).join(', ')})` : `is malformed (${resolution.message})`}. Refusing to serve until the contract resolves.`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
26
41
|
const base = args.serverUrl ?? process.env.DQL_RUNTIME_URL ?? 'http://127.0.0.1:3474';
|
|
27
42
|
const url = `${base.replace(/\/$/, '')}/api/notebook/execute`;
|
|
28
43
|
let source;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-via-block.js","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"query-via-block.js","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { DQLContext } from '../context.js';
|
|
3
|
+
export declare const queryViaMetadataInput: {
|
|
4
|
+
question: z.ZodString;
|
|
5
|
+
proposedSql: z.ZodString;
|
|
6
|
+
upstreamRefs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
7
|
+
proposedDomain: z.ZodOptional<z.ZodString>;
|
|
8
|
+
proposedEntity: z.ZodOptional<z.ZodString>;
|
|
9
|
+
saveDraft: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
+
dryRun: z.ZodOptional<z.ZodBoolean>;
|
|
11
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
serverUrl: z.ZodOptional<z.ZodString>;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Tier-2 of the graduated-trust loop. Use ONLY after `query_via_block` has
|
|
16
|
+
* confirmed there's no certified block for the question.
|
|
17
|
+
*
|
|
18
|
+
* - Executes the proposed SQL against the local runtime (unless dryRun).
|
|
19
|
+
* - Returns the result with `uncertified: true` so the agent surfaces the
|
|
20
|
+
* trust label to the human.
|
|
21
|
+
* - Optionally captures the proposal as a draft block at
|
|
22
|
+
* `blocks/_drafts/<slug>.dql`. Same question = same slug; askedTimes
|
|
23
|
+
* counter increments on dedupe.
|
|
24
|
+
*
|
|
25
|
+
* The agent contract: surface `uncertified: true` verbatim, and tell the
|
|
26
|
+
* user about the draft block path + the `dql certify --from-draft` command
|
|
27
|
+
* if they want the answer certified for next time.
|
|
28
|
+
*/
|
|
29
|
+
export declare function queryViaMetadata(ctx: DQLContext, args: {
|
|
30
|
+
question: string;
|
|
31
|
+
proposedSql: string;
|
|
32
|
+
upstreamRefs?: string[];
|
|
33
|
+
proposedDomain?: string;
|
|
34
|
+
proposedEntity?: string;
|
|
35
|
+
saveDraft?: boolean;
|
|
36
|
+
dryRun?: boolean;
|
|
37
|
+
limit?: number;
|
|
38
|
+
serverUrl?: string;
|
|
39
|
+
}): Promise<{
|
|
40
|
+
uncertified: boolean;
|
|
41
|
+
reason: string;
|
|
42
|
+
proposedSql: string;
|
|
43
|
+
draftBlock: {
|
|
44
|
+
path: string;
|
|
45
|
+
askedTimes: number;
|
|
46
|
+
proposedContractId: string;
|
|
47
|
+
} | undefined;
|
|
48
|
+
promote: string | undefined;
|
|
49
|
+
error?: undefined;
|
|
50
|
+
question?: undefined;
|
|
51
|
+
rowCount?: undefined;
|
|
52
|
+
durationMs?: undefined;
|
|
53
|
+
columns?: undefined;
|
|
54
|
+
rows?: undefined;
|
|
55
|
+
} | {
|
|
56
|
+
uncertified: boolean;
|
|
57
|
+
error: string;
|
|
58
|
+
draftBlock: {
|
|
59
|
+
path: string;
|
|
60
|
+
askedTimes: number;
|
|
61
|
+
proposedContractId: string;
|
|
62
|
+
} | undefined;
|
|
63
|
+
reason?: undefined;
|
|
64
|
+
proposedSql?: undefined;
|
|
65
|
+
promote?: undefined;
|
|
66
|
+
question?: undefined;
|
|
67
|
+
rowCount?: undefined;
|
|
68
|
+
durationMs?: undefined;
|
|
69
|
+
columns?: undefined;
|
|
70
|
+
rows?: undefined;
|
|
71
|
+
} | {
|
|
72
|
+
uncertified: boolean;
|
|
73
|
+
reason: string;
|
|
74
|
+
question: string;
|
|
75
|
+
rowCount: number;
|
|
76
|
+
durationMs: number | null;
|
|
77
|
+
columns: {
|
|
78
|
+
name: string;
|
|
79
|
+
type?: string;
|
|
80
|
+
}[];
|
|
81
|
+
rows: unknown[];
|
|
82
|
+
draftBlock: {
|
|
83
|
+
path: string;
|
|
84
|
+
askedTimes: number;
|
|
85
|
+
proposedContractId: string;
|
|
86
|
+
} | undefined;
|
|
87
|
+
promote: string | undefined;
|
|
88
|
+
proposedSql?: undefined;
|
|
89
|
+
error?: undefined;
|
|
90
|
+
}>;
|
|
91
|
+
/**
|
|
92
|
+
* Derive a deterministic snake_case slug from a free-form question. Same
|
|
93
|
+
* question -> same slug, so re-asking the question increments `asked_times`
|
|
94
|
+
* on the existing draft instead of creating a new file.
|
|
95
|
+
*
|
|
96
|
+
* v1: lowercase, strip punctuation, drop stopwords + common quantifiers
|
|
97
|
+
* (e.g. "how many"), join with `_`. Truncated to 60 chars to keep file
|
|
98
|
+
* paths sensible. Not perfect across paraphrases — that's a v2 problem.
|
|
99
|
+
*/
|
|
100
|
+
export declare function deriveSlug(question: string): string;
|
|
101
|
+
//# sourceMappingURL=query-via-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-via-metadata.d.ts","sourceRoot":"","sources":["../../src/tools/query-via-metadata.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,qBAAqB;;;;;;;;;;CAsDjC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;;;;cAKuB,MAAM;oBAAc,MAAM;4BAAsB,MAAM;;;;;;;;;;;;;cAAtD,MAAM;oBAAc,MAAM;4BAAsB,MAAM;;;;;;;;;;;;;;;;;cA4DlD,MAAM;eAAS,MAAM;;;;cA5DzB,MAAM;oBAAc,MAAM;4BAAsB,MAAM;;;;;GAoF/E;AAYD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQnD"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export const queryViaMetadataInput = {
|
|
5
|
+
question: z
|
|
6
|
+
.string()
|
|
7
|
+
.min(1)
|
|
8
|
+
.describe('The user question being answered, verbatim. Used for the draft block name and description.'),
|
|
9
|
+
proposedSql: z
|
|
10
|
+
.string()
|
|
11
|
+
.min(1)
|
|
12
|
+
.describe('SQL the agent inferred from the available manifest + dbt schema. Will be executed through the local DQL runtime against the certified data plane.'),
|
|
13
|
+
upstreamRefs: z
|
|
14
|
+
.array(z.string())
|
|
15
|
+
.optional()
|
|
16
|
+
.describe('Tables / blocks the agent thinks are involved.'),
|
|
17
|
+
proposedDomain: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Best guess at the DataLex domain that owns this question (e.g. "customer", "finance"). Used to suggest a contract id.'),
|
|
21
|
+
proposedEntity: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Best guess at the entity (PascalCase, e.g. "Customer"). Used together with proposedDomain to suggest a contract id.'),
|
|
25
|
+
saveDraft: z
|
|
26
|
+
.boolean()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Persist a draft .dql file under blocks/_drafts/ for later human review and certification. Default true.'),
|
|
29
|
+
dryRun: z
|
|
30
|
+
.boolean()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('If true, return the proposed SQL + lineage without executing. Default false (execute).'),
|
|
33
|
+
limit: z
|
|
34
|
+
.number()
|
|
35
|
+
.int()
|
|
36
|
+
.min(1)
|
|
37
|
+
.max(10000)
|
|
38
|
+
.optional()
|
|
39
|
+
.describe('Max rows to return on execution.'),
|
|
40
|
+
serverUrl: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('Base URL of the local DQL runtime (default http://127.0.0.1:3474). Start it with `dql serve`.'),
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Tier-2 of the graduated-trust loop. Use ONLY after `query_via_block` has
|
|
47
|
+
* confirmed there's no certified block for the question.
|
|
48
|
+
*
|
|
49
|
+
* - Executes the proposed SQL against the local runtime (unless dryRun).
|
|
50
|
+
* - Returns the result with `uncertified: true` so the agent surfaces the
|
|
51
|
+
* trust label to the human.
|
|
52
|
+
* - Optionally captures the proposal as a draft block at
|
|
53
|
+
* `blocks/_drafts/<slug>.dql`. Same question = same slug; askedTimes
|
|
54
|
+
* counter increments on dedupe.
|
|
55
|
+
*
|
|
56
|
+
* The agent contract: surface `uncertified: true` verbatim, and tell the
|
|
57
|
+
* user about the draft block path + the `dql certify --from-draft` command
|
|
58
|
+
* if they want the answer certified for next time.
|
|
59
|
+
*/
|
|
60
|
+
export async function queryViaMetadata(ctx, args) {
|
|
61
|
+
const slug = deriveSlug(args.question);
|
|
62
|
+
const proposedContractId = suggestContractId(slug, args.proposedDomain, args.proposedEntity);
|
|
63
|
+
let draftBlock;
|
|
64
|
+
if (args.saveDraft !== false) {
|
|
65
|
+
draftBlock = upsertDraft(ctx.projectRoot, {
|
|
66
|
+
slug,
|
|
67
|
+
question: args.question,
|
|
68
|
+
proposedSql: args.proposedSql,
|
|
69
|
+
proposedContractId,
|
|
70
|
+
proposedDomain: args.proposedDomain,
|
|
71
|
+
proposedEntity: args.proposedEntity,
|
|
72
|
+
upstreamRefs: args.upstreamRefs ?? [],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (args.dryRun) {
|
|
76
|
+
return {
|
|
77
|
+
uncertified: true,
|
|
78
|
+
reason: 'dryRun=true; SQL not executed. Returned proposal only.',
|
|
79
|
+
proposedSql: args.proposedSql,
|
|
80
|
+
draftBlock,
|
|
81
|
+
promote: draftBlock
|
|
82
|
+
? `if you want this question certified, run: dql certify --from-draft ${draftBlock.path}`
|
|
83
|
+
: undefined,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const base = args.serverUrl ?? process.env.DQL_RUNTIME_URL ?? 'http://127.0.0.1:3474';
|
|
87
|
+
const url = `${base.replace(/\/$/, '')}/api/notebook/execute`;
|
|
88
|
+
let response;
|
|
89
|
+
try {
|
|
90
|
+
response = await fetch(url, {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers: { 'Content-Type': 'application/json' },
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
cell: {
|
|
95
|
+
id: `mcp-tier2-${slug}`,
|
|
96
|
+
type: 'dql',
|
|
97
|
+
source: wrapSqlAsDqlCell(args.proposedSql),
|
|
98
|
+
title: args.question,
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return {
|
|
105
|
+
uncertified: true,
|
|
106
|
+
error: `Could not reach DQL runtime at ${base}. Start it with \`dql serve\` in ${ctx.projectRoot}. (${err instanceof Error ? err.message : String(err)})`,
|
|
107
|
+
draftBlock,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
return {
|
|
112
|
+
uncertified: true,
|
|
113
|
+
error: `Runtime returned ${response.status}: ${await response.text()}`,
|
|
114
|
+
draftBlock,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const payload = (await response.json());
|
|
118
|
+
if (payload.error) {
|
|
119
|
+
return { uncertified: true, error: payload.error, draftBlock };
|
|
120
|
+
}
|
|
121
|
+
const rows = payload.result?.rows ?? [];
|
|
122
|
+
return {
|
|
123
|
+
uncertified: true,
|
|
124
|
+
reason: 'no certified block matched the question; result derived from manifest + dbt schema',
|
|
125
|
+
question: args.question,
|
|
126
|
+
rowCount: rows.length,
|
|
127
|
+
durationMs: payload.result?.executionTime ?? null,
|
|
128
|
+
columns: payload.result?.columns ?? [],
|
|
129
|
+
rows: args.limit ? rows.slice(0, args.limit) : rows,
|
|
130
|
+
draftBlock,
|
|
131
|
+
promote: draftBlock
|
|
132
|
+
? `if you want this question certified, run: dql certify --from-draft ${draftBlock.path}`
|
|
133
|
+
: undefined,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// -- helpers ---------------------------------------------------------------
|
|
137
|
+
const STOPWORDS = new Set([
|
|
138
|
+
'a', 'an', 'and', 'are', 'as', 'at', 'be', 'by', 'do', 'for', 'from',
|
|
139
|
+
'has', 'have', 'how', 'i', 'in', 'is', 'it', 'me', 'much', 'my', 'of',
|
|
140
|
+
'on', 'or', 'our', 'so', 'that', 'the', 'their', 'then', 'there', 'this',
|
|
141
|
+
'to', 'us', 'was', 'we', 'were', 'what', 'when', 'where', 'which', 'who',
|
|
142
|
+
'why', 'will', 'with', 'you', 'your',
|
|
143
|
+
]);
|
|
144
|
+
/**
|
|
145
|
+
* Derive a deterministic snake_case slug from a free-form question. Same
|
|
146
|
+
* question -> same slug, so re-asking the question increments `asked_times`
|
|
147
|
+
* on the existing draft instead of creating a new file.
|
|
148
|
+
*
|
|
149
|
+
* v1: lowercase, strip punctuation, drop stopwords + common quantifiers
|
|
150
|
+
* (e.g. "how many"), join with `_`. Truncated to 60 chars to keep file
|
|
151
|
+
* paths sensible. Not perfect across paraphrases — that's a v2 problem.
|
|
152
|
+
*/
|
|
153
|
+
export function deriveSlug(question) {
|
|
154
|
+
const tokens = question
|
|
155
|
+
.toLowerCase()
|
|
156
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
157
|
+
.split(/\s+/)
|
|
158
|
+
.filter((t) => t.length > 0 && !STOPWORDS.has(t));
|
|
159
|
+
const slug = tokens.join('_').slice(0, 60).replace(/_+$/, '');
|
|
160
|
+
return slug || 'untitled_proposal';
|
|
161
|
+
}
|
|
162
|
+
function suggestContractId(slug, domain, entity) {
|
|
163
|
+
const d = (domain || 'misc').toLowerCase();
|
|
164
|
+
const e = entity && /^[A-Z]/.test(entity) ? entity : 'Unknown';
|
|
165
|
+
return `${d}.${e}.${slug}`;
|
|
166
|
+
}
|
|
167
|
+
function wrapSqlAsDqlCell(sql) {
|
|
168
|
+
// Tier-2 cells are raw SQL. The runtime accepts SQL directly; no DQL
|
|
169
|
+
// block wrapper is required for execution.
|
|
170
|
+
return sql;
|
|
171
|
+
}
|
|
172
|
+
function upsertDraft(projectRoot, rec) {
|
|
173
|
+
const draftDir = join(projectRoot, 'blocks', '_drafts');
|
|
174
|
+
const filePath = join(draftDir, `${rec.slug}.dql`);
|
|
175
|
+
if (existsSync(filePath)) {
|
|
176
|
+
const existing = readFileSync(filePath, 'utf-8');
|
|
177
|
+
const m = existing.match(/asked_times\s*=\s*(\d+)/);
|
|
178
|
+
const prev = m ? Number.parseInt(m[1], 10) : 1;
|
|
179
|
+
const next = Number.isFinite(prev) ? prev + 1 : 2;
|
|
180
|
+
const updated = m
|
|
181
|
+
? existing.replace(/asked_times\s*=\s*\d+/, `asked_times = ${next}`)
|
|
182
|
+
: existing.replace(/_proposed\s*\{/, `_proposed {\n asked_times = ${next}`);
|
|
183
|
+
const stamped = stampLastAsked(updated);
|
|
184
|
+
writeFileSync(filePath, stamped);
|
|
185
|
+
return {
|
|
186
|
+
path: relativeToProject(projectRoot, filePath),
|
|
187
|
+
askedTimes: next,
|
|
188
|
+
proposedContractId: rec.proposedContractId,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
192
|
+
writeFileSync(filePath, renderDraft(rec));
|
|
193
|
+
return {
|
|
194
|
+
path: relativeToProject(projectRoot, filePath),
|
|
195
|
+
askedTimes: 1,
|
|
196
|
+
proposedContractId: rec.proposedContractId,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function relativeToProject(root, abs) {
|
|
200
|
+
const rootSlash = root.endsWith('/') ? root : root + '/';
|
|
201
|
+
return abs.startsWith(rootSlash) ? abs.slice(rootSlash.length) : abs;
|
|
202
|
+
}
|
|
203
|
+
function renderDraft(rec) {
|
|
204
|
+
const now = new Date().toISOString();
|
|
205
|
+
const upstream = rec.upstreamRefs.length > 0
|
|
206
|
+
? `\n upstream_refs = [${rec.upstreamRefs.map((u) => `"${u}"`).join(', ')}]`
|
|
207
|
+
: '';
|
|
208
|
+
// Single quoted SQL inside triple-double-quotes; avoid breaking on `"""` in user SQL.
|
|
209
|
+
const safeSql = rec.proposedSql.replace(/"""/g, '\\"\\"\\"');
|
|
210
|
+
return `block "${rec.slug}" {
|
|
211
|
+
domain = "${rec.proposedDomain ?? 'misc'}"
|
|
212
|
+
type = "custom"
|
|
213
|
+
status = "draft"
|
|
214
|
+
description = """${rec.question}"""
|
|
215
|
+
|
|
216
|
+
# Tier-2 proposal — auto-captured from query_via_metadata. Reviewer
|
|
217
|
+
# fills in datalex_contract + owner, then runs:
|
|
218
|
+
# dql certify --from-draft blocks/_drafts/${rec.slug}.dql \\
|
|
219
|
+
# --domain ${rec.proposedDomain ?? 'misc'} \\
|
|
220
|
+
# --contract ${rec.proposedContractId}@1 \\
|
|
221
|
+
# --owner you@example.com
|
|
222
|
+
datalex_contract = ""
|
|
223
|
+
|
|
224
|
+
_proposed {
|
|
225
|
+
asked_times = 1
|
|
226
|
+
first_asked = "${now}"
|
|
227
|
+
last_asked = "${now}"
|
|
228
|
+
proposed_contract_id = "${rec.proposedContractId}"
|
|
229
|
+
proposed_domain = "${rec.proposedDomain ?? ''}"
|
|
230
|
+
proposed_entity = "${rec.proposedEntity ?? ''}"${upstream}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
query = """
|
|
234
|
+
${safeSql.split('\n').join('\n ')}
|
|
235
|
+
"""
|
|
236
|
+
}
|
|
237
|
+
`;
|
|
238
|
+
}
|
|
239
|
+
function stampLastAsked(content) {
|
|
240
|
+
const now = new Date().toISOString();
|
|
241
|
+
if (/last_asked\s*=\s*"[^"]*"/.test(content)) {
|
|
242
|
+
return content.replace(/last_asked\s*=\s*"[^"]*"/, `last_asked = "${now}"`);
|
|
243
|
+
}
|
|
244
|
+
return content;
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=query-via-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-via-metadata.js","sourceRoot":"","sources":["../../src/tools/query-via-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CACP,4FAA4F,CAC7F;IACH,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CACP,mJAAmJ,CACpJ;IACH,YAAY,EAAE,CAAC;SACZ,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,gDAAgD,CAAC;IAC7D,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,uHAAuH,CACxH;IACH,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,qHAAqH,CACtH;IACH,SAAS,EAAE,CAAC;SACT,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,yGAAyG,CAC1G;IACH,MAAM,EAAE,CAAC;SACN,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,wFAAwF,CACzF;IACH,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,KAAK,CAAC;SACV,QAAQ,EAAE;SACV,QAAQ,CAAC,kCAAkC,CAAC;IAC/C,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,+FAA+F,CAChG;CACJ,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAe,EACf,IAUC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAE7F,IAAI,UAAwF,CAAC;IAC7F,IAAI,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;QAC7B,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE;YACxC,IAAI;YACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,kBAAkB;YAClB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE;SACtC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,wDAAwD;YAChE,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU;YACV,OAAO,EAAE,UAAU;gBACjB,CAAC,CAAC,sEAAsE,UAAU,CAAC,IAAI,EAAE;gBACzF,CAAC,CAAC,SAAS;SACd,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,uBAAuB,CAAC;IACtF,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,uBAAuB,CAAC;IAE9D,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC1B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI,EAAE;oBACJ,EAAE,EAAE,aAAa,IAAI,EAAE;oBACvB,IAAI,EAAE,KAAK;oBACX,MAAM,EAAE,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC;oBAC1C,KAAK,EAAE,IAAI,CAAC,QAAQ;iBACrB;aACF,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,KAAK,EAAE,kCAAkC,IAAI,oCAAoC,GAAG,CAAC,WAAW,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG;YACzJ,UAAU;SACX,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,KAAK,EAAE,oBAAoB,QAAQ,CAAC,MAAM,KAAK,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE;YACtE,UAAU;SACX,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAOrC,CAAC;IACF,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;IACjE,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;IAExC,OAAO;QACL,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,oFAAoF;QAC5F,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,IAAI,CAAC,MAAM;QACrB,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,IAAI,IAAI;QACjD,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI,EAAE;QACtC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;QACnD,UAAU;QACV,OAAO,EAAE,UAAU;YACjB,CAAC,CAAC,sEAAsE,UAAU,CAAC,IAAI,EAAE;YACzF,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED,6EAA6E;AAE7E,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM;IACpE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI;IACrE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IACxE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK;IACxE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CACrC,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,MAAM,GAAG,QAAQ;SACpB,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9D,OAAO,IAAI,IAAI,mBAAmB,CAAC;AACrC,CAAC;AAED,SAAS,iBAAiB,CACxB,IAAY,EACZ,MAA0B,EAC1B,MAA0B;IAE1B,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,CAAC,GAAG,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/D,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACnC,qEAAqE;IACrE,2CAA2C;IAC3C,OAAO,GAAG,CAAC;AACb,CAAC;AAYD,SAAS,WAAW,CAClB,WAAmB,EACnB,GAAgB;IAEhB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC;IAEnD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,CAAC;YACf,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,uBAAuB,EAAE,iBAAiB,IAAI,EAAE,CAAC;YACpE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,sCAAsC,IAAI,EAAE,CAAC,CAAC;QACrF,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACxC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjC,OAAO;YACL,IAAI,EAAE,iBAAiB,CAAC,WAAW,EAAE,QAAQ,CAAC;YAC9C,UAAU,EAAE,IAAI;YAChB,kBAAkB,EAAE,GAAG,CAAC,kBAAkB;SAC3C,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,aAAa,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,OAAO;QACL,IAAI,EAAE,iBAAiB,CAAC,WAAW,EAAE,QAAQ,CAAC;QAC9C,UAAU,EAAE,CAAC;QACb,kBAAkB,EAAE,GAAG,CAAC,kBAAkB;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,GAAW;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;IACzD,OAAO,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACvE,CAAC;AAED,SAAS,WAAW,CAAC,GAAgB;IACnC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;QAC1C,CAAC,CAAC,0BAA0B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QAC/E,CAAC,CAAC,EAAE,CAAC;IACP,sFAAsF;IACtF,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7D,OAAO,UAAU,GAAG,CAAC,IAAI;gBACX,GAAG,CAAC,cAAc,IAAI,MAAM;;;uBAGrB,GAAG,CAAC,QAAQ;;;;kDAIe,GAAG,CAAC,IAAI;+BAC3B,GAAG,CAAC,cAAc,IAAI,MAAM;iCAC1B,GAAG,CAAC,kBAAkB;;;;;;yBAM9B,GAAG;wBACJ,GAAG;kCACO,GAAG,CAAC,kBAAkB;6BAC3B,GAAG,CAAC,cAAc,IAAI,EAAE;6BACxB,GAAG,CAAC,cAAc,IAAI,EAAE,IAAI,QAAQ;;;;UAIvD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;;;CAG/C,CAAC;AACF,CAAC;AAED,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,0BAA0B,EAAE,iBAAiB,GAAG,GAAG,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duckcodeailabs/dql-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "DQL MCP server: expose certified blocks, semantic layer, lineage, and governance to LLM agents via the Model Context Protocol",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@duckcodeailabs/dql-agent": "^1.5.2",
|
|
28
|
-
"@duckcodeailabs/dql-core": "^1.5.2",
|
|
29
|
-
"@duckcodeailabs/dql-governance": "^1.5.2",
|
|
30
|
-
"@duckcodeailabs/dql-project": "^1.5.2",
|
|
31
27
|
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
32
|
-
"zod": "^3.25.0"
|
|
28
|
+
"zod": "^3.25.0",
|
|
29
|
+
"@duckcodeailabs/dql-agent": "1.6.0",
|
|
30
|
+
"@duckcodeailabs/dql-project": "1.6.0",
|
|
31
|
+
"@duckcodeailabs/dql-governance": "1.6.0",
|
|
32
|
+
"@duckcodeailabs/dql-core": "1.6.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^20.0.0",
|