@duckcodeailabs/dql-agent 1.10.0 → 1.10.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.map +1 -1
- package/dist/agent-run-engine.js +6 -1
- package/dist/agent-run-engine.js.map +1 -1
- package/dist/analytical-compatibility.d.ts +61 -0
- package/dist/analytical-compatibility.d.ts.map +1 -0
- package/dist/analytical-compatibility.js +515 -0
- package/dist/analytical-compatibility.js.map +1 -0
- package/dist/analytical-execution-graph.d.ts +174 -0
- package/dist/analytical-execution-graph.d.ts.map +1 -0
- package/dist/analytical-execution-graph.js +599 -0
- package/dist/analytical-execution-graph.js.map +1 -0
- package/dist/analytical-failure-repair.d.ts +91 -0
- package/dist/analytical-failure-repair.d.ts.map +1 -0
- package/dist/analytical-failure-repair.js +325 -0
- package/dist/analytical-failure-repair.js.map +1 -0
- package/dist/analytical-frame.d.ts +19 -0
- package/dist/analytical-frame.d.ts.map +1 -0
- package/dist/analytical-frame.js +299 -0
- package/dist/analytical-frame.js.map +1 -0
- package/dist/analytical-period-resolution.d.ts +53 -0
- package/dist/analytical-period-resolution.d.ts.map +1 -0
- package/dist/analytical-period-resolution.js +218 -0
- package/dist/analytical-period-resolution.js.map +1 -0
- package/dist/analytical-readiness.d.ts +17 -0
- package/dist/analytical-readiness.d.ts.map +1 -0
- package/dist/analytical-readiness.js +95 -0
- package/dist/analytical-readiness.js.map +1 -0
- package/dist/analytical-result-facts.d.ts +79 -0
- package/dist/analytical-result-facts.d.ts.map +1 -0
- package/dist/analytical-result-facts.js +301 -0
- package/dist/analytical-result-facts.js.map +1 -0
- package/dist/answer-loop.d.ts +51 -4
- package/dist/answer-loop.d.ts.map +1 -1
- package/dist/answer-loop.js +866 -35
- package/dist/answer-loop.js.map +1 -1
- package/dist/governed-relational-compiler.d.ts +51 -0
- package/dist/governed-relational-compiler.d.ts.map +1 -1
- package/dist/governed-relational-compiler.js +144 -1
- package/dist/governed-relational-compiler.js.map +1 -1
- package/dist/index.d.ts +16 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/kg/build.d.ts +2 -2
- package/dist/kg/build.d.ts.map +1 -1
- package/dist/kg/build.js +250 -10
- package/dist/kg/build.js.map +1 -1
- package/dist/meaning-resolution.d.ts +13 -0
- package/dist/meaning-resolution.d.ts.map +1 -1
- package/dist/meaning-resolution.js +69 -0
- package/dist/meaning-resolution.js.map +1 -1
- package/dist/metadata/analysis-planner.js +3 -1
- package/dist/metadata/analysis-planner.js.map +1 -1
- package/dist/metadata/catalog.d.ts +4 -2
- package/dist/metadata/catalog.d.ts.map +1 -1
- package/dist/metadata/catalog.js +227 -9
- package/dist/metadata/catalog.js.map +1 -1
- package/dist/metadata/meaning-evidence.d.ts +9 -2
- package/dist/metadata/meaning-evidence.d.ts.map +1 -1
- package/dist/metadata/meaning-evidence.js +105 -7
- package/dist/metadata/meaning-evidence.js.map +1 -1
- package/dist/plan-execution-adapter.d.ts +72 -1
- package/dist/plan-execution-adapter.d.ts.map +1 -1
- package/dist/plan-execution-adapter.js +208 -0
- package/dist/plan-execution-adapter.js.map +1 -1
- package/dist/resolved-analytical-plan.d.ts +14 -3
- package/dist/resolved-analytical-plan.d.ts.map +1 -1
- package/dist/resolved-analytical-plan.js +74 -20
- package/dist/resolved-analytical-plan.js.map +1 -1
- package/dist/router.d.ts +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +167 -21
- package/dist/router.js.map +1 -1
- package/dist/skills/loader.d.ts +17 -0
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +62 -4
- package/dist/skills/loader.js.map +1 -1
- package/package.json +4 -4
package/dist/metadata/catalog.js
CHANGED
|
@@ -11,10 +11,10 @@ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync
|
|
|
11
11
|
import { createRequire } from 'node:module';
|
|
12
12
|
import { dirname, join } from 'node:path';
|
|
13
13
|
import { brotliCompressSync, brotliDecompressSync, constants as zlibConstants } from 'node:zlib';
|
|
14
|
-
import { buildManifest, buildManifestKnowledgeGraph, loadDomainPackageRegistry, loadManifestKnowledgeSkills, loadProjectConfig, parseContractRef, resolveDataLexManifestPath, resolveDbtManifestPath, resolveSemanticLayerWithDiagnostics, extractColumnLineage, normalizeDqlArtifactReference, composeEffectiveTrust, } from
|
|
15
|
-
import { buildKGFromManifest, buildKGFromSemanticLayer } from
|
|
16
|
-
import { domainContextSearchDomains } from
|
|
17
|
-
import { buildBlockBusinessFingerprint, buildBlockSqlFingerprints } from
|
|
14
|
+
import { buildManifest, buildManifestKnowledgeGraph, loadDomainPackageRegistry, loadManifestKnowledgeSkills, loadProjectConfig, parseContractRef, resolveDataLexManifestPath, resolveDbtManifestPath, resolveSemanticLayerWithDiagnostics, extractColumnLineage, normalizeDqlArtifactReference, composeEffectiveTrust, normalizeMetricCapabilityContract, } from "@duckcodeailabs/dql-core";
|
|
15
|
+
import { buildKGFromManifest, buildKGFromSemanticLayer } from "../kg/build.js";
|
|
16
|
+
import { domainContextSearchDomains, } from "../domain-context.js";
|
|
17
|
+
import { buildBlockBusinessFingerprint, buildBlockSqlFingerprints, } from "./block-fingerprints.js";
|
|
18
18
|
import { buildAnalysisQuestionPlan, certifiedApplicabilityForObject, scoreAllowedSqlRelationWithAnalysisPlan, scoreMetadataObjectWithAnalysisPlan, sortAllowedSqlContextForAnalysisPlan, } from './analysis-planner.js';
|
|
19
19
|
import { extractSimpleSelectShape, sourceSqlShapeColumns } from './sql-shape.js';
|
|
20
20
|
import { grainMatches, requestedGrainFromPlan, } from './grain-gate.js';
|
|
@@ -835,6 +835,7 @@ export function buildMetadataSnapshot(projectRoot, manifest, semanticLayer, skil
|
|
|
835
835
|
addRawDbtManifestCatalogObjects(projectRoot, manifest, objects, edges, diagnostics);
|
|
836
836
|
addBlockDependencyEdges(manifest, edges);
|
|
837
837
|
addBlockOutputLineageObjects(manifest, objects, edges);
|
|
838
|
+
addCertifiedBlockAnalyticalCapabilities(objects);
|
|
838
839
|
// Manifest v3 is the unified DQL runtime. DataLex is migration input only;
|
|
839
840
|
// retaining it here would reintroduce a second analytical source of truth.
|
|
840
841
|
if (manifest.manifestVersion !== 3) {
|
|
@@ -878,6 +879,171 @@ export function buildMetadataSnapshot(projectRoot, manifest, semanticLayer, skil
|
|
|
878
879
|
snapshot.fingerprint = fingerprintSnapshot(snapshot);
|
|
879
880
|
return snapshot;
|
|
880
881
|
}
|
|
882
|
+
/**
|
|
883
|
+
* Upgrade only fully declared certified blocks into RFC 0005 capabilities.
|
|
884
|
+
* Local/display-name matching is intentionally insufficient: every reusable
|
|
885
|
+
* metric, grain, dimension/filter, and output role must bind exactly to the
|
|
886
|
+
* already-normalized semantic capability in this immutable snapshot.
|
|
887
|
+
*
|
|
888
|
+
* Acceptance: CONTRACT-002, AGT-018.
|
|
889
|
+
*/
|
|
890
|
+
function addCertifiedBlockAnalyticalCapabilities(objects) {
|
|
891
|
+
const semanticCapabilities = [...objects.values()].flatMap((object) => {
|
|
892
|
+
if (object.objectType !== "semantic_metric")
|
|
893
|
+
return [];
|
|
894
|
+
const capability = normalizeMetricCapabilityContract(object.payload?.analyticalCapability);
|
|
895
|
+
if (!capability)
|
|
896
|
+
return [];
|
|
897
|
+
const payload = object.payload ?? {};
|
|
898
|
+
return [
|
|
899
|
+
{
|
|
900
|
+
object,
|
|
901
|
+
capability,
|
|
902
|
+
exactRefs: new Set(uniqueNonBlank([
|
|
903
|
+
capability.metricId,
|
|
904
|
+
object.objectKey,
|
|
905
|
+
object.fullName,
|
|
906
|
+
stringValue(payload.qualifiedId),
|
|
907
|
+
stringValue(payload.sourceNativeId),
|
|
908
|
+
...metadataStringArray(payload.aliases),
|
|
909
|
+
])),
|
|
910
|
+
},
|
|
911
|
+
];
|
|
912
|
+
});
|
|
913
|
+
for (const block of objects.values()) {
|
|
914
|
+
if (block.objectType !== "dql_block" || block.status !== "certified")
|
|
915
|
+
continue;
|
|
916
|
+
const payload = block.payload ?? {};
|
|
917
|
+
const metricRefs = uniqueNonBlank([
|
|
918
|
+
...metadataStringArray(payload.metricRefs),
|
|
919
|
+
]);
|
|
920
|
+
if (metricRefs.length !== 1)
|
|
921
|
+
continue;
|
|
922
|
+
const metrics = semanticCapabilities.filter((candidate) => candidate.exactRefs.has(metricRefs[0]));
|
|
923
|
+
if (metrics.length !== 1)
|
|
924
|
+
continue;
|
|
925
|
+
const semantic = metrics[0];
|
|
926
|
+
const grain = stringValue(payload.grain);
|
|
927
|
+
if (!grain || !semantic.capability.resultGrainIds.includes(grain))
|
|
928
|
+
continue;
|
|
929
|
+
const groupedRefs = uniqueNonBlank([
|
|
930
|
+
...metadataStringArray(payload.dimensions),
|
|
931
|
+
...metadataStringArray(payload.dimensionsRef),
|
|
932
|
+
]);
|
|
933
|
+
const filterRefs = uniqueNonBlank(metadataStringArray(payload.allowedFilters));
|
|
934
|
+
const declaredRefs = new Set([...groupedRefs, ...filterRefs]);
|
|
935
|
+
const capabilityDimensionIds = new Set(semantic.capability.dimensions.map((item) => item.dimensionId));
|
|
936
|
+
const capabilityTimeIds = new Set(semantic.capability.timeDimensions.map((item) => item.dimensionId));
|
|
937
|
+
if ([...declaredRefs].some((id) => !capabilityDimensionIds.has(id) && !capabilityTimeIds.has(id)))
|
|
938
|
+
continue;
|
|
939
|
+
const dimensions = semantic.capability.dimensions.flatMap((dimension) => {
|
|
940
|
+
if (!declaredRefs.has(dimension.dimensionId))
|
|
941
|
+
return [];
|
|
942
|
+
const roles = dimension.supportedRoles.filter((role) => (role === "filter" && filterRefs.includes(dimension.dimensionId)) ||
|
|
943
|
+
(role === "group_by" &&
|
|
944
|
+
groupedRefs.includes(dimension.dimensionId)) ||
|
|
945
|
+
(role === "display" &&
|
|
946
|
+
groupedRefs.includes(dimension.dimensionId)) ||
|
|
947
|
+
(role === "rank_entity" &&
|
|
948
|
+
payload.pattern === "ranking" &&
|
|
949
|
+
groupedRefs.includes(dimension.dimensionId)));
|
|
950
|
+
return roles.length > 0
|
|
951
|
+
? [{ ...dimension, supportedRoles: roles }]
|
|
952
|
+
: [];
|
|
953
|
+
});
|
|
954
|
+
if ([...declaredRefs].some((id) => capabilityDimensionIds.has(id) &&
|
|
955
|
+
!dimensions.some((dimension) => dimension.dimensionId === id)))
|
|
956
|
+
continue;
|
|
957
|
+
const timeDimensions = semantic.capability.timeDimensions.filter((dimension) => declaredRefs.has(dimension.dimensionId));
|
|
958
|
+
const outputs = analyticalBlockOutputs(payload.outputContract);
|
|
959
|
+
if (!outputs ||
|
|
960
|
+
outputs.ids.length === 0 ||
|
|
961
|
+
!outputs.kinds.includes("metric_value"))
|
|
962
|
+
continue;
|
|
963
|
+
const operations = [];
|
|
964
|
+
if (filterRefs.length > 0)
|
|
965
|
+
operations.push("filter");
|
|
966
|
+
if (groupedRefs.some((id) => capabilityDimensionIds.has(id)))
|
|
967
|
+
operations.push("group");
|
|
968
|
+
if (payload.pattern === "trend")
|
|
969
|
+
operations.push("trend");
|
|
970
|
+
if (payload.pattern === "ranking" && outputs.kinds.includes("rank"))
|
|
971
|
+
operations.push("rank");
|
|
972
|
+
if (outputs.kinds.includes("delta") ||
|
|
973
|
+
outputs.kinds.includes("percent_delta"))
|
|
974
|
+
operations.push("compare");
|
|
975
|
+
const blockId = stringValue(payload.qualifiedId) ?? block.objectKey;
|
|
976
|
+
const fingerprint = stringValue(recordPayload(payload.businessFingerprint)?.hash) ??
|
|
977
|
+
sha256(stableStringify({
|
|
978
|
+
blockId,
|
|
979
|
+
metricRefs,
|
|
980
|
+
grain,
|
|
981
|
+
groupedRefs,
|
|
982
|
+
filterRefs,
|
|
983
|
+
outputs,
|
|
984
|
+
}));
|
|
985
|
+
const capability = {
|
|
986
|
+
...semantic.capability,
|
|
987
|
+
defaultResultGrainId: grain,
|
|
988
|
+
resultGrainIds: uniqueNonBlank([
|
|
989
|
+
grain,
|
|
990
|
+
...dimensions.map((dimension) => dimension.entityId),
|
|
991
|
+
]),
|
|
992
|
+
dimensions,
|
|
993
|
+
timeDimensions,
|
|
994
|
+
operations: [...new Set(operations)],
|
|
995
|
+
supportedOutputKinds: outputs.kinds,
|
|
996
|
+
declaredOutputIds: outputs.ids,
|
|
997
|
+
executionCapabilities: [
|
|
998
|
+
{ route: "certified", adapterId: block.objectKey },
|
|
999
|
+
],
|
|
1000
|
+
sourceFingerprint: fingerprint.startsWith("sha256:")
|
|
1001
|
+
? fingerprint
|
|
1002
|
+
: `sha256:${fingerprint}`,
|
|
1003
|
+
};
|
|
1004
|
+
const normalized = normalizeMetricCapabilityContract(capability);
|
|
1005
|
+
if (!normalized)
|
|
1006
|
+
continue;
|
|
1007
|
+
objects.set(block.objectKey, {
|
|
1008
|
+
...block,
|
|
1009
|
+
payload: { ...payload, analyticalCapability: normalized },
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
function analyticalBlockOutputs(value) {
|
|
1014
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
1015
|
+
return undefined;
|
|
1016
|
+
const ids = [];
|
|
1017
|
+
const kinds = [];
|
|
1018
|
+
for (const item of value) {
|
|
1019
|
+
const output = recordPayload(item);
|
|
1020
|
+
const id = stringValue(output?.name);
|
|
1021
|
+
const role = stringValue(output?.role)?.toLowerCase();
|
|
1022
|
+
if (!id || !role)
|
|
1023
|
+
return undefined;
|
|
1024
|
+
const kind = role === "metric" || role === "measure" || role === "value"
|
|
1025
|
+
? "metric_value"
|
|
1026
|
+
: role === "dimension" || role === "grain"
|
|
1027
|
+
? "dimension"
|
|
1028
|
+
: role === "rank"
|
|
1029
|
+
? "rank"
|
|
1030
|
+
: role === "delta"
|
|
1031
|
+
? "delta"
|
|
1032
|
+
: role === "percent_delta"
|
|
1033
|
+
? "percent_delta"
|
|
1034
|
+
: undefined;
|
|
1035
|
+
if (!kind)
|
|
1036
|
+
return undefined;
|
|
1037
|
+
ids.push(id);
|
|
1038
|
+
kinds.push(kind);
|
|
1039
|
+
}
|
|
1040
|
+
return { ids: uniqueNonBlank(ids), kinds: [...new Set(kinds)] };
|
|
1041
|
+
}
|
|
1042
|
+
function recordPayload(value) {
|
|
1043
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
1044
|
+
? value
|
|
1045
|
+
: undefined;
|
|
1046
|
+
}
|
|
881
1047
|
/**
|
|
882
1048
|
* Manifest graph v2 intentionally omits verbose objects and edges. Snapshot
|
|
883
1049
|
* construction rematerializes that compiler graph once, then persists the
|
|
@@ -982,8 +1148,16 @@ function addManifestKnowledgeGraph(manifest, objects, edges) {
|
|
|
982
1148
|
sourceSystem: 'DQL compiled cross-domain policy',
|
|
983
1149
|
payload: compactObject(route),
|
|
984
1150
|
});
|
|
985
|
-
addMetadataEdge(edges,
|
|
986
|
-
|
|
1151
|
+
addMetadataEdge(edges, "cross_domain_route", keyByGraphId.get(`domain::${route.providerDomainId}`) ??
|
|
1152
|
+
`domain:${route.providerDomainId}`, objectKey, {
|
|
1153
|
+
state: route.state,
|
|
1154
|
+
reasonCodes: route.reasonCodes,
|
|
1155
|
+
});
|
|
1156
|
+
addMetadataEdge(edges, "cross_domain_route", objectKey, keyByGraphId.get(`domain::${route.consumerDomainId}`) ??
|
|
1157
|
+
`domain:${route.consumerDomainId}`, {
|
|
1158
|
+
state: route.state,
|
|
1159
|
+
reasonCodes: route.reasonCodes,
|
|
1160
|
+
});
|
|
987
1161
|
}
|
|
988
1162
|
for (const edge of graph.edges ?? []) {
|
|
989
1163
|
const fromKey = keyByGraphId.get(edge.from) ?? edge.from;
|
|
@@ -2407,7 +2581,8 @@ function addSkillObjects(skills, objects, edges) {
|
|
|
2407
2581
|
domain: skill.domain,
|
|
2408
2582
|
domains: skill.domains ?? [],
|
|
2409
2583
|
modelAreaRefs: skill.modelAreaRefs ?? [],
|
|
2410
|
-
status: skill.status ??
|
|
2584
|
+
status: skill.status ?? "active",
|
|
2585
|
+
analyticalPolicy: skill.analyticalPolicy,
|
|
2411
2586
|
bodyHash,
|
|
2412
2587
|
}));
|
|
2413
2588
|
const objectKey = `skill:${identity}`;
|
|
@@ -2442,6 +2617,7 @@ function addSkillObjects(skills, objects, edges) {
|
|
|
2442
2617
|
examples: skill.examples ?? [],
|
|
2443
2618
|
sourceRefs: skill.sourceRefs ?? [],
|
|
2444
2619
|
vocabulary: skill.vocabulary,
|
|
2620
|
+
analyticalPolicy: skill.analyticalPolicy,
|
|
2445
2621
|
bodyHash,
|
|
2446
2622
|
sourceFingerprint,
|
|
2447
2623
|
isStarter: skill.isStarter,
|
|
@@ -6260,13 +6436,22 @@ function skillFromMetadataObject(object) {
|
|
|
6260
6436
|
examples: stringArrayPayload(payload.examples),
|
|
6261
6437
|
sourceRefs: stringArrayPayload(payload.sourceRefs),
|
|
6262
6438
|
vocabulary: stringRecordPayload(payload.vocabulary),
|
|
6263
|
-
|
|
6264
|
-
|
|
6439
|
+
analyticalPolicy: skillAnalyticalPolicyPayload(payload.analyticalPolicy),
|
|
6440
|
+
body: "",
|
|
6441
|
+
sourcePath: object.sourcePath ?? "",
|
|
6265
6442
|
isStarter: payload.isStarter === true,
|
|
6266
6443
|
};
|
|
6267
6444
|
}
|
|
6268
6445
|
function localContextSkillFromParsed(skill, object) {
|
|
6269
6446
|
const guidance = skill.body.slice(0, 4_000);
|
|
6447
|
+
const sourceHash = stringPayload(object.payload?.sourceFingerprint);
|
|
6448
|
+
const policy = skill.analyticalPolicy && sourceHash
|
|
6449
|
+
? {
|
|
6450
|
+
policyId: `${skill.qualifiedId ?? skill.id}#analytical`,
|
|
6451
|
+
sourceHash,
|
|
6452
|
+
...skill.analyticalPolicy,
|
|
6453
|
+
}
|
|
6454
|
+
: undefined;
|
|
6270
6455
|
return {
|
|
6271
6456
|
objectKey: object.objectKey,
|
|
6272
6457
|
id: skill.id,
|
|
@@ -6286,6 +6471,7 @@ function localContextSkillFromParsed(skill, object) {
|
|
|
6286
6471
|
requiredFilters: [...(skill.requiredFilters ?? [])],
|
|
6287
6472
|
clarifyWhen: [...(skill.clarifyWhen ?? [])],
|
|
6288
6473
|
vocabulary: { ...skill.vocabulary },
|
|
6474
|
+
...(policy ? { analyticalPolicy: policy } : {}),
|
|
6289
6475
|
guidance,
|
|
6290
6476
|
guidanceTruncated: guidance.length < skill.body.length,
|
|
6291
6477
|
sourceRefs: [...(skill.sourceRefs ?? [])],
|
|
@@ -6293,6 +6479,38 @@ function localContextSkillFromParsed(skill, object) {
|
|
|
6293
6479
|
sourcePath: object.sourcePath,
|
|
6294
6480
|
};
|
|
6295
6481
|
}
|
|
6482
|
+
function skillAnalyticalPolicyPayload(value) {
|
|
6483
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
6484
|
+
return undefined;
|
|
6485
|
+
const record = value;
|
|
6486
|
+
const completenessPolicy = stringPayload(record.completenessPolicy);
|
|
6487
|
+
const comparisonAlignment = stringPayload(record.comparisonAlignment);
|
|
6488
|
+
const defaultRankingPeriod = stringPayload(record.defaultRankingPeriod);
|
|
6489
|
+
const policy = {
|
|
6490
|
+
metricIds: stringArrayPayload(record.metricIds),
|
|
6491
|
+
timeRole: stringPayload(record.timeRole),
|
|
6492
|
+
calendarId: stringPayload(record.calendarId),
|
|
6493
|
+
timezone: stringPayload(record.timezone),
|
|
6494
|
+
completenessPolicy: completenessPolicy === "partial_current" ||
|
|
6495
|
+
completenessPolicy === "latest_complete" ||
|
|
6496
|
+
completenessPolicy === "closed_period"
|
|
6497
|
+
? completenessPolicy
|
|
6498
|
+
: undefined,
|
|
6499
|
+
comparisonAlignment: comparisonAlignment === "elapsed_period" ||
|
|
6500
|
+
comparisonAlignment === "calendar_period" ||
|
|
6501
|
+
comparisonAlignment === "fiscal_period"
|
|
6502
|
+
? comparisonAlignment
|
|
6503
|
+
: undefined,
|
|
6504
|
+
defaultRankingPeriod: defaultRankingPeriod === "current" ||
|
|
6505
|
+
defaultRankingPeriod === "comparison"
|
|
6506
|
+
? defaultRankingPeriod
|
|
6507
|
+
: undefined,
|
|
6508
|
+
narrativeGuidance: stringArrayPayload(record.narrativeGuidance),
|
|
6509
|
+
};
|
|
6510
|
+
return Object.values(policy).some((item) => Array.isArray(item) ? item.length > 0 : Boolean(item))
|
|
6511
|
+
? policy
|
|
6512
|
+
: undefined;
|
|
6513
|
+
}
|
|
6296
6514
|
function stringPayload(value) {
|
|
6297
6515
|
return typeof value === 'string' && value.trim() ? value : undefined;
|
|
6298
6516
|
}
|