@duckcodeailabs/dql-agent 1.13.5 → 1.14.1
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 +79 -4
- package/dist/agent-run-engine.d.ts.map +1 -1
- package/dist/agent-run-engine.js +457 -39
- package/dist/agent-run-engine.js.map +1 -1
- package/dist/agent-run-gates.d.ts.map +1 -1
- package/dist/agent-run-gates.js +13 -0
- package/dist/agent-run-gates.js.map +1 -1
- package/dist/agent-run-store.d.ts.map +1 -1
- package/dist/agent-run-store.js +42 -25
- package/dist/agent-run-store.js.map +1 -1
- package/dist/agentic/analyst-loop.d.ts +91 -0
- package/dist/agentic/analyst-loop.d.ts.map +1 -0
- package/dist/agentic/analyst-loop.js +311 -0
- package/dist/agentic/analyst-loop.js.map +1 -0
- package/dist/agentic/assumptions.d.ts +62 -0
- package/dist/agentic/assumptions.d.ts.map +1 -0
- package/dist/agentic/assumptions.js +73 -0
- package/dist/agentic/assumptions.js.map +1 -0
- package/dist/agentic/business-explanation.d.ts +56 -0
- package/dist/agentic/business-explanation.d.ts.map +1 -0
- package/dist/agentic/business-explanation.js +130 -0
- package/dist/agentic/business-explanation.js.map +1 -0
- package/dist/agentic/identifier-ledger.d.ts +74 -0
- package/dist/agentic/identifier-ledger.d.ts.map +1 -0
- package/dist/agentic/identifier-ledger.js +151 -0
- package/dist/agentic/identifier-ledger.js.map +1 -0
- package/dist/agentic/ledger-tools.d.ts +68 -0
- package/dist/agentic/ledger-tools.d.ts.map +1 -0
- package/dist/agentic/ledger-tools.js +198 -0
- package/dist/agentic/ledger-tools.js.map +1 -0
- package/dist/agentic/orchestrator-policy.d.ts +60 -0
- package/dist/agentic/orchestrator-policy.d.ts.map +1 -0
- package/dist/agentic/orchestrator-policy.js +73 -0
- package/dist/agentic/orchestrator-policy.js.map +1 -0
- package/dist/agentic/orchestrator.d.ts +54 -0
- package/dist/agentic/orchestrator.d.ts.map +1 -0
- package/dist/agentic/orchestrator.js +67 -0
- package/dist/agentic/orchestrator.js.map +1 -0
- package/dist/agentic/preview-tool.d.ts +36 -0
- package/dist/agentic/preview-tool.d.ts.map +1 -0
- package/dist/agentic/preview-tool.js +71 -0
- package/dist/agentic/preview-tool.js.map +1 -0
- package/dist/agentic/rerank.d.ts +50 -0
- package/dist/agentic/rerank.d.ts.map +1 -0
- package/dist/agentic/rerank.js +140 -0
- package/dist/agentic/rerank.js.map +1 -0
- package/dist/agentic/research/hypothesis.d.ts +110 -0
- package/dist/agentic/research/hypothesis.d.ts.map +1 -0
- package/dist/agentic/research/hypothesis.js +125 -0
- package/dist/agentic/research/hypothesis.js.map +1 -0
- package/dist/agentic/research/synthesis.d.ts +32 -0
- package/dist/agentic/research/synthesis.d.ts.map +1 -0
- package/dist/agentic/research/synthesis.js +94 -0
- package/dist/agentic/research/synthesis.js.map +1 -0
- package/dist/agentic/research-agent.d.ts +54 -0
- package/dist/agentic/research-agent.d.ts.map +1 -0
- package/dist/agentic/research-agent.js +176 -0
- package/dist/agentic/research-agent.js.map +1 -0
- package/dist/agentic/sql-authorization.d.ts +131 -0
- package/dist/agentic/sql-authorization.d.ts.map +1 -0
- package/dist/agentic/sql-authorization.js +232 -0
- package/dist/agentic/sql-authorization.js.map +1 -0
- package/dist/agentic/tool-loop.d.ts +29 -0
- package/dist/agentic/tool-loop.d.ts.map +1 -1
- package/dist/agentic/tool-loop.js +129 -52
- package/dist/agentic/tool-loop.js.map +1 -1
- package/dist/agentic/toolset.d.ts.map +1 -1
- package/dist/agentic/toolset.js +155 -0
- package/dist/agentic/toolset.js.map +1 -1
- package/dist/agentic/turn-plan.d.ts +35 -0
- package/dist/agentic/turn-plan.d.ts.map +1 -0
- package/dist/agentic/turn-plan.js +108 -0
- package/dist/agentic/turn-plan.js.map +1 -0
- package/dist/agentic/value-probe.d.ts +89 -0
- package/dist/agentic/value-probe.d.ts.map +1 -0
- package/dist/agentic/value-probe.js +304 -0
- package/dist/agentic/value-probe.js.map +1 -0
- package/dist/analytical-orchestration.d.ts +336 -0
- package/dist/analytical-orchestration.d.ts.map +1 -0
- package/dist/analytical-orchestration.js +631 -0
- package/dist/analytical-orchestration.js.map +1 -0
- package/dist/analytical-request-policy.d.ts +26 -0
- package/dist/analytical-request-policy.d.ts.map +1 -0
- package/dist/analytical-request-policy.js +82 -0
- package/dist/analytical-request-policy.js.map +1 -0
- package/dist/analytical-result-facts.d.ts +14 -1
- package/dist/analytical-result-facts.d.ts.map +1 -1
- package/dist/analytical-result-facts.js +76 -1
- package/dist/analytical-result-facts.js.map +1 -1
- package/dist/answer-loop.d.ts +61 -16
- package/dist/answer-loop.d.ts.map +1 -1
- package/dist/answer-loop.js +256 -36
- package/dist/answer-loop.js.map +1 -1
- package/dist/cascade/budgets.d.ts.map +1 -1
- package/dist/cascade/budgets.js +8 -1
- package/dist/cascade/budgets.js.map +1 -1
- package/dist/cascade/packer.d.ts +88 -0
- package/dist/cascade/packer.d.ts.map +1 -0
- package/dist/cascade/packer.js +106 -0
- package/dist/cascade/packer.js.map +1 -0
- package/dist/conversation/result-ops.d.ts +18 -3
- package/dist/conversation/result-ops.d.ts.map +1 -1
- package/dist/conversation/result-ops.js +77 -5
- package/dist/conversation/result-ops.js.map +1 -1
- package/dist/conversation/rolling-summary.d.ts.map +1 -1
- package/dist/conversation/rolling-summary.js +7 -2
- package/dist/conversation/rolling-summary.js.map +1 -1
- package/dist/conversation/session-store.d.ts +3 -0
- package/dist/conversation/session-store.d.ts.map +1 -1
- package/dist/conversation/session-store.js +8 -4
- package/dist/conversation/session-store.js.map +1 -1
- package/dist/conversation/snapshot.d.ts.map +1 -1
- package/dist/conversation/snapshot.js +13 -1
- package/dist/conversation/snapshot.js.map +1 -1
- package/dist/conversation/turn-trust.d.ts.map +1 -1
- package/dist/conversation/turn-trust.js +6 -0
- package/dist/conversation/turn-trust.js.map +1 -1
- package/dist/hints/store.d.ts.map +1 -1
- package/dist/hints/store.js +15 -5
- package/dist/hints/store.js.map +1 -1
- package/dist/index.d.ts +27 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -4
- package/dist/index.js.map +1 -1
- package/dist/intent-controller.d.ts +8 -0
- package/dist/intent-controller.d.ts.map +1 -1
- package/dist/intent-controller.js +65 -0
- package/dist/intent-controller.js.map +1 -1
- package/dist/meaning-resolution.d.ts +7 -0
- package/dist/meaning-resolution.d.ts.map +1 -1
- package/dist/meaning-resolution.js.map +1 -1
- package/dist/metadata/block-fit.d.ts +18 -0
- package/dist/metadata/block-fit.d.ts.map +1 -1
- package/dist/metadata/block-fit.js +41 -1
- package/dist/metadata/block-fit.js.map +1 -1
- package/dist/metadata/catalog.d.ts +44 -23
- package/dist/metadata/catalog.d.ts.map +1 -1
- package/dist/metadata/catalog.js +363 -53
- package/dist/metadata/catalog.js.map +1 -1
- package/dist/metadata/meaning-evidence.d.ts.map +1 -1
- package/dist/metadata/meaning-evidence.js +101 -8
- package/dist/metadata/meaning-evidence.js.map +1 -1
- package/dist/metadata/metric-match.d.ts +32 -0
- package/dist/metadata/metric-match.d.ts.map +1 -1
- package/dist/metadata/metric-match.js +120 -9
- package/dist/metadata/metric-match.js.map +1 -1
- package/dist/research-loop.d.ts +33 -2
- package/dist/research-loop.d.ts.map +1 -1
- package/dist/research-loop.js +44 -4
- package/dist/research-loop.js.map +1 -1
- package/dist/resolved-analytical-plan.d.ts.map +1 -1
- package/dist/resolved-analytical-plan.js +92 -5
- package/dist/resolved-analytical-plan.js.map +1 -1
- package/dist/router.d.ts +36 -16
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +604 -25
- package/dist/router.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytical-orchestration.d.ts","sourceRoot":"","sources":["../src/analytical-orchestration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared contracts for the conversational analytical orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* The existing DQL engine remains the authority for compilation, execution,
|
|
5
|
+
* trust, and the immutable resolved analytical plan. This module is the thin
|
|
6
|
+
* outer contract used by the conversational layer to describe what it
|
|
7
|
+
* understood, what it searched, and why it could or could not continue.
|
|
8
|
+
*
|
|
9
|
+
* The contract is intentionally content-only: it never carries model
|
|
10
|
+
* chain-of-thought, credentials, raw provider payloads, or authorization.
|
|
11
|
+
*
|
|
12
|
+
* Acceptance: AGT-027..033, CTX-007, PERF-003, E2E-022.
|
|
13
|
+
*/
|
|
14
|
+
import { createHash } from 'node:crypto';
|
|
15
|
+
export const ANALYTICAL_ORCHESTRATION_CONTRACT_VERSION = 1;
|
|
16
|
+
/**
|
|
17
|
+
* Small, explainable intent vocabulary used before the physical plan exists.
|
|
18
|
+
* It is deliberately not a second semantic matcher: candidate identity still
|
|
19
|
+
* comes from retrieval plus the bounded meaning call. These helpers only turn
|
|
20
|
+
* a request into a task graph and output contract, so a compound question can
|
|
21
|
+
* report partial success instead of collapsing the whole turn to one error.
|
|
22
|
+
*/
|
|
23
|
+
export function inferAnalyticalTurnKind(question) {
|
|
24
|
+
const text = question.toLowerCase();
|
|
25
|
+
if (/\b(hello|hi|hey|thanks|thank you|good morning|good afternoon)\b/.test(text))
|
|
26
|
+
return 'conversation';
|
|
27
|
+
if (/\b(why|root cause|driver|diagnos|anomal|changed)\b/.test(text))
|
|
28
|
+
return 'diagnosis';
|
|
29
|
+
if (/\b(research|investigate|deep dive|tell a story|surrounding context)\b/.test(text))
|
|
30
|
+
return 'research';
|
|
31
|
+
if (/\b(compare|versus|vs\.?|difference)\b/.test(text))
|
|
32
|
+
return 'comparison';
|
|
33
|
+
if (/\b(top|bottom|highest|lowest|rank)\b/.test(text))
|
|
34
|
+
return 'ranking';
|
|
35
|
+
if (/\b(by|per|over time|trend|monthly|daily|weekly)\b/.test(text))
|
|
36
|
+
return 'breakdown';
|
|
37
|
+
if (/\b(what is|what are|define|definition|meaning)\b/.test(text) && !/\b(total|revenue|count|sales|amount)\b/.test(text))
|
|
38
|
+
return 'definition';
|
|
39
|
+
if (/\b(region|country|state|city|name|label|email|category|product|customer)\b/.test(text)
|
|
40
|
+
&& /\b(where|which|what|who)\b/.test(text))
|
|
41
|
+
return 'lookup';
|
|
42
|
+
return 'aggregation';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* `Regarding: "Mr. Matthew Meyer"` and friends — a short label, a colon, and a
|
|
46
|
+
* quoted value, with nothing else in the clause. Deliberately narrow: it must
|
|
47
|
+
* be the WHOLE clause and the value must be quoted, so an ordinary question
|
|
48
|
+
* that happens to contain a colon is untouched.
|
|
49
|
+
*/
|
|
50
|
+
const ANNOTATION_CLAUSE = /^\s*[A-Za-z][A-Za-z ]{0,24}:\s*["“'‘][^"”'’]*["”'’]\s*$/;
|
|
51
|
+
export function splitAnalyticalTasks(question) {
|
|
52
|
+
// The separator belongs to the SPLIT, not to the clause. Carrying it through
|
|
53
|
+
// produced a child task whose question was literally
|
|
54
|
+
// `" then "What customer type is Wesley Jenkins` — quote, connector and all —
|
|
55
|
+
// which then failed to resolve and surfaced that punctuation to the reader as
|
|
56
|
+
// the task title.
|
|
57
|
+
const leadingJunk = /^(?:[\s"'“”‘’,:;.\-]+|\b(?:then|and|also)\b)+/i;
|
|
58
|
+
const trailingJunk = /[\s"'“”‘’,:;.\-]+$/;
|
|
59
|
+
const raw = question
|
|
60
|
+
.split(/\s*(?:\?|;|\band then\b|\balso\b)\s*/i)
|
|
61
|
+
.flatMap((part) => part.split(/\s+\band\s+(?=(?:what|who|which|show|list|tell|give|how|why)\b)/i));
|
|
62
|
+
// A `Label: "value"` clause is an ANNOTATION, not a question. The composer
|
|
63
|
+
// appends `Regarding: "<selected row>"` when the reader follows up on
|
|
64
|
+
// something they clicked, and splitting on the `?` before it turned that
|
|
65
|
+
// referent into a task of its own — titled `Regarding: "Mr. Matthew Meyer`,
|
|
66
|
+
// which then "answered" by computing an unrelated maximum over the rows still
|
|
67
|
+
// on screen. Context says WHO the real task is about; it is never a task.
|
|
68
|
+
// Filtered before the junk strip, which would unbalance the quotes.
|
|
69
|
+
const asked = raw.filter((part) => !ANNOTATION_CLAUSE.test(part));
|
|
70
|
+
const parts = (asked.length > 0 ? asked : raw)
|
|
71
|
+
.map((part) => part.replace(leadingJunk, '').replace(trailingJunk, '').trim())
|
|
72
|
+
.filter(Boolean);
|
|
73
|
+
return parts.length > 0 ? parts : [question.trim()];
|
|
74
|
+
}
|
|
75
|
+
export function buildAnalyticalTaskGraph(input) {
|
|
76
|
+
const rootKind = input.mode === 'research' ? 'research' : inferAnalyticalTurnKind(input.question);
|
|
77
|
+
// A research turn may later create bounded evidence branches, but that is a
|
|
78
|
+
// research planner's job. Splitting at ingress loses the surrounding story
|
|
79
|
+
// before it has an opportunity to reason about it.
|
|
80
|
+
const clauses = (rootKind === 'research' ? [input.question.trim()] : splitAnalyticalTasks(input.question))
|
|
81
|
+
.slice(0, Math.max(1, Math.min(6, input.maxTasks ?? 6)));
|
|
82
|
+
const candidateIds = [...new Set((input.candidateIds ?? []).filter((id) => id.trim()))];
|
|
83
|
+
const metrics = [...new Set((input.metrics ?? []).filter((metric) => metric.trim()))];
|
|
84
|
+
const dimensions = [...new Set((input.dimensions ?? []).filter((dimension) => dimension.trim()))];
|
|
85
|
+
const filters = input.filters ?? [];
|
|
86
|
+
const inheritedBindings = input.inheritedBindings ?? [];
|
|
87
|
+
const unboundTasks = clauses.map((clause, index) => {
|
|
88
|
+
const kind = rootKind === 'research' ? 'research' : inferAnalyticalTurnKind(clause);
|
|
89
|
+
const research = kind === 'research' || kind === 'diagnosis';
|
|
90
|
+
const taskKind = research
|
|
91
|
+
? 'research_branch'
|
|
92
|
+
: kind === 'lookup'
|
|
93
|
+
? 'attribute_lookup'
|
|
94
|
+
: kind === 'breakdown'
|
|
95
|
+
? 'breakdown'
|
|
96
|
+
: kind === 'comparison'
|
|
97
|
+
? 'comparison'
|
|
98
|
+
: kind === 'ranking'
|
|
99
|
+
? 'ranking'
|
|
100
|
+
: kind === 'definition'
|
|
101
|
+
? 'definition'
|
|
102
|
+
: 'aggregation';
|
|
103
|
+
return {
|
|
104
|
+
version: 1,
|
|
105
|
+
id: `task-${index + 1}`,
|
|
106
|
+
kind: taskKind,
|
|
107
|
+
question: clause,
|
|
108
|
+
dependencies: index === 0 ? [] : [],
|
|
109
|
+
output: {
|
|
110
|
+
metrics,
|
|
111
|
+
dimensions,
|
|
112
|
+
filters,
|
|
113
|
+
...(kind === 'ranking' ? { order: 'desc' } : {}),
|
|
114
|
+
},
|
|
115
|
+
status: 'planned',
|
|
116
|
+
candidateIds,
|
|
117
|
+
inheritedBindings,
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
const tasks = bindTopRankedRegionDependencies(unboundTasks);
|
|
121
|
+
return {
|
|
122
|
+
kind: rootKind === 'research' ? 'research' : tasks.length > 1 ? 'compound' : rootKind,
|
|
123
|
+
tasks,
|
|
124
|
+
partial: false,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const TOP_RANKED_REGION_RE = /(?:\b(?:top|highest|most)\b[^?.!]{0,72}\bregions?\b|\bregions?\b[^?.!]{0,72}\b(?:top|highest|most)\b)/i;
|
|
128
|
+
const DEPENDENT_REGION_CUSTOMERS_RE = /\b(?:that|this|same)\s+region\b/i;
|
|
129
|
+
/**
|
|
130
|
+
* Recognise only the demonstrated two-step dependency. Broader pronoun
|
|
131
|
+
* resolution belongs to the normal conversation layer; turning every compound
|
|
132
|
+
* question into a dependency would serialise unrelated work and invent filters.
|
|
133
|
+
*/
|
|
134
|
+
function bindTopRankedRegionDependencies(tasks) {
|
|
135
|
+
return tasks.map((task, index) => {
|
|
136
|
+
if (!DEPENDENT_REGION_CUSTOMERS_RE.test(task.question) || !/\bcustomers?\b/i.test(task.question))
|
|
137
|
+
return task;
|
|
138
|
+
const parent = tasks.slice(0, index).reverse().find((candidate) => TOP_RANKED_REGION_RE.test(candidate.question));
|
|
139
|
+
if (!parent)
|
|
140
|
+
return task;
|
|
141
|
+
const dependency = {
|
|
142
|
+
version: 1,
|
|
143
|
+
kind: 'top_ranked_region',
|
|
144
|
+
sourceTaskId: parent.id,
|
|
145
|
+
targetDimension: 'region',
|
|
146
|
+
};
|
|
147
|
+
return { ...task, dependencies: [parent.id], dependency };
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
export function buildAnalyticalTurnPlan(input) {
|
|
151
|
+
const graph = buildAnalyticalTaskGraph(input);
|
|
152
|
+
const zeroCall = input.zeroCallReason === 'explicit_binding'
|
|
153
|
+
|| input.zeroCallReason === 'conversation_only'
|
|
154
|
+
|| input.zeroCallReason === 'frozen_research_child';
|
|
155
|
+
return {
|
|
156
|
+
version: 1,
|
|
157
|
+
...(input.turnId ? { turnId: input.turnId } : {}),
|
|
158
|
+
question: input.question,
|
|
159
|
+
kind: graph.kind,
|
|
160
|
+
meaningCallBudget: zeroCall ? 0 : 1,
|
|
161
|
+
meaningCallReason: input.zeroCallReason ?? 'candidate_interpretation',
|
|
162
|
+
...(input.snapshotId ? { snapshotId: input.snapshotId } : {}),
|
|
163
|
+
...(input.sourceFingerprint ? { sourceFingerprint: input.sourceFingerprint } : {}),
|
|
164
|
+
taskIds: graph.tasks.map((task) => task.id),
|
|
165
|
+
tasks: graph.tasks,
|
|
166
|
+
authorityOrder: ['certified', 'semantic', 'governed_relational', 'generated'],
|
|
167
|
+
frozen: input.frozen === true,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
export function summarizeTaskOutcomes(tasks) {
|
|
171
|
+
const completed = tasks.filter((task) => task.status === 'completed').map((task) => task.id);
|
|
172
|
+
const gaps = tasks.filter((task) => task.status === 'gap' || task.status === 'blocked').map((task) => task.id);
|
|
173
|
+
const status = completed.length === tasks.length && tasks.length > 0
|
|
174
|
+
? 'completed'
|
|
175
|
+
: completed.length > 0
|
|
176
|
+
? 'partial'
|
|
177
|
+
: gaps.some((id) => tasks.find((task) => task.id === id)?.status === 'blocked')
|
|
178
|
+
? 'blocked'
|
|
179
|
+
: 'gap';
|
|
180
|
+
return { status, completed, gaps };
|
|
181
|
+
}
|
|
182
|
+
/** Stable scalar transport for a selected canonical result cell. */
|
|
183
|
+
export function canonicalResultBindingValue(value) {
|
|
184
|
+
if (typeof value === 'string')
|
|
185
|
+
return value;
|
|
186
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
187
|
+
return String(value);
|
|
188
|
+
if (typeof value === 'boolean')
|
|
189
|
+
return String(value);
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
/** A row proof includes all canonical columns, not just the selected cell. */
|
|
193
|
+
export function canonicalResultRowFingerprint(result, row) {
|
|
194
|
+
return stableFingerprint({
|
|
195
|
+
columns: result.columns,
|
|
196
|
+
row: Object.fromEntries(result.columns.map((column) => [column, row[column]])),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Validate an untrusted selected-result reference against a persisted
|
|
201
|
+
* canonical result. The source run/artifact identities are checked by the
|
|
202
|
+
* host before calling this pure result-level validator.
|
|
203
|
+
*/
|
|
204
|
+
export function validateSelectedResultBinding(binding, result) {
|
|
205
|
+
if (!binding
|
|
206
|
+
|| binding.version !== 1
|
|
207
|
+
|| !binding.sourceRunId.trim()
|
|
208
|
+
|| !binding.sourceArtifactId.trim()
|
|
209
|
+
|| !binding.canonicalColumn.trim()
|
|
210
|
+
|| !binding.value.trim()
|
|
211
|
+
|| !normalizeAnalyticalExecutionFingerprint(binding.rowFingerprint)
|
|
212
|
+
|| !normalizeAnalyticalExecutionFingerprint(binding.resultFingerprint)) {
|
|
213
|
+
return {
|
|
214
|
+
ok: false,
|
|
215
|
+
code: 'RESULT_BINDING_INVALID',
|
|
216
|
+
message: 'The selected result reference is incomplete or malformed.',
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (!result || binding.resultFingerprint !== result.resultFingerprint) {
|
|
220
|
+
return {
|
|
221
|
+
ok: false,
|
|
222
|
+
code: 'RESULT_BINDING_RESULT_MISMATCH',
|
|
223
|
+
message: 'The selected result is no longer the persisted result for this run.',
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
if (!result.columns.includes(binding.canonicalColumn)) {
|
|
227
|
+
return {
|
|
228
|
+
ok: false,
|
|
229
|
+
code: 'RESULT_BINDING_ROW_MISMATCH',
|
|
230
|
+
message: `The selected column ${binding.canonicalColumn} is not present in the persisted result.`,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
const matched = result.rows.some((row) => canonicalResultRowFingerprint(result, row) === binding.rowFingerprint
|
|
234
|
+
&& canonicalResultBindingValue(row[binding.canonicalColumn]) === binding.value);
|
|
235
|
+
if (!matched) {
|
|
236
|
+
return {
|
|
237
|
+
ok: false,
|
|
238
|
+
code: 'RESULT_BINDING_ROW_MISMATCH',
|
|
239
|
+
message: 'The selected row/value does not match the persisted result.',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return { ok: true, binding: { ...binding, resultFingerprint: result.resultFingerprint } };
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Derive the one value a `top region -> customers in that region` child may
|
|
246
|
+
* consume. A first row alone is never proof. The parent must either return an
|
|
247
|
+
* explicit rank, or be the server-computed descending ranking task and return
|
|
248
|
+
* at least two rows with one strictly-leading numeric measure. `rowCount` is
|
|
249
|
+
* the returned-row contract, not proof that a singleton is the complete group
|
|
250
|
+
* set. Ties and ambiguous result shapes remain a typed child gap.
|
|
251
|
+
*/
|
|
252
|
+
export function resolveTopRankedRegionDependency(sourceTaskId, result, parentTask) {
|
|
253
|
+
if (!result || result.rows.length === 0) {
|
|
254
|
+
return {
|
|
255
|
+
ok: false,
|
|
256
|
+
code: 'RESULT_CONTRACT_MISMATCH',
|
|
257
|
+
message: 'The top-region task did not produce a canonical result that can bind the dependent customer task.',
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const canonicalResultFingerprint = normalizeAnalyticalExecutionFingerprint(result.resultFingerprint);
|
|
261
|
+
const executionReceipt = normalizeAnalyticalExecutionReceipt(result.executionReceipt);
|
|
262
|
+
if (!executionReceipt) {
|
|
263
|
+
return {
|
|
264
|
+
ok: false,
|
|
265
|
+
code: 'RESULT_CONTRACT_MISMATCH',
|
|
266
|
+
message: 'The top-region result did not retain a complete normalized execution receipt, so the dependent customer task was not run.',
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
if (!canonicalResultFingerprint
|
|
270
|
+
|| result.resultFingerprint !== canonicalResultFingerprint
|
|
271
|
+
|| executionReceipt.resultFingerprint !== canonicalResultFingerprint) {
|
|
272
|
+
return {
|
|
273
|
+
ok: false,
|
|
274
|
+
code: 'RESULT_CONTRACT_MISMATCH',
|
|
275
|
+
message: 'The top-region execution receipt does not match the canonical result, so the dependent customer task was not run.',
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
const regionColumns = result.columns.filter((column) => /(?:^|_)region(?:_name)?$/i.test(column));
|
|
279
|
+
if (regionColumns.length !== 1) {
|
|
280
|
+
return {
|
|
281
|
+
ok: false,
|
|
282
|
+
code: 'RESULT_CONTRACT_MISMATCH',
|
|
283
|
+
message: 'The top-region result did not contain exactly one canonical region column.',
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
const canonicalColumn = regionColumns[0];
|
|
287
|
+
const first = result.rows[0];
|
|
288
|
+
const value = canonicalResultBindingValue(first[canonicalColumn]);
|
|
289
|
+
if (!value) {
|
|
290
|
+
return {
|
|
291
|
+
ok: false,
|
|
292
|
+
code: 'RESULT_CONTRACT_MISMATCH',
|
|
293
|
+
message: 'The leading top-region row did not contain a usable region value.',
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
if (!hasUnambiguousTopRow(result, parentTask)) {
|
|
297
|
+
return {
|
|
298
|
+
ok: false,
|
|
299
|
+
code: 'RESULT_CONTRACT_MISMATCH',
|
|
300
|
+
message: 'The top-region result did not prove a single leading region, so the dependent customer task was not run.',
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
ok: true,
|
|
305
|
+
binding: {
|
|
306
|
+
version: 1,
|
|
307
|
+
sourceTaskId,
|
|
308
|
+
sourceResultFingerprint: canonicalResultFingerprint,
|
|
309
|
+
canonicalColumn,
|
|
310
|
+
value,
|
|
311
|
+
rowFingerprint: canonicalResultRowFingerprint(result, first),
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function hasUnambiguousTopRow(result, parentTask) {
|
|
316
|
+
const rankColumn = result.columns.find((column) => /(?:^|_)(?:rank|row_number)$/i.test(column));
|
|
317
|
+
if (rankColumn) {
|
|
318
|
+
const ranks = result.rows.map((row) => numericCell(row[rankColumn]));
|
|
319
|
+
if (ranks[0] === 1 && ranks.slice(1).every((rank) => rank === undefined || rank > 1))
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
// A plain numerical result column does not say that its first row was ranked.
|
|
323
|
+
// It becomes a ranking proof only when the server's own parent task explicitly
|
|
324
|
+
// asked for a descending ranking AND the returned rows demonstrate a strictly
|
|
325
|
+
// leading value. A singleton needs an explicit rank = 1: it cannot establish
|
|
326
|
+
// that unreturned groups are lower.
|
|
327
|
+
if (parentTask?.kind !== 'ranking' || parentTask.output.order !== 'desc')
|
|
328
|
+
return false;
|
|
329
|
+
if (result.rows.length < 2)
|
|
330
|
+
return false;
|
|
331
|
+
const measures = result.columns.filter((column) => {
|
|
332
|
+
if (column === rankColumn)
|
|
333
|
+
return false;
|
|
334
|
+
const values = result.rows.map((row) => numericCell(row[column]));
|
|
335
|
+
return values.every((value) => value !== undefined);
|
|
336
|
+
});
|
|
337
|
+
if (measures.length !== 1)
|
|
338
|
+
return false;
|
|
339
|
+
const values = result.rows.map((row) => numericCell(row[measures[0]]));
|
|
340
|
+
return values.slice(1).every((value) => values[0] > value);
|
|
341
|
+
}
|
|
342
|
+
function numericCell(value) {
|
|
343
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
344
|
+
return value;
|
|
345
|
+
if (typeof value === 'string' && value.trim() && Number.isFinite(Number(value)))
|
|
346
|
+
return Number(value);
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Normalize connector, MetricFlow, and provider result shapes at one boundary.
|
|
351
|
+
* Connectors may return `ColumnMeta[]` and rows as arrays; UI surfaces should
|
|
352
|
+
* never need to guess how to index those rows.
|
|
353
|
+
*/
|
|
354
|
+
export function normalizeCanonicalQueryResult(input) {
|
|
355
|
+
const columns = Array.isArray(input.columns)
|
|
356
|
+
? input.columns.map(columnName)
|
|
357
|
+
: [];
|
|
358
|
+
const rawRows = Array.isArray(input.rows) ? input.rows : [];
|
|
359
|
+
const inferredColumns = columns.length > 0
|
|
360
|
+
? columns
|
|
361
|
+
: objectRowColumns(rawRows).length > 0
|
|
362
|
+
? objectRowColumns(rawRows)
|
|
363
|
+
: firstArrayRow(rawRows)
|
|
364
|
+
? firstArrayRow(rawRows).map((_, index) => `column_${index + 1}`)
|
|
365
|
+
: [];
|
|
366
|
+
const rows = rawRows.map((row) => normalizeRow(row, inferredColumns));
|
|
367
|
+
const rowCount = typeof input.rowCount === 'number' && Number.isFinite(input.rowCount)
|
|
368
|
+
? Math.max(0, Math.trunc(input.rowCount))
|
|
369
|
+
: rows.length;
|
|
370
|
+
const executionTime = typeof input.executionTimeMs === 'number'
|
|
371
|
+
? input.executionTimeMs
|
|
372
|
+
: typeof input.executionTime === 'number'
|
|
373
|
+
? input.executionTime
|
|
374
|
+
: undefined;
|
|
375
|
+
const canonical = {
|
|
376
|
+
version: 1,
|
|
377
|
+
columns: inferredColumns,
|
|
378
|
+
rows,
|
|
379
|
+
rowCount,
|
|
380
|
+
...(executionTime !== undefined ? { executionTime } : {}),
|
|
381
|
+
...(input.truncated === true ? { truncated: true } : {}),
|
|
382
|
+
};
|
|
383
|
+
const receipt = input.executionReceipt && typeof input.executionReceipt === 'object'
|
|
384
|
+
? input.executionReceipt
|
|
385
|
+
: undefined;
|
|
386
|
+
const receiptFingerprint = typeof receipt?.resultFingerprint === 'string' ? receipt.resultFingerprint : undefined;
|
|
387
|
+
const suppliedFingerprint = typeof input.resultFingerprint === 'string' && input.resultFingerprint.trim()
|
|
388
|
+
? input.resultFingerprint.trim()
|
|
389
|
+
: receiptFingerprint;
|
|
390
|
+
const trustState = input.trustState === 'certified'
|
|
391
|
+
|| input.trustState === 'governed'
|
|
392
|
+
|| input.trustState === 'review_required'
|
|
393
|
+
|| input.trustState === 'not_applicable'
|
|
394
|
+
|| input.trustState === 'blocked'
|
|
395
|
+
? input.trustState
|
|
396
|
+
: undefined;
|
|
397
|
+
return {
|
|
398
|
+
...canonical,
|
|
399
|
+
...(receipt ? { executionReceipt: receipt } : {}),
|
|
400
|
+
...(trustState ? { trustState } : {}),
|
|
401
|
+
...(typeof input.answerTier === 'string' && input.answerTier.trim()
|
|
402
|
+
? { answerTier: input.answerTier.trim() }
|
|
403
|
+
: {}),
|
|
404
|
+
// A connector/execution receipt is authoritative. The local digest is only
|
|
405
|
+
// a backwards-compatible fallback for legacy unreceipted rows.
|
|
406
|
+
resultFingerprint: suppliedFingerprint ?? stableFingerprint(canonical),
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
export function canonicalResultRows(result) {
|
|
410
|
+
return result.rows.map((row) => result.columns.map((column) => row[column]));
|
|
411
|
+
}
|
|
412
|
+
export function assertCanonicalResult(result) {
|
|
413
|
+
if (result.version !== 1)
|
|
414
|
+
throw new Error('Unsupported analytical result contract version.');
|
|
415
|
+
if (result.rowCount < result.rows.length)
|
|
416
|
+
throw new Error('Result rowCount cannot be smaller than the returned rows.');
|
|
417
|
+
if (new Set(result.columns).size !== result.columns.length)
|
|
418
|
+
throw new Error('Result columns must be unique.');
|
|
419
|
+
for (const row of result.rows) {
|
|
420
|
+
for (const column of result.columns) {
|
|
421
|
+
if (!Object.prototype.hasOwnProperty.call(row, column)) {
|
|
422
|
+
throw new Error(`Result row is missing the declared column ${column}.`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
/** Reciprocal-rank fusion keeps recall across lexical, vector, and graph lanes. */
|
|
428
|
+
export function fuseContextCandidates(lanes, limit = 32) {
|
|
429
|
+
const safeLimit = Math.max(1, Math.min(100, Math.trunc(limit)));
|
|
430
|
+
const byId = new Map();
|
|
431
|
+
const diagnostics = { lanes: {}, selectedIds: [], truncated: false };
|
|
432
|
+
for (const [lane, cards] of Object.entries(lanes)) {
|
|
433
|
+
diagnostics.lanes[lane] = { returned: cards.length };
|
|
434
|
+
cards.forEach((card, index) => {
|
|
435
|
+
if (!card.id.trim())
|
|
436
|
+
return;
|
|
437
|
+
const score = 1 / (60 + index + 1) + Math.max(0, Math.min(1, card.relevance)) * 0.25;
|
|
438
|
+
const existing = byId.get(card.id);
|
|
439
|
+
if (existing) {
|
|
440
|
+
existing.score += score;
|
|
441
|
+
existing.lanes.add(lane);
|
|
442
|
+
if ((card.relevance ?? 0) > existing.relevance)
|
|
443
|
+
existing.relevance = card.relevance;
|
|
444
|
+
if (card.compatible === true)
|
|
445
|
+
existing.compatible = true;
|
|
446
|
+
if (!existing.summary && card.summary)
|
|
447
|
+
existing.summary = card.summary;
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
byId.set(card.id, { ...card, score, lanes: new Set([lane]) });
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
const selected = [...byId.values()]
|
|
455
|
+
.sort((left, right) => right.score - left.score || right.relevance - left.relevance || left.id.localeCompare(right.id))
|
|
456
|
+
.slice(0, safeLimit)
|
|
457
|
+
.map(({ score: _score, lanes: _lanes, ...card }) => card);
|
|
458
|
+
diagnostics.selectedIds = selected.map((card) => card.id);
|
|
459
|
+
diagnostics.truncated = byId.size > selected.length;
|
|
460
|
+
return { candidates: selected, diagnostics };
|
|
461
|
+
}
|
|
462
|
+
export async function retrieveContextLanes(lanes, limit = 32, maxConcurrent = 4) {
|
|
463
|
+
const entries = Object.entries(lanes);
|
|
464
|
+
const concurrency = Math.max(1, Math.min(8, Math.trunc(maxConcurrent) || 1));
|
|
465
|
+
const settled = [];
|
|
466
|
+
let nextIndex = 0;
|
|
467
|
+
const worker = async () => {
|
|
468
|
+
for (;;) {
|
|
469
|
+
const index = nextIndex;
|
|
470
|
+
nextIndex += 1;
|
|
471
|
+
const entry = entries[index];
|
|
472
|
+
if (!entry)
|
|
473
|
+
return;
|
|
474
|
+
const [name, retrieve] = entry;
|
|
475
|
+
const startedAt = Date.now();
|
|
476
|
+
try {
|
|
477
|
+
const cards = await retrieve();
|
|
478
|
+
settled[index] = [name, cards, Date.now() - startedAt];
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
settled[index] = [name, { error: error instanceof Error ? error.message : String(error) }, Date.now() - startedAt];
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, entries.length) }, () => worker()));
|
|
486
|
+
const successful = {};
|
|
487
|
+
const errors = {};
|
|
488
|
+
const durations = {};
|
|
489
|
+
for (const [name, result, durationMs] of settled) {
|
|
490
|
+
durations[name] = durationMs;
|
|
491
|
+
if (Array.isArray(result))
|
|
492
|
+
successful[name] = result;
|
|
493
|
+
else
|
|
494
|
+
errors[name] = result.error;
|
|
495
|
+
}
|
|
496
|
+
const fused = fuseContextCandidates(successful, limit);
|
|
497
|
+
for (const [name, cards] of Object.entries(successful)) {
|
|
498
|
+
fused.diagnostics.lanes[name] = {
|
|
499
|
+
returned: cards.length,
|
|
500
|
+
durationMs: durations[name],
|
|
501
|
+
status: cards.length > 0 ? 'ok' : 'empty',
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
for (const [name, error] of Object.entries(errors)) {
|
|
505
|
+
fused.diagnostics.lanes[name] = {
|
|
506
|
+
returned: 0,
|
|
507
|
+
durationMs: durations[name],
|
|
508
|
+
status: 'error',
|
|
509
|
+
error,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
return fused;
|
|
513
|
+
}
|
|
514
|
+
export function capResearchBranches(branches, max = 6) {
|
|
515
|
+
return branches.slice(0, Math.max(1, Math.min(6, Math.trunc(max))));
|
|
516
|
+
}
|
|
517
|
+
export function buildResearchEvidenceLedger(input) {
|
|
518
|
+
const entries = input.entries.slice(0, 6).map((entry) => {
|
|
519
|
+
const resultFingerprint = normalizeAnalyticalExecutionFingerprint(entry.resultFingerprint);
|
|
520
|
+
const executionReceipt = normalizeAnalyticalExecutionReceipt(entry.executionReceipt);
|
|
521
|
+
const receiptFingerprint = executionReceipt?.resultFingerprint;
|
|
522
|
+
const listedFingerprint = entry.receipts
|
|
523
|
+
.map((receipt) => normalizeAnalyticalExecutionFingerprint(receipt))
|
|
524
|
+
.find((receipt) => Boolean(receipt));
|
|
525
|
+
const executionProof = resultFingerprint ?? receiptFingerprint ?? listedFingerprint;
|
|
526
|
+
// A receipt/result proof is meaningful only for an observed branch. Never
|
|
527
|
+
// carry a preloaded receipt, child ID, context-pack ID, or malformed
|
|
528
|
+
// fingerprint through a failed/cancelled/skipped entry.
|
|
529
|
+
if (entry.status !== 'observed') {
|
|
530
|
+
const { executionReceipt: _receipt, resultFingerprint: _fingerprint, ...withoutProof } = entry;
|
|
531
|
+
return { ...withoutProof, receipts: [] };
|
|
532
|
+
}
|
|
533
|
+
// A ready/observed branch without a complete receipt or canonical result
|
|
534
|
+
// fingerprint is not an observation. Downgrade it and retain no invented
|
|
535
|
+
// proof; callers can still inspect the branch and retry it explicitly.
|
|
536
|
+
if (!executionProof) {
|
|
537
|
+
const { executionReceipt: _receipt, resultFingerprint: _fingerprint, ...withoutProof } = entry;
|
|
538
|
+
return {
|
|
539
|
+
...withoutProof,
|
|
540
|
+
status: 'failed',
|
|
541
|
+
receipts: [],
|
|
542
|
+
error: entry.error ?? 'Research branch had no valid execution receipt or canonical result fingerprint.',
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
return {
|
|
546
|
+
...entry,
|
|
547
|
+
status: 'observed',
|
|
548
|
+
resultFingerprint: executionProof,
|
|
549
|
+
...(executionReceipt ? { executionReceipt } : {}),
|
|
550
|
+
receipts: [executionProof],
|
|
551
|
+
};
|
|
552
|
+
});
|
|
553
|
+
return {
|
|
554
|
+
version: 1,
|
|
555
|
+
rootQuestion: input.rootQuestion,
|
|
556
|
+
...(input.planId ? { planId: input.planId } : {}),
|
|
557
|
+
...(input.snapshotId ? { snapshotId: input.snapshotId } : {}),
|
|
558
|
+
entries,
|
|
559
|
+
factIds: [...new Set(entries.flatMap((entry) => entry.facts))],
|
|
560
|
+
stoppingReason: input.stoppingReason ?? (entries.length > 0 ? 'completed' : 'not_started'),
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
/** The only accepted host-side execution identity is a SHA-256 fingerprint. */
|
|
564
|
+
export function normalizeAnalyticalExecutionFingerprint(value) {
|
|
565
|
+
return typeof value === 'string' && /^[a-f0-9]{64}$/i.test(value.trim())
|
|
566
|
+
? value.trim().toLowerCase()
|
|
567
|
+
: undefined;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Normalize a complete DQL execution receipt. A partial object or arbitrary
|
|
571
|
+
* identifier is deliberately not execution evidence.
|
|
572
|
+
*/
|
|
573
|
+
export function normalizeAnalyticalExecutionReceipt(value) {
|
|
574
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
575
|
+
return undefined;
|
|
576
|
+
const record = value;
|
|
577
|
+
const sourceFingerprint = normalizeAnalyticalExecutionFingerprint(record.sourceFingerprint);
|
|
578
|
+
const compiledSqlFingerprint = normalizeAnalyticalExecutionFingerprint(record.compiledSqlFingerprint);
|
|
579
|
+
const parameterFingerprint = normalizeAnalyticalExecutionFingerprint(record.parameterFingerprint);
|
|
580
|
+
const resultFingerprint = normalizeAnalyticalExecutionFingerprint(record.resultFingerprint);
|
|
581
|
+
return sourceFingerprint && compiledSqlFingerprint && parameterFingerprint && resultFingerprint
|
|
582
|
+
? { sourceFingerprint, compiledSqlFingerprint, parameterFingerprint, resultFingerprint }
|
|
583
|
+
: undefined;
|
|
584
|
+
}
|
|
585
|
+
export function buildCoverageGap(input) {
|
|
586
|
+
return { version: 1, ...input };
|
|
587
|
+
}
|
|
588
|
+
function columnName(value) {
|
|
589
|
+
if (typeof value === 'string')
|
|
590
|
+
return value;
|
|
591
|
+
if (value && typeof value === 'object' && typeof value.name === 'string') {
|
|
592
|
+
return String(value.name);
|
|
593
|
+
}
|
|
594
|
+
return String(value ?? 'column');
|
|
595
|
+
}
|
|
596
|
+
function objectRowColumns(rows) {
|
|
597
|
+
const columns = new Set();
|
|
598
|
+
for (const row of rows) {
|
|
599
|
+
if (!row || typeof row !== 'object' || Array.isArray(row))
|
|
600
|
+
continue;
|
|
601
|
+
for (const column of Object.keys(row))
|
|
602
|
+
columns.add(column);
|
|
603
|
+
}
|
|
604
|
+
return [...columns];
|
|
605
|
+
}
|
|
606
|
+
function firstArrayRow(rows) {
|
|
607
|
+
const row = rows.find((candidate) => Array.isArray(candidate));
|
|
608
|
+
return row;
|
|
609
|
+
}
|
|
610
|
+
function normalizeRow(row, columns) {
|
|
611
|
+
if (Array.isArray(row))
|
|
612
|
+
return Object.fromEntries(columns.map((column, index) => [column, row[index]]));
|
|
613
|
+
if (row && typeof row === 'object') {
|
|
614
|
+
const record = row;
|
|
615
|
+
return Object.fromEntries(columns.map((column) => [column, record[column]]));
|
|
616
|
+
}
|
|
617
|
+
return Object.fromEntries(columns.map((column) => [column, undefined]));
|
|
618
|
+
}
|
|
619
|
+
function stableFingerprint(value) {
|
|
620
|
+
const text = stableStringify(value);
|
|
621
|
+
return createHash('sha256').update(text).digest('hex');
|
|
622
|
+
}
|
|
623
|
+
function stableStringify(value) {
|
|
624
|
+
if (value === null || typeof value !== 'object')
|
|
625
|
+
return JSON.stringify(value);
|
|
626
|
+
if (Array.isArray(value))
|
|
627
|
+
return `[${value.map(stableStringify).join(',')}]`;
|
|
628
|
+
const record = value;
|
|
629
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`).join(',')}}`;
|
|
630
|
+
}
|
|
631
|
+
//# sourceMappingURL=analytical-orchestration.js.map
|