@duckcodeailabs/dql-agent 1.11.10 → 1.12.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.
Files changed (69) hide show
  1. package/dist/agent-run-engine.d.ts.map +1 -1
  2. package/dist/agent-run-engine.js +7 -3
  3. package/dist/agent-run-engine.js.map +1 -1
  4. package/dist/answer-loop.d.ts +25 -1
  5. package/dist/answer-loop.d.ts.map +1 -1
  6. package/dist/answer-loop.js +139 -16
  7. package/dist/answer-loop.js.map +1 -1
  8. package/dist/conversation/rolling-summary.d.ts +23 -0
  9. package/dist/conversation/rolling-summary.d.ts.map +1 -1
  10. package/dist/conversation/rolling-summary.js +64 -0
  11. package/dist/conversation/rolling-summary.js.map +1 -1
  12. package/dist/conversation/session-store.d.ts +18 -2
  13. package/dist/conversation/session-store.d.ts.map +1 -1
  14. package/dist/conversation/session-store.js +65 -8
  15. package/dist/conversation/session-store.js.map +1 -1
  16. package/dist/conversation/snapshot.d.ts +37 -4
  17. package/dist/conversation/snapshot.d.ts.map +1 -1
  18. package/dist/conversation/snapshot.js +115 -6
  19. package/dist/conversation/snapshot.js.map +1 -1
  20. package/dist/hints/correction-eval.d.ts.map +1 -1
  21. package/dist/hints/correction-eval.js +4 -6
  22. package/dist/hints/correction-eval.js.map +1 -1
  23. package/dist/hints/dependencies.d.ts +63 -0
  24. package/dist/hints/dependencies.d.ts.map +1 -0
  25. package/dist/hints/dependencies.js +196 -0
  26. package/dist/hints/dependencies.js.map +1 -0
  27. package/dist/hints/git-store.d.ts +55 -2
  28. package/dist/hints/git-store.d.ts.map +1 -1
  29. package/dist/hints/git-store.js +246 -11
  30. package/dist/hints/git-store.js.map +1 -1
  31. package/dist/hints/graph.d.ts +17 -0
  32. package/dist/hints/graph.d.ts.map +1 -0
  33. package/dist/hints/graph.js +222 -0
  34. package/dist/hints/graph.js.map +1 -0
  35. package/dist/hints/lifecycle.d.ts +101 -0
  36. package/dist/hints/lifecycle.d.ts.map +1 -0
  37. package/dist/hints/lifecycle.js +387 -0
  38. package/dist/hints/lifecycle.js.map +1 -0
  39. package/dist/hints/retrieval.d.ts +13 -1
  40. package/dist/hints/retrieval.d.ts.map +1 -1
  41. package/dist/hints/retrieval.js +74 -11
  42. package/dist/hints/retrieval.js.map +1 -1
  43. package/dist/hints/store.d.ts +9 -2
  44. package/dist/hints/store.d.ts.map +1 -1
  45. package/dist/hints/store.js +155 -15
  46. package/dist/hints/store.js.map +1 -1
  47. package/dist/hints/types.d.ts +63 -3
  48. package/dist/hints/types.d.ts.map +1 -1
  49. package/dist/hints/types.js +1 -1
  50. package/dist/hints/types.js.map +1 -1
  51. package/dist/index.d.ts +16 -10
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +8 -5
  54. package/dist/index.js.map +1 -1
  55. package/dist/intent-controller.d.ts.map +1 -1
  56. package/dist/intent-controller.js +24 -3
  57. package/dist/intent-controller.js.map +1 -1
  58. package/dist/metadata/catalog.d.ts +32 -0
  59. package/dist/metadata/catalog.d.ts.map +1 -1
  60. package/dist/metadata/catalog.js +86 -4
  61. package/dist/metadata/catalog.js.map +1 -1
  62. package/dist/router.d.ts.map +1 -1
  63. package/dist/router.js +32 -9
  64. package/dist/router.js.map +1 -1
  65. package/dist/skills/loader.js +1 -1
  66. package/dist/skills/loader.js.map +1 -1
  67. package/dist/tools/registry.js +5 -5
  68. package/dist/tools/registry.js.map +1 -1
  69. package/package.json +4 -4
@@ -20,6 +20,7 @@ import { extractSimpleSelectShape, sourceSqlShapeColumns } from './sql-shape.js'
20
20
  import { grainMatches, requestedGrainFromPlan, } from './grain-gate.js';
21
21
  import { certifiedFitAllowsTier1, certifiedTerminationVerdict, evaluateCertifiedBlockFit, } from './block-fit.js';
22
22
  import { retrieveScopedHints } from '../hints/retrieval.js';
23
+ import { currentHintDependencyFingerprints } from '../hints/dependencies.js';
23
24
  import { buildFtsMatch } from '../memory/fts-query.js';
24
25
  import { cosineSimilarity, envEmbeddingProvider, HashedTokenEmbeddingProvider, } from '../embeddings/provider.js';
25
26
  import { projectEmbeddingProvider } from '../embeddings/project-embeddings.js';
