@exellix/graph-engine 6.0.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/.env.example +3 -0
- package/CHANGELOG.md +208 -0
- package/README.md +827 -0
- package/dist/src/errors/ExellixGraphError.d.ts +38 -0
- package/dist/src/errors/ExellixGraphError.js +21 -0
- package/dist/src/errors/exellixGraphErrorCodes.d.ts +31 -0
- package/dist/src/errors/exellixGraphErrorCodes.js +32 -0
- package/dist/src/index.d.ts +100 -0
- package/dist/src/index.js +75 -0
- package/dist/src/inspection/contractInspection.d.ts +21 -0
- package/dist/src/inspection/contractInspection.js +526 -0
- package/dist/src/inspection/contractTypes.d.ts +137 -0
- package/dist/src/inspection/contractTypes.js +1 -0
- package/dist/src/inspection/controlInspection.d.ts +22 -0
- package/dist/src/inspection/controlInspection.js +130 -0
- package/dist/src/inspection/graphInspection.d.ts +51 -0
- package/dist/src/inspection/graphInspection.js +467 -0
- package/dist/src/inspection/index.d.ts +21 -0
- package/dist/src/inspection/index.js +17 -0
- package/dist/src/inspection/nodeInspection.d.ts +42 -0
- package/dist/src/inspection/nodeInspection.js +474 -0
- package/dist/src/inspection/types.d.ts +321 -0
- package/dist/src/inspection/types.js +14 -0
- package/dist/src/inspection/validateAiTasksNodeExtensions.d.ts +12 -0
- package/dist/src/inspection/validateAiTasksNodeExtensions.js +119 -0
- package/dist/src/inspection/validateCatalogPlanning.d.ts +21 -0
- package/dist/src/inspection/validateCatalogPlanning.js +187 -0
- package/dist/src/integrations/ActivityTrackerIntegration.d.ts +86 -0
- package/dist/src/integrations/ActivityTrackerIntegration.js +134 -0
- package/dist/src/integrations/ActivixGraphRunIntegration.d.ts +34 -0
- package/dist/src/integrations/ActivixGraphRunIntegration.js +338 -0
- package/dist/src/integrations/ActivixNodeActivityIntegration.d.ts +33 -0
- package/dist/src/integrations/ActivixNodeActivityIntegration.js +220 -0
- package/dist/src/integrations/cataloxGraphCatalog.d.ts +21 -0
- package/dist/src/integrations/cataloxGraphCatalog.js +30 -0
- package/dist/src/integrations/createActivixExellixIntegration.d.ts +14 -0
- package/dist/src/integrations/createActivixExellixIntegration.js +16 -0
- package/dist/src/integrations/createActivixFromEnv.d.ts +31 -0
- package/dist/src/integrations/createActivixFromEnv.js +53 -0
- package/dist/src/loaders/FileGraphLoader.d.ts +23 -0
- package/dist/src/loaders/FileGraphLoader.js +31 -0
- package/dist/src/playground/PlaygroundReporter.d.ts +40 -0
- package/dist/src/playground/PlaygroundReporter.js +480 -0
- package/dist/src/playground/index.d.ts +1 -0
- package/dist/src/playground/index.js +1 -0
- package/dist/src/runtime/ExellixGraphRuntime.d.ts +263 -0
- package/dist/src/runtime/ExellixGraphRuntime.js +1716 -0
- package/dist/src/runtime/GraphEngine.d.ts +33 -0
- package/dist/src/runtime/GraphEngine.js +4 -0
- package/dist/src/runtime/aiTasksObservability.d.ts +6 -0
- package/dist/src/runtime/aiTasksObservability.js +37 -0
- package/dist/src/runtime/aiTasksStrategyPhases.d.ts +46 -0
- package/dist/src/runtime/aiTasksStrategyPhases.js +93 -0
- package/dist/src/runtime/applyAiTaskProfileWebScopingToNarrix.d.ts +17 -0
- package/dist/src/runtime/applyAiTaskProfileWebScopingToNarrix.js +46 -0
- package/dist/src/runtime/buildAiTasksRunTaskRequest.d.ts +67 -0
- package/dist/src/runtime/buildAiTasksRunTaskRequest.js +164 -0
- package/dist/src/runtime/buildRunLog.d.ts +27 -0
- package/dist/src/runtime/buildRunLog.js +234 -0
- package/dist/src/runtime/buildRunTaskTaskConfigurationForward.d.ts +9 -0
- package/dist/src/runtime/buildRunTaskTaskConfigurationForward.js +80 -0
- package/dist/src/runtime/buildTaskNodeJobContext.d.ts +11 -0
- package/dist/src/runtime/buildTaskNodeJobContext.js +30 -0
- package/dist/src/runtime/canonicalModelUsed.d.ts +6 -0
- package/dist/src/runtime/canonicalModelUsed.js +36 -0
- package/dist/src/runtime/contextualScope.d.ts +7 -0
- package/dist/src/runtime/contextualScope.js +121 -0
- package/dist/src/runtime/dataFiltersEvaluation.d.ts +60 -0
- package/dist/src/runtime/dataFiltersEvaluation.js +169 -0
- package/dist/src/runtime/deepMerge.d.ts +5 -0
- package/dist/src/runtime/deepMerge.js +22 -0
- package/dist/src/runtime/events.d.ts +92 -0
- package/dist/src/runtime/events.js +122 -0
- package/dist/src/runtime/executionMatrixHost.d.ts +98 -0
- package/dist/src/runtime/executionMatrixHost.js +134 -0
- package/dist/src/runtime/executionVariableBuckets.d.ts +67 -0
- package/dist/src/runtime/executionVariableBuckets.js +96 -0
- package/dist/src/runtime/finalizers/errors.d.ts +9 -0
- package/dist/src/runtime/finalizers/errors.js +10 -0
- package/dist/src/runtime/finalizers/executeFinalizer.d.ts +40 -0
- package/dist/src/runtime/finalizers/executeFinalizer.js +471 -0
- package/dist/src/runtime/finalizers/schema.d.ts +18 -0
- package/dist/src/runtime/finalizers/schema.js +63 -0
- package/dist/src/runtime/finalizers/validateFinalizer.d.ts +16 -0
- package/dist/src/runtime/finalizers/validateFinalizer.js +534 -0
- package/dist/src/runtime/graphDocumentFingerprint.d.ts +8 -0
- package/dist/src/runtime/graphDocumentFingerprint.js +21 -0
- package/dist/src/runtime/graphEngineMemoryPaths.d.ts +12 -0
- package/dist/src/runtime/graphEngineMemoryPaths.js +55 -0
- package/dist/src/runtime/graphResponseMapping.d.ts +23 -0
- package/dist/src/runtime/graphResponseMapping.js +156 -0
- package/dist/src/runtime/graphResponseMigration.d.ts +7 -0
- package/dist/src/runtime/graphResponseMigration.js +44 -0
- package/dist/src/runtime/graphRunExecutionSeed.d.ts +29 -0
- package/dist/src/runtime/graphRunExecutionSeed.js +61 -0
- package/dist/src/runtime/graphRunIdentity.d.ts +7 -0
- package/dist/src/runtime/graphRunIdentity.js +18 -0
- package/dist/src/runtime/localSkills/deterministicRule.d.ts +137 -0
- package/dist/src/runtime/localSkills/deterministicRule.js +196 -0
- package/dist/src/runtime/localSkills/index.d.ts +12 -0
- package/dist/src/runtime/localSkills/index.js +14 -0
- package/dist/src/runtime/localSkills/memorixItemToScopedOutput.d.ts +7 -0
- package/dist/src/runtime/localSkills/memorixItemToScopedOutput.js +104 -0
- package/dist/src/runtime/localSkills/memorixRuntime.d.ts +9 -0
- package/dist/src/runtime/localSkills/memorixRuntime.js +70 -0
- package/dist/src/runtime/localSkills/memorixScopedConfig.d.ts +16 -0
- package/dist/src/runtime/localSkills/memorixScopedConfig.js +18 -0
- package/dist/src/runtime/localSkills/scopedAnswerAssembler.d.ts +23 -0
- package/dist/src/runtime/localSkills/scopedAnswerAssembler.js +35 -0
- package/dist/src/runtime/localSkills/scopedAnswerFields.d.ts +12 -0
- package/dist/src/runtime/localSkills/scopedAnswerFields.js +66 -0
- package/dist/src/runtime/localSkills/scopedAnswerWriter.d.ts +32 -0
- package/dist/src/runtime/localSkills/scopedAnswerWriter.js +156 -0
- package/dist/src/runtime/localSkills/scopedDataReader.d.ts +47 -0
- package/dist/src/runtime/localSkills/scopedDataReader.js +89 -0
- package/dist/src/runtime/localSkills/utils.d.ts +12 -0
- package/dist/src/runtime/localSkills/utils.js +39 -0
- package/dist/src/runtime/materializeStructuredRunTaskInput.d.ts +9 -0
- package/dist/src/runtime/materializeStructuredRunTaskInput.js +34 -0
- package/dist/src/runtime/memory.d.ts +51 -0
- package/dist/src/runtime/memory.js +250 -0
- package/dist/src/runtime/mergeExellixGraphRuntimeInvocation.d.ts +18 -0
- package/dist/src/runtime/mergeExellixGraphRuntimeInvocation.js +32 -0
- package/dist/src/runtime/modelConfigSelection.d.ts +7 -0
- package/dist/src/runtime/modelConfigSelection.js +37 -0
- package/dist/src/runtime/narrixIngestEnv.d.ts +9 -0
- package/dist/src/runtime/narrixIngestEnv.js +18 -0
- package/dist/src/runtime/pathExpr.d.ts +36 -0
- package/dist/src/runtime/pathExpr.js +131 -0
- package/dist/src/runtime/predicates.d.ts +14 -0
- package/dist/src/runtime/predicates.js +86 -0
- package/dist/src/runtime/readTaskNodeInputsConfig.d.ts +23 -0
- package/dist/src/runtime/readTaskNodeInputsConfig.js +27 -0
- package/dist/src/runtime/resolveExecutionPipelineForTaskNode.d.ts +11 -0
- package/dist/src/runtime/resolveExecutionPipelineForTaskNode.js +93 -0
- package/dist/src/runtime/resolveGraphEngineMemoryPaths.d.ts +63 -0
- package/dist/src/runtime/resolveGraphEngineMemoryPaths.js +213 -0
- package/dist/src/runtime/resolveModelConfigForNode.d.ts +20 -0
- package/dist/src/runtime/resolveModelConfigForNode.js +69 -0
- package/dist/src/runtime/resolveNarrixForTaskNode.d.ts +14 -0
- package/dist/src/runtime/resolveNarrixForTaskNode.js +19 -0
- package/dist/src/runtime/resolveTaskKey.d.ts +11 -0
- package/dist/src/runtime/resolveTaskKey.js +28 -0
- package/dist/src/runtime/resolveTaskNodeInputs.d.ts +25 -0
- package/dist/src/runtime/resolveTaskNodeInputs.js +140 -0
- package/dist/src/runtime/runTaskAugments.d.ts +17 -0
- package/dist/src/runtime/runTaskAugments.js +37 -0
- package/dist/src/runtime/runTaskResponse.d.ts +4 -0
- package/dist/src/runtime/runTaskResponse.js +13 -0
- package/dist/src/runtime/runtimeObjects.d.ts +85 -0
- package/dist/src/runtime/runtimeObjects.js +50 -0
- package/dist/src/runtime/smartInputPaths.d.ts +13 -0
- package/dist/src/runtime/smartInputPaths.js +38 -0
- package/dist/src/runtime/stepRetry.d.ts +21 -0
- package/dist/src/runtime/stepRetry.js +238 -0
- package/dist/src/runtime/synthesizedContextPipeline.d.ts +12 -0
- package/dist/src/runtime/synthesizedContextPipeline.js +28 -0
- package/dist/src/runtime/taskNodeConditionsEvaluation.d.ts +27 -0
- package/dist/src/runtime/taskNodeConditionsEvaluation.js +140 -0
- package/dist/src/runtime/taskNodeMainReadiness.d.ts +45 -0
- package/dist/src/runtime/taskNodeMainReadiness.js +164 -0
- package/dist/src/runtime/taskNodeRunTaskPreflight.d.ts +89 -0
- package/dist/src/runtime/taskNodeRunTaskPreflight.js +204 -0
- package/dist/src/runtime/validateCanonicalGraphDocument.d.ts +25 -0
- package/dist/src/runtime/validateCanonicalGraphDocument.js +567 -0
- package/dist/src/runtime/variables.d.ts +2 -0
- package/dist/src/runtime/variables.js +1 -0
- package/dist/src/runtime/withTimeout.d.ts +5 -0
- package/dist/src/runtime/withTimeout.js +20 -0
- package/dist/src/types/aiTaskProfile.d.ts +41 -0
- package/dist/src/types/aiTaskProfile.js +6 -0
- package/dist/src/types/aiTasksDerivedTypes.d.ts +5 -0
- package/dist/src/types/aiTasksDerivedTypes.js +1 -0
- package/dist/src/types/events.d.ts +23 -0
- package/dist/src/types/events.js +1 -0
- package/dist/src/types/job.d.ts +9 -0
- package/dist/src/types/job.js +1 -0
- package/dist/src/types/narrix.d.ts +60 -0
- package/dist/src/types/narrix.js +1 -0
- package/dist/src/types/options.d.ts +122 -0
- package/dist/src/types/options.js +1 -0
- package/dist/src/types/refs.d.ts +747 -0
- package/dist/src/types/refs.js +12 -0
- package/dist/src/types/results.d.ts +103 -0
- package/dist/src/types/results.js +1 -0
- package/dist/src/types/runLog.d.ts +72 -0
- package/dist/src/types/runLog.js +18 -0
- package/dist/src/types/taskNodeConfiguration.d.ts +95 -0
- package/dist/src/types/taskNodeConfiguration.js +3 -0
- package/dist/src/util/packageVersion.d.ts +2 -0
- package/dist/src/util/packageVersion.js +12 -0
- package/dist/testkit/RealTasksClient.d.ts +16 -0
- package/dist/testkit/RealTasksClient.js +143 -0
- package/dist/testkit/depGraphEngineFactory.d.ts +6 -0
- package/dist/testkit/depGraphEngineFactory.js +54 -0
- package/dist/testkit/exellixRuntimeObjects.d.ts +7 -0
- package/dist/testkit/exellixRuntimeObjects.js +25 -0
- package/dist/testkit/inMemoryGraphLoader.d.ts +6 -0
- package/dist/testkit/inMemoryGraphLoader.js +12 -0
- package/dist/testkit/index.d.ts +4 -0
- package/dist/testkit/index.js +4 -0
- package/package.json +70 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Graph, GraphNode } from '../types/refs.js';
|
|
2
|
+
import type { NodeScopingQuestion, NodeScopingData, NodeMemoryShape, NodeNarrixDiscovery, NodeInspection } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the effective skillKey for a node. 5.x reads only the canonical `node.skillKey`.
|
|
5
|
+
* Returns undefined for finalizer nodes or task nodes that omit `skillKey`, so inspection stays non-throwing.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveNodeSkillKey(node: GraphNode): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Returns the scoping question, sources, and targets for a single node.
|
|
10
|
+
*
|
|
11
|
+
* All fields are derived statically from the node definition — no I/O.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getNodeScopingQuestion(node: GraphNode): NodeScopingQuestion;
|
|
14
|
+
/**
|
|
15
|
+
* Returns the conceptual execution-memory shape before and after a node runs.
|
|
16
|
+
*
|
|
17
|
+
* `upstreamWritePaths` should be the execution/output mapping paths of all upstream nodes.
|
|
18
|
+
* Pass `graph` when inspecting finalizers so question-driven item paths resolve the
|
|
19
|
+
* same way runtime resolves them.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getNodeMemoryShape(node: GraphNode, upstreamWritePaths?: string[], graph?: Graph): NodeMemoryShape;
|
|
22
|
+
/**
|
|
23
|
+
* Returns the Narrix discovery configuration for a node, or null if narrix
|
|
24
|
+
* is not configured on this node.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getNodeNarrixDiscovery(node: GraphNode): NodeNarrixDiscovery | null;
|
|
27
|
+
/**
|
|
28
|
+
* Fetches the actual x-scoped-data for the node's scoping question, given an entityId.
|
|
29
|
+
*
|
|
30
|
+
* Only meaningful for nodes with `skillKey: 'scoped-data-reader'`.
|
|
31
|
+
* For other nodes, `data` will be null and `error` will explain why.
|
|
32
|
+
*/
|
|
33
|
+
export declare function fetchNodeScopingData(node: GraphNode, entityId: string, options?: {
|
|
34
|
+
opDb?: string;
|
|
35
|
+
}): Promise<NodeScopingData>;
|
|
36
|
+
/**
|
|
37
|
+
* Full per-node inspection: scoping question, memory shape, and narrix discovery.
|
|
38
|
+
*
|
|
39
|
+
* For graph-level context (before.expects), use `inspectGraph` which computes
|
|
40
|
+
* upstream paths automatically.
|
|
41
|
+
*/
|
|
42
|
+
export declare function inspectNode(node: GraphNode, upstreamWritePaths?: string[], graph?: Graph): NodeInspection;
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { mapAiTaskProfileQuestionsToWebScopeQuestions } from '../runtime/applyAiTaskProfileWebScopingToNarrix.js';
|
|
2
|
+
import { readTaskNodeInputsConfig } from '../runtime/readTaskNodeInputsConfig.js';
|
|
3
|
+
import { runScopedDataReader } from '../runtime/localSkills/scopedDataReader.js';
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Internal helpers
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
function isTaskNode(node) {
|
|
8
|
+
return node.type !== 'finalizer';
|
|
9
|
+
}
|
|
10
|
+
function isFinalizerNode(node) {
|
|
11
|
+
return node.type === 'finalizer';
|
|
12
|
+
}
|
|
13
|
+
function isPlainObject(v) {
|
|
14
|
+
return v != null && typeof v === 'object' && !Array.isArray(v);
|
|
15
|
+
}
|
|
16
|
+
function findGraphNodeById(graph, nodeId) {
|
|
17
|
+
return graph.nodes.find((n) => String(n.id) === String(nodeId));
|
|
18
|
+
}
|
|
19
|
+
function pushDedupedRead(reads, path, source, memory) {
|
|
20
|
+
if (typeof path !== 'string' || path.length === 0)
|
|
21
|
+
return;
|
|
22
|
+
const existing = reads.find((r) => r.path === path && r.memory === memory);
|
|
23
|
+
if (!existing) {
|
|
24
|
+
reads.push({ path, memory, source });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!existing.source) {
|
|
28
|
+
existing.source = source;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const sources = existing.source.split(', ').filter(Boolean);
|
|
32
|
+
if (!sources.includes(source)) {
|
|
33
|
+
existing.source = [...sources, source].join(', ');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function finalizerInputReads(node) {
|
|
37
|
+
const reads = [];
|
|
38
|
+
for (const [label, binding] of Object.entries((node.inputs ?? {}))) {
|
|
39
|
+
if (binding.type === 'executionMemoryPath' || binding.type === 'outputsMemoryPath') {
|
|
40
|
+
pushDedupedRead(reads, binding.path, `inputs.${label}`, binding.type === 'outputsMemoryPath' ? 'outputsMemory' : 'executionMemory');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return reads;
|
|
44
|
+
}
|
|
45
|
+
function finalizerRuntimeReadSources(node, graph) {
|
|
46
|
+
const reads = finalizerInputReads(node);
|
|
47
|
+
const cfg = node.config;
|
|
48
|
+
if (node.finalizerType !== 'aggregate' || !isPlainObject(cfg)) {
|
|
49
|
+
return reads;
|
|
50
|
+
}
|
|
51
|
+
if (cfg.strategy === 'report-schema' && isPlainObject(cfg.sections)) {
|
|
52
|
+
for (const [key, spec] of Object.entries(cfg.sections)) {
|
|
53
|
+
if (!isPlainObject(spec))
|
|
54
|
+
continue;
|
|
55
|
+
pushDedupedRead(reads, spec.path, `config.sections.${key}`, 'executionMemory');
|
|
56
|
+
}
|
|
57
|
+
return reads;
|
|
58
|
+
}
|
|
59
|
+
if (cfg.strategy === 'question-driven') {
|
|
60
|
+
if (isPlainObject(cfg.meta)) {
|
|
61
|
+
for (const [key, binding] of Object.entries(cfg.meta)) {
|
|
62
|
+
if (!isPlainObject(binding))
|
|
63
|
+
continue;
|
|
64
|
+
pushDedupedRead(reads, binding.path, `config.meta.${key}`, binding.type === 'outputsMemoryPath' ? 'outputsMemory' : 'executionMemory');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (isPlainObject(cfg.items)) {
|
|
68
|
+
for (const [key, spec] of Object.entries(cfg.items)) {
|
|
69
|
+
if (!isPlainObject(spec))
|
|
70
|
+
continue;
|
|
71
|
+
if (typeof spec.answerPath === 'string' && spec.answerPath.length > 0) {
|
|
72
|
+
pushDedupedRead(reads, spec.answerPath, `config.items.${key}.answerPath`, 'executionMemory');
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (!graph)
|
|
76
|
+
continue;
|
|
77
|
+
const nodeId = typeof spec.nodeId === 'string' ? spec.nodeId : undefined;
|
|
78
|
+
const referencedNode = nodeId ? findGraphNodeById(graph, nodeId) : undefined;
|
|
79
|
+
const fallbackPath = referencedNode?.executionMapping?.path;
|
|
80
|
+
pushDedupedRead(reads, fallbackPath, `config.items.${key}.node.executionMapping.path`, 'executionMemory');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return reads;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolves the effective skillKey for a node. 5.x reads only the canonical `node.skillKey`.
|
|
88
|
+
* Returns undefined for finalizer nodes or task nodes that omit `skillKey`, so inspection stays non-throwing.
|
|
89
|
+
*/
|
|
90
|
+
export function resolveNodeSkillKey(node) {
|
|
91
|
+
if (isFinalizerNode(node))
|
|
92
|
+
return undefined;
|
|
93
|
+
const n = node;
|
|
94
|
+
return typeof n.skillKey === 'string' ? n.skillKey : undefined;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Classifies a jobContextMapping / inputs value string reference into a source type.
|
|
98
|
+
* Handles prefixes: executionMemory.* | jobMemory.* | variables.* | input.* | node.* | output.*
|
|
99
|
+
*/
|
|
100
|
+
function classifyRefType(ref) {
|
|
101
|
+
if (ref.startsWith('jobMemory.'))
|
|
102
|
+
return 'jobMemory';
|
|
103
|
+
if (ref.startsWith('variables.'))
|
|
104
|
+
return 'variables';
|
|
105
|
+
// executionMemory.* is explicit; input.* and execution.* are shorthand execution memory paths
|
|
106
|
+
if (ref.startsWith('executionMemory.') ||
|
|
107
|
+
ref.startsWith('input.') ||
|
|
108
|
+
ref.startsWith('execution.') ||
|
|
109
|
+
ref.startsWith('node.') ||
|
|
110
|
+
ref.startsWith('output.')) {
|
|
111
|
+
return 'executionMemory';
|
|
112
|
+
}
|
|
113
|
+
return 'executionMemory';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Strip common prefixes to get the canonical dot-path used inside execution memory.
|
|
117
|
+
*/
|
|
118
|
+
function stripRefPrefix(ref) {
|
|
119
|
+
const prefixes = ['executionMemory.', 'jobMemory.', 'variables.'];
|
|
120
|
+
for (const p of prefixes) {
|
|
121
|
+
if (ref.startsWith(p))
|
|
122
|
+
return ref.slice(p.length);
|
|
123
|
+
}
|
|
124
|
+
return ref;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Extract sources from a node's jobContextMapping.
|
|
128
|
+
*/
|
|
129
|
+
function sourcesFromJobContextMapping(node) {
|
|
130
|
+
const mapping = node.jobContextMapping;
|
|
131
|
+
if (!mapping?.map)
|
|
132
|
+
return [];
|
|
133
|
+
return Object.entries(mapping.map).map(([label, ref]) => ({
|
|
134
|
+
type: classifyRefType(ref),
|
|
135
|
+
path: stripRefPrefix(ref),
|
|
136
|
+
label,
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Extract sources from runtime payload bindings (`inputsConfig`).
|
|
141
|
+
*/
|
|
142
|
+
function sourcesFromInputBindings(node) {
|
|
143
|
+
const recipe = readTaskNodeInputsConfig(node);
|
|
144
|
+
const sources = [];
|
|
145
|
+
for (const [key, val] of Object.entries(recipe)) {
|
|
146
|
+
if (val == null || typeof val === 'string')
|
|
147
|
+
continue;
|
|
148
|
+
if (typeof val === 'object') {
|
|
149
|
+
const v = val;
|
|
150
|
+
if (v.type === 'executionMemoryPath' && typeof v.path === 'string') {
|
|
151
|
+
sources.push({ type: 'executionMemory', path: v.path, label: key });
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (typeof v['$path'] === 'string') {
|
|
155
|
+
const raw = v['$path'];
|
|
156
|
+
if (raw.startsWith('variables.'))
|
|
157
|
+
continue;
|
|
158
|
+
sources.push({ type: classifyRefType(raw), path: stripRefPrefix(raw), label: key });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return sources;
|
|
163
|
+
}
|
|
164
|
+
function variableRefsFromRecipe(recipe, labelPrefix) {
|
|
165
|
+
const sources = [];
|
|
166
|
+
for (const [key, val] of Object.entries(recipe)) {
|
|
167
|
+
if (val == null || typeof val !== 'object')
|
|
168
|
+
continue;
|
|
169
|
+
const raw = val['$path'];
|
|
170
|
+
if (typeof raw === 'string' && raw.startsWith('variables.')) {
|
|
171
|
+
sources.push({ type: 'variables', path: stripRefPrefix(raw), label: `${labelPrefix}.${key}` });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return sources;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Extract variable refs from `taskVariable` (and legacy `variables.*` refs still under `inputs`).
|
|
178
|
+
*/
|
|
179
|
+
function sourcesFromTaskVariable(node) {
|
|
180
|
+
const sources = [];
|
|
181
|
+
if (node.taskVariable && typeof node.taskVariable === 'object') {
|
|
182
|
+
sources.push(...variableRefsFromRecipe(node.taskVariable, 'taskVariable'));
|
|
183
|
+
}
|
|
184
|
+
sources.push(...variableRefsFromRecipe(readTaskNodeInputsConfig(node), 'inputsConfig'));
|
|
185
|
+
return sources;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Extract scoped-data source if the node uses the `scoped-data-reader` skill.
|
|
189
|
+
*/
|
|
190
|
+
function scopedDataSourceFromMetadata(node) {
|
|
191
|
+
const tc = node.taskConfiguration;
|
|
192
|
+
if (!tc)
|
|
193
|
+
return null;
|
|
194
|
+
const skillKey = resolveNodeSkillKey(node);
|
|
195
|
+
if (skillKey !== 'scoped-data-reader')
|
|
196
|
+
return null;
|
|
197
|
+
const { scopingMapId, entityIdPath, questionId, pack } = tc;
|
|
198
|
+
if (!scopingMapId && !questionId && !Array.isArray(pack))
|
|
199
|
+
return null;
|
|
200
|
+
const readability = node.metadata?.graphReadability;
|
|
201
|
+
return {
|
|
202
|
+
type: 'scopedData',
|
|
203
|
+
scopingMapId: typeof scopingMapId === 'string' ? scopingMapId : undefined,
|
|
204
|
+
entityIdPath: typeof entityIdPath === 'string' ? entityIdPath : undefined,
|
|
205
|
+
questionId: typeof questionId === 'string' ? questionId : undefined,
|
|
206
|
+
expectedKeys: Array.isArray(readability?.reads) ? readability.reads : undefined,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// Public API
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
/**
|
|
213
|
+
* Returns the scoping question, sources, and targets for a single node.
|
|
214
|
+
*
|
|
215
|
+
* All fields are derived statically from the node definition — no I/O.
|
|
216
|
+
*/
|
|
217
|
+
export function getNodeScopingQuestion(node) {
|
|
218
|
+
const nodeId = node.id;
|
|
219
|
+
if (isFinalizerNode(node)) {
|
|
220
|
+
// Finalizer: no question, inputs are memory bindings.
|
|
221
|
+
const sources = Object.entries((node.inputs ?? {})).map(([label, binding]) => {
|
|
222
|
+
if (binding.type === 'executionMemoryPath' || binding.type === 'outputsMemoryPath') {
|
|
223
|
+
return {
|
|
224
|
+
type: binding.type === 'outputsMemoryPath' ? 'outputsMemory' : 'executionMemory',
|
|
225
|
+
path: binding.path,
|
|
226
|
+
label,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
return { type: 'literal', label };
|
|
230
|
+
});
|
|
231
|
+
return {
|
|
232
|
+
nodeId,
|
|
233
|
+
name: undefined,
|
|
234
|
+
question: undefined,
|
|
235
|
+
kind: undefined,
|
|
236
|
+
sources,
|
|
237
|
+
targets: [],
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const task = node;
|
|
241
|
+
const readability = task.metadata?.graphReadability;
|
|
242
|
+
const name = readability?.title;
|
|
243
|
+
const legacyInputsConfig = readTaskNodeInputsConfig(task);
|
|
244
|
+
const question = readability?.asks ??
|
|
245
|
+
(typeof task.taskVariable?.question === 'string' ? task.taskVariable.question : undefined) ??
|
|
246
|
+
(typeof legacyInputsConfig.question === 'string' ? legacyInputsConfig.question : undefined);
|
|
247
|
+
const kind = readability?.kind;
|
|
248
|
+
// Sources
|
|
249
|
+
const sources = [];
|
|
250
|
+
// 1. Scoped-data if applicable
|
|
251
|
+
const scopedSrc = scopedDataSourceFromMetadata(task);
|
|
252
|
+
if (scopedSrc) {
|
|
253
|
+
// Merge graphReadability.reads into expectedKeys if not already set
|
|
254
|
+
if (!scopedSrc.expectedKeys && Array.isArray(readability?.reads)) {
|
|
255
|
+
scopedSrc.expectedKeys = readability.reads;
|
|
256
|
+
}
|
|
257
|
+
sources.push(scopedSrc);
|
|
258
|
+
}
|
|
259
|
+
// 2. jobContextMapping map values
|
|
260
|
+
sources.push(...sourcesFromJobContextMapping(task));
|
|
261
|
+
// 3. input bindings + taskVariable variable refs
|
|
262
|
+
sources.push(...sourcesFromInputBindings(task));
|
|
263
|
+
sources.push(...sourcesFromTaskVariable(task));
|
|
264
|
+
// 4. smartInput.paths (graph-engine / ai-tasks 7.1+; legacy `paths: string[]` vs Rendrix-native SmartInputConfig)
|
|
265
|
+
const si = task.smartInput;
|
|
266
|
+
if (si && Array.isArray(si.paths)) {
|
|
267
|
+
for (const p of si.paths) {
|
|
268
|
+
if (typeof p === 'string' && p.length > 0) {
|
|
269
|
+
sources.push({ type: 'executionMemory', path: p, label: `smartInput:${p}` });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// 5. taskConfiguration.aiTaskProfile.inputSynthesis.sources when enabled
|
|
274
|
+
const isynth = task.taskConfiguration?.aiTaskProfile?.inputSynthesis;
|
|
275
|
+
if (isynth?.enabled && Array.isArray(isynth.sources)) {
|
|
276
|
+
for (const p of isynth.sources) {
|
|
277
|
+
if (typeof p === 'string' && p.length > 0) {
|
|
278
|
+
sources.push({ type: 'executionMemory', path: p, label: `inputSynthesis:${p}` });
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// Targets
|
|
283
|
+
const targets = [];
|
|
284
|
+
if (task.executionMapping?.path) {
|
|
285
|
+
targets.push({
|
|
286
|
+
path: task.executionMapping.path,
|
|
287
|
+
memory: 'executionMemory',
|
|
288
|
+
mode: task.executionMapping.mode,
|
|
289
|
+
produces: Array.isArray(readability?.produces) ? readability.produces : undefined,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return { nodeId, name, question, kind, sources, targets };
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Returns the conceptual execution-memory shape before and after a node runs.
|
|
296
|
+
*
|
|
297
|
+
* `upstreamWritePaths` should be the execution/output mapping paths of all upstream nodes.
|
|
298
|
+
* Pass `graph` when inspecting finalizers so question-driven item paths resolve the
|
|
299
|
+
* same way runtime resolves them.
|
|
300
|
+
*/
|
|
301
|
+
export function getNodeMemoryShape(node, upstreamWritePaths, graph) {
|
|
302
|
+
const nodeId = node.id;
|
|
303
|
+
if (isFinalizerNode(node)) {
|
|
304
|
+
const reads = finalizerRuntimeReadSources(node, graph);
|
|
305
|
+
const outputsMemoryWrites = [];
|
|
306
|
+
if (node.outputMapping?.path) {
|
|
307
|
+
outputsMemoryWrites.push({ path: node.outputMapping.path, memory: 'outputsMemory', source: 'outputMapping' });
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
nodeId,
|
|
311
|
+
before: {
|
|
312
|
+
reads,
|
|
313
|
+
expects: (upstreamWritePaths ?? []).map((p) => ({ path: p })),
|
|
314
|
+
},
|
|
315
|
+
after: { writes: [], outputsMemoryWrites },
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
const task = node;
|
|
319
|
+
// before.reads — from jobContextMapping.map source values
|
|
320
|
+
const reads = [];
|
|
321
|
+
const mapping = task.jobContextMapping?.map;
|
|
322
|
+
if (mapping) {
|
|
323
|
+
for (const [label, ref] of Object.entries(mapping)) {
|
|
324
|
+
reads.push({ path: stripRefPrefix(ref), source: `jobContextMapping.map.${label}` });
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
const inputsConfig = readTaskNodeInputsConfig(task);
|
|
328
|
+
for (const [key, val] of Object.entries(inputsConfig)) {
|
|
329
|
+
if (!val || typeof val !== 'object')
|
|
330
|
+
continue;
|
|
331
|
+
const v = val;
|
|
332
|
+
if ((v.type === 'executionMemoryPath' || v.type === 'outputsMemoryPath') && typeof v.path === 'string') {
|
|
333
|
+
reads.push({
|
|
334
|
+
path: v.path,
|
|
335
|
+
memory: v.type === 'outputsMemoryPath' ? 'outputsMemory' : 'executionMemory',
|
|
336
|
+
source: `inputsConfig.${key}`,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
else if (typeof v['$path'] === 'string') {
|
|
340
|
+
reads.push({ path: stripRefPrefix(v['$path']), source: `inputsConfig.${key}` });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// after.writes — from executionMapping
|
|
344
|
+
const writes = [];
|
|
345
|
+
if (task.executionMapping?.path) {
|
|
346
|
+
writes.push({ path: task.executionMapping.path, memory: 'executionMemory', source: 'executionMapping' });
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
nodeId,
|
|
350
|
+
before: {
|
|
351
|
+
reads,
|
|
352
|
+
expects: (upstreamWritePaths ?? []).map((p) => ({ path: p })),
|
|
353
|
+
},
|
|
354
|
+
after: { writes, outputsMemoryWrites: [] },
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Returns the Narrix discovery configuration for a node, or null if narrix
|
|
359
|
+
* is not configured on this node.
|
|
360
|
+
*/
|
|
361
|
+
export function getNodeNarrixDiscovery(node) {
|
|
362
|
+
if (isFinalizerNode(node))
|
|
363
|
+
return null;
|
|
364
|
+
const task = node;
|
|
365
|
+
const narrix = task.taskConfiguration?.narrix;
|
|
366
|
+
if (!narrix || typeof narrix !== 'object')
|
|
367
|
+
return null;
|
|
368
|
+
const n = narrix;
|
|
369
|
+
const web = task.taskConfiguration?.aiTaskProfile?.webScoping;
|
|
370
|
+
const enableWebScope = web?.enabled === true;
|
|
371
|
+
return {
|
|
372
|
+
nodeId: node.id,
|
|
373
|
+
enabled: true,
|
|
374
|
+
questionId: typeof n.questionId === 'string' ? n.questionId : undefined,
|
|
375
|
+
layer: typeof n.layer === 'string' ? n.layer : undefined,
|
|
376
|
+
narrativeTypeIds: Array.isArray(n.narrativeTypeIds) ? n.narrativeTypeIds : undefined,
|
|
377
|
+
webScope: {
|
|
378
|
+
enabled: enableWebScope,
|
|
379
|
+
forced: undefined,
|
|
380
|
+
questions: Array.isArray(web?.questions) && web.questions.length > 0
|
|
381
|
+
? mapAiTaskProfileQuestionsToWebScopeQuestions(web.questions)
|
|
382
|
+
: undefined,
|
|
383
|
+
entityIdPath: undefined,
|
|
384
|
+
entityTypePath: undefined,
|
|
385
|
+
enrichFromRaw: undefined,
|
|
386
|
+
},
|
|
387
|
+
outputPaths: {
|
|
388
|
+
signals: 'executionMemory._narrix.scoping.signals',
|
|
389
|
+
stories: 'executionMemory._narrix.scoping.stories',
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Fetches the actual x-scoped-data for the node's scoping question, given an entityId.
|
|
395
|
+
*
|
|
396
|
+
* Only meaningful for nodes with `skillKey: 'scoped-data-reader'`.
|
|
397
|
+
* For other nodes, `data` will be null and `error` will explain why.
|
|
398
|
+
*/
|
|
399
|
+
export async function fetchNodeScopingData(node, entityId, options) {
|
|
400
|
+
const base = getNodeScopingQuestion(node);
|
|
401
|
+
if (isFinalizerNode(node)) {
|
|
402
|
+
return { ...base, entityId, data: null, error: 'finalizer nodes do not read scoped data' };
|
|
403
|
+
}
|
|
404
|
+
const task = node;
|
|
405
|
+
const skillKey = resolveNodeSkillKey(task);
|
|
406
|
+
if (skillKey !== 'scoped-data-reader') {
|
|
407
|
+
return {
|
|
408
|
+
...base,
|
|
409
|
+
entityId,
|
|
410
|
+
data: null,
|
|
411
|
+
error: `node skillKey is "${skillKey ?? 'unset'}" — only scoped-data-reader nodes fetch x-scoped-data`,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
const tc = (task.taskConfiguration ?? {});
|
|
415
|
+
const entityIdPath = typeof tc.entityIdPath === 'string' ? tc.entityIdPath : '_entityId';
|
|
416
|
+
// Build a synthetic executionMemory so runScopedDataReader resolves the entityId
|
|
417
|
+
const syntheticMemory = {};
|
|
418
|
+
const parts = entityIdPath.split('.');
|
|
419
|
+
let cursor = syntheticMemory;
|
|
420
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
421
|
+
cursor[parts[i]] = {};
|
|
422
|
+
cursor = cursor[parts[i]];
|
|
423
|
+
}
|
|
424
|
+
cursor[parts[parts.length - 1]] = entityId;
|
|
425
|
+
const cfg = {
|
|
426
|
+
scopingMapId: typeof tc.scopingMapId === 'string' ? tc.scopingMapId : undefined,
|
|
427
|
+
questionId: typeof tc.questionId === 'string' ? tc.questionId : undefined,
|
|
428
|
+
entityIdPath,
|
|
429
|
+
opDb: options?.opDb ?? (typeof tc.opDb === 'string' ? tc.opDb : undefined),
|
|
430
|
+
pack: Array.isArray(tc.pack) ? tc.pack : undefined,
|
|
431
|
+
};
|
|
432
|
+
try {
|
|
433
|
+
const data = await runScopedDataReader(cfg, syntheticMemory);
|
|
434
|
+
return { ...base, entityId, data };
|
|
435
|
+
}
|
|
436
|
+
catch (err) {
|
|
437
|
+
return {
|
|
438
|
+
...base,
|
|
439
|
+
entityId,
|
|
440
|
+
data: null,
|
|
441
|
+
error: err?.message ?? String(err),
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Full per-node inspection: scoping question, memory shape, and narrix discovery.
|
|
447
|
+
*
|
|
448
|
+
* For graph-level context (before.expects), use `inspectGraph` which computes
|
|
449
|
+
* upstream paths automatically.
|
|
450
|
+
*/
|
|
451
|
+
export function inspectNode(node, upstreamWritePaths, graph) {
|
|
452
|
+
const skillKey = resolveNodeSkillKey(node);
|
|
453
|
+
const readability = isTaskNode(node)
|
|
454
|
+
? node.metadata?.graphReadability
|
|
455
|
+
: undefined;
|
|
456
|
+
let catalogBinding;
|
|
457
|
+
let catalogRequest;
|
|
458
|
+
if (isTaskNode(node)) {
|
|
459
|
+
const m = node.metadata;
|
|
460
|
+
catalogBinding = m?.catalogBinding;
|
|
461
|
+
catalogRequest = m?.catalogRequest;
|
|
462
|
+
}
|
|
463
|
+
return {
|
|
464
|
+
nodeId: node.id,
|
|
465
|
+
nodeType: node.type ?? 'task',
|
|
466
|
+
skillKey,
|
|
467
|
+
kind: readability?.kind,
|
|
468
|
+
scopingQuestion: getNodeScopingQuestion(node),
|
|
469
|
+
memoryShape: getNodeMemoryShape(node, upstreamWritePaths, graph),
|
|
470
|
+
narrixDiscovery: getNodeNarrixDiscovery(node),
|
|
471
|
+
catalogBinding,
|
|
472
|
+
catalogRequest,
|
|
473
|
+
};
|
|
474
|
+
}
|