@@ -721,11 +722,16 @@ export async function buildLocalContextPack(projectRoot, request) {
721
722
  // Approved scoped correction hints — folded in AFTER certified routing so
722
723
  // they never override a certified answer. On the `certified` route we still
723
724
  // surface in-scope hints as advisory context, but never to change the route.
724
- const questionScope = deriveQuestionScope(request, questionPlan, objects, routeDecision);
725
+ const questionScope = deriveQuestionScope(request, questionPlan, objects, routeDecision, allowedSqlContext);
725
726
  const hintResult = await retrieveScopedHints(projectRoot, {
726
727
  questionScope,
727
728
  limit: 6,
728
- }).catch(() => ({ applied: [], conflicts: [] }));
729
+ currentSnapshotId: catalog.state('fingerprint'),
730
+ currentDependencies: currentHintDependencyFingerprints({
731
+ objects,
732
+ relations: allowedSqlContext.relations,
733
+ }),
734
+ }).catch(() => ({ applied: [], conflicts: [], excluded: [] }));
729
735
  const knowledgeLens = buildKnowledgeLens(catalog, effectiveDomainContext, selectedSkills);
730
736
  const domainBriefing = buildDomainBriefing(catalog, effectiveDomainContext);
731
737
  const payload = {
@@ -753,6 +759,7 @@ export async function buildLocalContextPack(projectRoot, request) {
753
759
  conflicts,
754
760
  appliedHints: hintResult.applied,
755
761
  hintConflicts: hintResult.conflicts,
762
+ hintExclusions: hintResult.excluded,
756
763
  retrievalDiagnostics: {
757
764
  strategy: usedFullCatalog ? 'full_catalog' : 'sqlite_fts',
758
765
  lanes: snapshotRetrieval.lanes,
@@ -2278,11 +2285,21 @@ export class MetadataCatalog {
2278
2285
  const capturedAt = snapshot.capturedAt ?? new Date().toISOString();
2279
2286
  const normalizedTables = normalizeRuntimeSchemaTables(snapshot.tables).slice(0, 10_000);
2280
2287
  const cleanSnapshot = {
2288
+ version: 1,
2289
+ generationId: snapshot.generationId,
2290
+ scopeFingerprint: snapshot.scopeFingerprint,
2291
+ connectionId: snapshot.connectionId,
2292
+ status: snapshot.status ?? 'ready',
2281
2293
  source: snapshot.source,
2282
2294
  capturedAt,
2295
+ observedTarget: normalizeRuntimeSchemaObservedTarget(snapshot.observedTarget),
2296
+ scopes: normalizeRuntimeSchemaScopes(snapshot.scopes),
2297
+ queryCount: boundedRuntimeSchemaNumber(snapshot.queryCount),
2298
+ durationMs: boundedRuntimeSchemaNumber(snapshot.durationMs),
2299
+ truncated: snapshot.truncated === true || undefined,
2283
2300
  tables: normalizedTables,
2284
2301
  };
2285
- const id = `schema_${Date.parse(capturedAt) || Date.now()}`;
2302
+ const id = snapshot.generationId?.trim() || `schema_${Date.parse(capturedAt) || Date.now()}`;
2286
2303
  const insertSnapshot = this.db.prepare(`
2287
2304
  INSERT OR REPLACE INTO runtime_schema_snapshots (
2288
2305
  id, source, payload_json, captured_at
@@ -2325,6 +2342,10 @@ export class MetadataCatalog {
2325
2342
  setState.run('runtime_value_index_captured_at', capturedAt);
2326
2343
  setState.run('runtime_schema_table_count', String(normalizedTables.length));
2327
2344
  setState.run('runtime_schema_index_captured_at', capturedAt);
2345
+ setState.run('runtime_schema_generation_id', id);
2346
+ if (cleanSnapshot.scopeFingerprint) {
2347
+ setState.run('runtime_schema_scope_fingerprint', cleanSnapshot.scopeFingerprint);
2348
+ }
2328
2349
  });
2329
2350
  txn();
2330
2351
  return cleanSnapshot;
@@ -2989,6 +3010,10 @@ function addRawDbtCatalogObject(input) {
2989
3010
  schema,
2990
3011
  materialized: rawDbtMaterialization(input.node),
2991
3012
  dependsOn: rawDbtDependsOn(input.node),
3013
+ // dbt's checksum changes with the model/source definition. Persist it in
3014
+ // the governed object so Hint Graph dependency fingerprints detect SQL
3015
+ // edits even when relation names and columns stay the same.
3016
+ checksum: input.node.checksum,
2992
3017
  tags: metadataStringArray(input.node.tags),
2993
3018
  catalogOnly: existing ? undefined : true,
2994
3019
  columnCompleteness,
@@ -3762,7 +3787,7 @@ function addProjectDiagnostics(manifest, semanticLayer, diagnostics) {
3762
3787
  * Dialect is intentionally left undefined here (unknown at this layer); the hint
3763
3788
  * scope matcher tolerates an unknown question dialect.
3764
3789
  */
3765
- function deriveQuestionScope(request, questionPlan, objects, routeDecision) {
3790
+ function deriveQuestionScope(request, questionPlan, objects, routeDecision, allowedSqlContext) {
3766
3791
  const focusKey = routeDecision.exactObjectKey ?? request.focusObjectKey;
3767
3792
  const focus = focusKey ? objects.find((object) => object.objectKey === focusKey) : undefined;
3768
3793
  const topByType = (type) => objects.find((object) => object.objectType === type);
@@ -3784,6 +3809,13 @@ function deriveQuestionScope(request, questionPlan, objects, routeDecision) {
3784
3809
  domain: lowerOrUndef(domain),
3785
3810
  term: lowerOrUndef(term),
3786
3811
  block,
3812
+ relations: allowedSqlContext.relations
3813
+ .map((relation) => relation.relation)
3814
+ .filter(Boolean)
3815
+ .slice(0, 80),
3816
+ columns: allowedSqlContext.relations
3817
+ .flatMap((relation) => relation.columns.map((column) => `${relation.relation}.${column.name}`))
3818
+ .slice(0, 320),
3787
3819
  text: request.question,
3788
3820
  };
3789
3821
  }
@@ -5580,6 +5612,7 @@ function runtimeSchemaTableObject(table, snapshotSource, capturedAt) {
5580
5612
  sourceSystem: snapshotSource ?? table.source ?? 'runtime schema snapshot',
5581
5613
  payload: compactObject({
5582
5614
  relation,
5615
+ catalogOrDatabase: table.catalogOrDatabase,
5583
5616
  schema: table.schema,
5584
5617
  columnCompleteness: 'complete',
5585
5618
  columns: table.columns,
@@ -5935,6 +5968,7 @@ function normalizeRuntimeSchemaTables(tables) {
5935
5968
  const current = byRelation.get(key);
5936
5969
  const normalized = {
5937
5970
  relation,
5971
+ catalogOrDatabase: table.catalogOrDatabase,
5938
5972
  schema: table.schema,
5939
5973
  name: table.name ?? relation.split('.').at(-1) ?? relation,
5940
5974
  description: table.description,
@@ -5967,11 +6001,59 @@ function safeRuntimeSchemaSnapshot(value) {
5967
6001
  if (!Array.isArray(record.tables))
5968
6002
  return null;
5969
6003
  return {
6004
+ version: 1,
6005
+ generationId: stringValue(record.generationId),
6006
+ scopeFingerprint: stringValue(record.scopeFingerprint),
6007
+ connectionId: stringValue(record.connectionId),
6008
+ status: record.status === 'partial' || record.status === 'stale' ? record.status : 'ready',
5970
6009
  source: stringValue(record.source),
5971
6010
  capturedAt: stringValue(record.capturedAt),
6011
+ observedTarget: normalizeRuntimeSchemaObservedTarget(record.observedTarget),
6012
+ scopes: normalizeRuntimeSchemaScopes(record.scopes),
6013
+ queryCount: boundedRuntimeSchemaNumber(record.queryCount),
6014
+ durationMs: boundedRuntimeSchemaNumber(record.durationMs),
6015
+ truncated: record.truncated === true || undefined,
5972
6016
  tables: normalizeRuntimeSchemaTables(record.tables),
5973
6017
  };
5974
6018
  }
6019
+ function normalizeRuntimeSchemaObservedTarget(value) {
6020
+ if (!value || typeof value !== 'object' || Array.isArray(value))
6021
+ return undefined;
6022
+ const record = value;
6023
+ const driver = stringValue(record.driver);
6024
+ if (!driver)
6025
+ return undefined;
6026
+ return {
6027
+ driver,
6028
+ accountOrWorkspace: stringValue(record.accountOrWorkspace),
6029
+ role: stringValue(record.role),
6030
+ warehouse: stringValue(record.warehouse),
6031
+ defaultCatalogOrDatabase: stringValue(record.defaultCatalogOrDatabase),
6032
+ defaultSchema: stringValue(record.defaultSchema),
6033
+ };
6034
+ }
6035
+ function normalizeRuntimeSchemaScopes(value) {
6036
+ if (!Array.isArray(value))
6037
+ return undefined;
6038
+ const scopes = value.flatMap((entry) => {
6039
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry))
6040
+ return [];
6041
+ const record = entry;
6042
+ const catalogOrDatabase = stringValue(record.catalogOrDatabase);
6043
+ if (!catalogOrDatabase)
6044
+ return [];
6045
+ const schemas = Array.isArray(record.schemas)
6046
+ ? Array.from(new Set(record.schemas.map(stringValue).filter((item) => Boolean(item))))
6047
+ : [];
6048
+ return [{ catalogOrDatabase, schemas }];
6049
+ });
6050
+ return scopes.length > 0 ? scopes : undefined;
6051
+ }
6052
+ function boundedRuntimeSchemaNumber(value) {
6053
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0)
6054
+ return undefined;
6055
+ return Math.min(Number.MAX_SAFE_INTEGER, Math.floor(value));
6056
+ }
5975
6057
  function metadataRuntimeColumns(value) {
5976
6058
  if (!Array.isArray(value))
5977
6059
  return [];