@exellix/graph-engine 8.1.8 → 8.1.9
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/CHANGELOG.md +9 -0
- package/dist/src/compile/compileExellixExecutablePlan.js +1 -31
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +1 -0
- package/dist/src/runtime/ExellixGraphRuntime.d.ts +8 -2
- package/dist/src/runtime/ExellixGraphRuntime.js +40 -45
- package/dist/src/runtime/executionMatrixHost.js +3 -0
- package/dist/src/runtime/graphEngineLogxer.js +2 -2
- package/dist/src/runtime/resolveRunTaskInvokeInput.d.ts +35 -0
- package/dist/src/runtime/resolveRunTaskInvokeInput.js +135 -0
- package/dist/src/runtime/runTaskNodePlan.d.ts +2 -0
- package/dist/src/runtime/runTaskNodePlan.js +6 -1
- package/dist/src/runtime/taskNodeRunTaskPreflight.d.ts +4 -10
- package/dist/src/runtime/taskNodeRunTaskPreflight.js +24 -30
- package/dist/src/runtime/validateCanonicalGraphDocument.js +14 -0
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## 8.1.8
|
|
4
4
|
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- **Run-task data model 2.1:** `runtime.input` → `RunTaskRequest.input` via `inputsConfig` (`path: "input"`); **`executionMemory.input` is no longer seeded** or mirrored before `runTask`. `taskVariable` stays on `nodePlan.invokeContract` only (not merged into `input`). `executeGraph` requires compiled `plan.nodePlans[nodeId]` (`requireCompiledNodePlan`).
|
|
8
|
+
- **`buildExecutionSeedFromGraphEntry`** skips `input` / `input.*` graphEntry paths (invoke payload belongs on `runtime.input` only).
|
|
9
|
+
|
|
5
10
|
### Changed
|
|
6
11
|
|
|
7
12
|
- **Graphenix 2.1.0 alignment (Tier 2 + 3):** `@x12i/graphenix-core` ^2.0.1 (`formatVersion: "2.1.0"`); lifecycle `@x12i/graphenix-*` ^2.0.0; testkit emits `metadata.modelConfig` (no `metadata.extensions`, no `parameters.profile` / `nodeType`).
|
|
13
|
+
- **`compileExellixExecutablePlan`** — removed host patch that prefixed bare `invokeContract.reads` with `executionMemory.`.
|
|
14
|
+
- **`buildRunTaskInvokeInput`** / **`executionMemoryForRunTaskWire`** — canonical invoke binding resolver; entry gates evaluate `runtime.input`.
|
|
8
15
|
- **`@exellix/ai-tasks` ^9.1.0** — accepts parent plan `"executable-plan"` v2 and trace `"execution-trace"` v2; dedupes nested `graphenix-*@1.1.x` under ai-tasks.
|
|
9
16
|
- **`check:no-legacy`** — fails when ai-tasks < 9.1.0, graphenix-core < 2.0.1, or ai-tasks nests duplicate `@x12i/graphenix-*`.
|
|
10
17
|
|
|
11
18
|
### Added
|
|
12
19
|
|
|
13
20
|
- **`tests/reference-fixtures-compile.test.ts`** — compiles `graph-content-pipeline` and `graph-subnets-analysis` authoring fixtures; asserts `validateExecutablePlanV2`.
|
|
21
|
+
- **`tests/run-task-invoke-input.test.ts`** — wire-sketch parity for graphenix 2.1 invoke bindings.
|
|
22
|
+
- **`docs/run-task-handoff/`** — client handoff docs (compiler, backend-host, graph-engine, observability).
|
|
14
23
|
|
|
15
24
|
## 8.1.3
|
|
16
25
|
|
|
@@ -25,36 +25,6 @@ function patchEntryGatesFromGraphEntryDataFilters(plan, doc) {
|
|
|
25
25
|
next.deferredGates = { ...next.deferredGates, entryGates };
|
|
26
26
|
return next;
|
|
27
27
|
}
|
|
28
|
-
function patchInvokeContractReadPathsForExecutionMemory(plan) {
|
|
29
|
-
const allowedRoots = new Set([
|
|
30
|
-
'executionMemory',
|
|
31
|
-
'input',
|
|
32
|
-
'inputs',
|
|
33
|
-
'jobMemory',
|
|
34
|
-
'taskMemory',
|
|
35
|
-
'smartInput',
|
|
36
|
-
'xynthesized',
|
|
37
|
-
'runtime',
|
|
38
|
-
'response',
|
|
39
|
-
]);
|
|
40
|
-
const next = structuredClone(plan);
|
|
41
|
-
for (const nodePlan of Object.values(next.nodePlans ?? {})) {
|
|
42
|
-
if (!nodePlan?.executionUnits)
|
|
43
|
-
continue;
|
|
44
|
-
for (const unit of nodePlan.executionUnits) {
|
|
45
|
-
const contract = unit.invokeContract;
|
|
46
|
-
if (!contract || !Array.isArray(contract.reads))
|
|
47
|
-
continue;
|
|
48
|
-
contract.reads = contract.reads.map((readPath) => {
|
|
49
|
-
if (typeof readPath !== 'string')
|
|
50
|
-
return readPath;
|
|
51
|
-
const root = readPath.split('.')[0];
|
|
52
|
-
return allowedRoots.has(root) ? readPath : `executionMemory.${readPath}`;
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return next;
|
|
57
|
-
}
|
|
58
28
|
/**
|
|
59
29
|
* Host/test helper: canonical {@link AuthoringGraphDocument} + runtime → validated v2 executable plan.
|
|
60
30
|
* No legacy migration — graphs must already be Graphenix 2.x authoring shape.
|
|
@@ -65,7 +35,7 @@ export function compileExellixExecutablePlan(doc, runtime, options) {
|
|
|
65
35
|
const summary = authoringValidation.errors.map((e) => `${e.path}: ${e.message}`).join('; ');
|
|
66
36
|
throw new Error(`compileExellixExecutablePlan: invalid authoring graph: ${summary}`);
|
|
67
37
|
}
|
|
68
|
-
const plan =
|
|
38
|
+
const plan = patchEntryGatesFromGraphEntryDataFilters(compileExecutablePlanV2(doc, runtime, options), doc);
|
|
69
39
|
const planValidation = validateExecutablePlanV2(plan);
|
|
70
40
|
if (!planValidation.valid) {
|
|
71
41
|
const summary = planValidation.errors.map((e) => `${e.path}: ${e.message}`).join('; ');
|
package/dist/src/index.d.ts
CHANGED
|
@@ -51,6 +51,8 @@ export { isGraphAiModelConfig, isPartialGraphAiModelConfig, isModelConfigSelecti
|
|
|
51
51
|
export { GRAPH_ENGINE_MEMORY_PATH_ROOTS, splitGraphEngineMemoryPath, isAllowedGraphEngineMemoryPath, graphEngineMemoryPathValidationMessage, } from './runtime/graphEngineMemoryPaths.js';
|
|
52
52
|
export { buildRunTaskMainInput, extractCallerInputsBag, buildGraphEngineMemoryResolutionRoot, buildGraphEngineMemoryResolutionRootFromWorkingMemory, resolveGraphEngineMemoryPathValue, } from './runtime/resolveGraphEngineMemoryPaths.js';
|
|
53
53
|
export { mirrorStructuredInputOntoExecutionMemory, } from './runtime/materializeStructuredRunTaskInput.js';
|
|
54
|
+
export { buildRunTaskInvokeInput, executionMemoryForRunTaskWire, } from './runtime/resolveRunTaskInvokeInput.js';
|
|
55
|
+
export type { InvokeBindingContext } from './runtime/resolveRunTaskInvokeInput.js';
|
|
54
56
|
export { buildRunTaskTaskConfigurationForward } from './runtime/buildRunTaskTaskConfigurationForward.js';
|
|
55
57
|
export { normalizeSmartInputPath, collectSmartInputPaths, normalizeSmartInputConfigForRunTask, } from './runtime/smartInputPaths.js';
|
|
56
58
|
export { evaluateTaskNodeMainReadiness, buildMainReadinessResolutionRoot, resolveMainReadinessPolicy, collectInputSynthesisSourcePaths, } from './runtime/taskNodeMainReadiness.js';
|
package/dist/src/index.js
CHANGED
|
@@ -41,6 +41,7 @@ export { isGraphAiModelConfig, isPartialGraphAiModelConfig, isModelConfigSelecti
|
|
|
41
41
|
export { GRAPH_ENGINE_MEMORY_PATH_ROOTS, splitGraphEngineMemoryPath, isAllowedGraphEngineMemoryPath, graphEngineMemoryPathValidationMessage, } from './runtime/graphEngineMemoryPaths.js';
|
|
42
42
|
export { buildRunTaskMainInput, extractCallerInputsBag, buildGraphEngineMemoryResolutionRoot, buildGraphEngineMemoryResolutionRootFromWorkingMemory, resolveGraphEngineMemoryPathValue, } from './runtime/resolveGraphEngineMemoryPaths.js';
|
|
43
43
|
export { mirrorStructuredInputOntoExecutionMemory, } from './runtime/materializeStructuredRunTaskInput.js';
|
|
44
|
+
export { buildRunTaskInvokeInput, executionMemoryForRunTaskWire, } from './runtime/resolveRunTaskInvokeInput.js';
|
|
44
45
|
export { buildRunTaskTaskConfigurationForward } from './runtime/buildRunTaskTaskConfigurationForward.js';
|
|
45
46
|
export { normalizeSmartInputPath, collectSmartInputPaths, normalizeSmartInputConfigForRunTask, } from './runtime/smartInputPaths.js';
|
|
46
47
|
export { evaluateTaskNodeMainReadiness, buildMainReadinessResolutionRoot, resolveMainReadinessPolicy, collectInputSynthesisSourcePaths, } from './runtime/taskNodeMainReadiness.js';
|
|
@@ -39,9 +39,9 @@ export interface GraphRuntimeObject extends HostExecuteGraphRunOptions {
|
|
|
39
39
|
jobId: string;
|
|
40
40
|
/** Host job envelope (`agentId`, `jobType`, `input`, etc.). */
|
|
41
41
|
job: any;
|
|
42
|
-
/** Active
|
|
42
|
+
/** Active invoke payload for this run — maps to `RunTaskRequest.input` per node (not seeded into executionMemory). */
|
|
43
43
|
input?: Record<string, unknown>;
|
|
44
|
-
/** Caller / graph-entry bag
|
|
44
|
+
/** Caller / graph-entry bag forwarded on `RunTaskRequest.inputs` (dual root with `input`). */
|
|
45
45
|
inputs?: Record<string, unknown>;
|
|
46
46
|
/** Temporary task/node-scoped runtime memory. */
|
|
47
47
|
taskMemory?: any;
|
|
@@ -201,6 +201,12 @@ export declare function createExellixGraphRuntime(opts: ExellixGraphRuntimeOptio
|
|
|
201
201
|
jobType?: string;
|
|
202
202
|
};
|
|
203
203
|
mainReadinessPolicy?: import("../types/options.js").MainReadinessPolicy;
|
|
204
|
+
/** Canonical invoke payload — not mirrored into executionMemory.input. */
|
|
205
|
+
invokeRuntimeInput?: Record<string, unknown>;
|
|
206
|
+
/** Caller bag (`runtime.inputs`) forwarded separately on RunTaskRequest.inputs. */
|
|
207
|
+
invokeRuntimeInputs?: Record<string, unknown>;
|
|
208
|
+
/** When true, requires compiled nodePlan (executeGraph path). */
|
|
209
|
+
requireCompiledNodePlan?: boolean;
|
|
204
210
|
}) => Promise<{
|
|
205
211
|
nodeId: string;
|
|
206
212
|
skillKey: string;
|
|
@@ -8,10 +8,9 @@ import { mergeExecutionObject, copyExecutionContextFields, } from "./memory.js";
|
|
|
8
8
|
import { buildAiTasksRunTaskRequest, extractRunTaskStrategyOverrides, resolveJobTypeId, } from "./buildAiTasksRunTaskRequest.js";
|
|
9
9
|
import { runTaskResponseSucceeded } from "./runTaskResponse.js";
|
|
10
10
|
import { mergeGraphDocumentModel, EXELLIX_GRAPH_MODEL_VARIABLE_KEY, } from "../types/refs.js";
|
|
11
|
-
import { resolveTaskNodeInputsForRunTask } from "./resolveTaskNodeInputs.js";
|
|
12
11
|
import { assertAiTasksNodeExtensionsValid } from "../inspection/validateAiTasksNodeExtensions.js";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
12
|
+
import { extractCallerInputsBag } from "./resolveGraphEngineMemoryPaths.js";
|
|
13
|
+
import { buildRunTaskInvokeInput, executionMemoryForRunTaskWire, } from "./resolveRunTaskInvokeInput.js";
|
|
15
14
|
import { buildMainReadinessResolutionRoot, evaluateTaskNodeMainReadiness, resolveMainReadinessPolicy, } from "./taskNodeMainReadiness.js";
|
|
16
15
|
import { mergeXynthesizedPatchIntoExecution, seedGraphRunExecutionState, xynthesizedOutboundForNode, } from "./graphRunExecutionSeed.js";
|
|
17
16
|
import { buildTaskNodeJobContext } from "./buildTaskNodeJobContext.js";
|
|
@@ -30,7 +29,7 @@ import { runWithAiTasksStackLogging } from "@exellix/ai-tasks";
|
|
|
30
29
|
import { nodePlanFromFinalizerPlan, patchNodePlanMainModelFromWire, resolveRunTaskNodePlan, } from "./runTaskNodePlan.js";
|
|
31
30
|
import { assertHostJobId, newGraphRunTaskId } from "./graphRunIdentity.js";
|
|
32
31
|
import { resolveTaskKey } from "./resolveTaskKey.js";
|
|
33
|
-
import { buildPredicateEvalContextForNode,
|
|
32
|
+
import { buildPredicateEvalContextForNode, readExecutionVariableBuckets, seedGraphVariableBucketsFromRuntime, } from "./variables.js";
|
|
34
33
|
import { mergeExellixGraphRuntimeInvocation } from "./mergeExellixGraphRuntimeInvocation.js";
|
|
35
34
|
import { resolveStepRetryPolicy, runRunTaskWithRetry } from "./stepRetry.js";
|
|
36
35
|
import { isLocalSkillKey, runScopedDataReader, runDeterministicRule, runScopedAnswerWriter, runScopedAnswerAssembler, } from "./localSkills/index.js";
|
|
@@ -117,7 +116,7 @@ function resolveCoreObjectiveValue(args) {
|
|
|
117
116
|
? args.execution
|
|
118
117
|
: undefined;
|
|
119
118
|
return selectByPath({
|
|
120
|
-
input: executionRec?.input,
|
|
119
|
+
input: args.invokeInput ?? executionRec?.input,
|
|
121
120
|
execution: args.execution,
|
|
122
121
|
variables: executionRec?.jobVariables ?? args.variables,
|
|
123
122
|
jobVariables: executionRec?.jobVariables,
|
|
@@ -236,19 +235,18 @@ async function resolveKnowledgePatch(args) {
|
|
|
236
235
|
}
|
|
237
236
|
function normalizeRuntimeExecutionMemory(runtime) {
|
|
238
237
|
const execution = isPlainRecord(runtime.executionMemory)
|
|
239
|
-
? runtime.executionMemory
|
|
238
|
+
? { ...runtime.executionMemory }
|
|
240
239
|
: {};
|
|
241
|
-
if (runtime.input !== undefined) {
|
|
242
|
-
execution.input = isPlainRecord(runtime.input) ? { ...runtime.input } : runtime.input;
|
|
243
|
-
}
|
|
244
|
-
else if (!isPlainRecord(execution.input)) {
|
|
245
|
-
execution.input = {};
|
|
246
|
-
}
|
|
247
240
|
if (isPlainRecord(runtime.inputs)) {
|
|
248
241
|
execution.inputs = { ...runtime.inputs };
|
|
249
242
|
}
|
|
250
243
|
return execution;
|
|
251
244
|
}
|
|
245
|
+
function normalizeInvokeRuntimeInput(runtime) {
|
|
246
|
+
if (isPlainRecord(runtime.input))
|
|
247
|
+
return { ...runtime.input };
|
|
248
|
+
return {};
|
|
249
|
+
}
|
|
252
250
|
function normalizeRuntimeOutputsMemory(runtime) {
|
|
253
251
|
return isPlainRecord(runtime.outputsMemory) ? runtime.outputsMemory : {};
|
|
254
252
|
}
|
|
@@ -337,9 +335,8 @@ export function createExellixGraphRuntime(opts) {
|
|
|
337
335
|
if (executionSeed == null || typeof executionSeed !== "object")
|
|
338
336
|
executionSeed = {};
|
|
339
337
|
const executionRecSeed = executionSeed;
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
: {};
|
|
338
|
+
const invokeInputSeed = isPlainRecord(input.invokeRuntimeInput) ? input.invokeRuntimeInput : {};
|
|
339
|
+
const dataFiltersRecordSeed = invokeInputSeed;
|
|
343
340
|
let effectiveModelConfig = input.modelConfig;
|
|
344
341
|
if (!isGraphAiModelConfig(effectiveModelConfig)) {
|
|
345
342
|
if (input.graph == null) {
|
|
@@ -664,17 +661,9 @@ export function createExellixGraphRuntime(opts) {
|
|
|
664
661
|
throw pe;
|
|
665
662
|
}
|
|
666
663
|
const executionRec = execution;
|
|
667
|
-
mirrorTaskVariablesOnExecution({
|
|
668
|
-
execution: executionRec,
|
|
669
|
-
node: input.node,
|
|
670
|
-
runtimeTaskVariables: input.taskVariables ?? undefined,
|
|
671
|
-
});
|
|
672
664
|
const variableBuckets = readExecutionVariableBuckets(executionRec);
|
|
673
665
|
const jobVariables = variableBuckets.jobVariables;
|
|
674
|
-
const
|
|
675
|
-
node: input.node,
|
|
676
|
-
execution: executionRec,
|
|
677
|
-
});
|
|
666
|
+
const invokeRuntimeInput = isPlainRecord(input.invokeRuntimeInput) ? input.invokeRuntimeInput : {};
|
|
678
667
|
const jobContext = buildTaskNodeJobContext({
|
|
679
668
|
node: input.node,
|
|
680
669
|
jobMemory: input.jobMemory,
|
|
@@ -695,8 +684,9 @@ export function createExellixGraphRuntime(opts) {
|
|
|
695
684
|
nodePlan: input.nodePlan,
|
|
696
685
|
skillKey,
|
|
697
686
|
nodeId: String(input.node.id),
|
|
687
|
+
requireCompiledPlan: input.requireCompiledNodePlan === true,
|
|
698
688
|
});
|
|
699
|
-
if (!input.nodePlan) {
|
|
689
|
+
if (!input.nodePlan && input.requireCompiledNodePlan !== true) {
|
|
700
690
|
runTaskNodePlan = patchNodePlanMainModelFromWire(runTaskNodePlan, wireModelConfig);
|
|
701
691
|
}
|
|
702
692
|
const startedAt = Date.now();
|
|
@@ -714,21 +704,22 @@ export function createExellixGraphRuntime(opts) {
|
|
|
714
704
|
return c;
|
|
715
705
|
})()
|
|
716
706
|
: executionRec;
|
|
717
|
-
const callerInputs =
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
707
|
+
const callerInputs = input.invokeRuntimeInputs ??
|
|
708
|
+
extractCallerInputsBag({
|
|
709
|
+
execution: executionRec,
|
|
710
|
+
jobMemory: isPlainRecord(input.jobMemory) ? input.jobMemory : undefined,
|
|
711
|
+
});
|
|
712
|
+
const taskInput = buildRunTaskInvokeInput({
|
|
713
|
+
node: input.node,
|
|
714
|
+
runtimeInput: invokeRuntimeInput,
|
|
715
|
+
executionMemory: executionRec,
|
|
716
|
+
runtimeInputs: callerInputs,
|
|
717
|
+
variables: jobVariables,
|
|
718
|
+
extraFields: input.node?.data?.upstreamNodeIds !== undefined
|
|
719
|
+
? { upstreamNodeIds: input.node.data.upstreamNodeIds }
|
|
720
|
+
: undefined,
|
|
730
721
|
});
|
|
731
|
-
|
|
722
|
+
const executionMemoryForWire = executionMemoryForRunTaskWire(executionForTask);
|
|
732
723
|
const graphDocModel = jobVariables[EXELLIX_GRAPH_MODEL_VARIABLE_KEY];
|
|
733
724
|
const graphEntry = graphDocModel != null && typeof graphDocModel === "object" && !Array.isArray(graphDocModel)
|
|
734
725
|
? graphDocModel.graphEntry
|
|
@@ -740,7 +731,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
740
731
|
const readinessRoot = buildMainReadinessResolutionRoot({
|
|
741
732
|
taskInput,
|
|
742
733
|
callerInputs,
|
|
743
|
-
executionMemory:
|
|
734
|
+
executionMemory: executionMemoryForWire,
|
|
744
735
|
xynthesized: xynthesizedOutboundForNode(executionRec, String(input.node.id)),
|
|
745
736
|
jobMemory: input.jobMemory,
|
|
746
737
|
taskMemory: input.taskMemory,
|
|
@@ -797,7 +788,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
797
788
|
variables: jobVariables,
|
|
798
789
|
jobMemory: runTaskJobMemory,
|
|
799
790
|
taskMemory: runTaskTaskMemory,
|
|
800
|
-
executionMemory:
|
|
791
|
+
executionMemory: executionMemoryForWire,
|
|
801
792
|
jobContext,
|
|
802
793
|
prevNodeId: input.prevNodeId,
|
|
803
794
|
narrix: narrix ?? undefined,
|
|
@@ -1186,6 +1177,8 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1186
1177
|
// Track current memory and execution state (will be updated as nodes execute)
|
|
1187
1178
|
let currentJobMemory = runtime.jobMemory || {};
|
|
1188
1179
|
let currentTaskMemory = runtime.taskMemory;
|
|
1180
|
+
const invokeRuntimeInput = normalizeInvokeRuntimeInput(runtime);
|
|
1181
|
+
const invokeRuntimeInputs = isPlainRecord(runtime.inputs) ? { ...runtime.inputs } : undefined;
|
|
1189
1182
|
let currentExecution = normalizeRuntimeExecutionMemory(runtime);
|
|
1190
1183
|
let currentOutputsMemory = normalizeRuntimeOutputsMemory(runtime);
|
|
1191
1184
|
if (!currentExecution._trace)
|
|
@@ -1217,6 +1210,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1217
1210
|
const coreObjectiveValue = resolveCoreObjectiveValue({
|
|
1218
1211
|
sourcePath: coreObjectiveConfig.sourcePath,
|
|
1219
1212
|
execution: currentExecution,
|
|
1213
|
+
invokeInput: invokeRuntimeInput,
|
|
1220
1214
|
jobMemory: currentJobMemory,
|
|
1221
1215
|
taskMemory: currentTaskMemory,
|
|
1222
1216
|
job,
|
|
@@ -1300,9 +1294,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1300
1294
|
currentExecutionIsNull: currentExecution === null,
|
|
1301
1295
|
});
|
|
1302
1296
|
function recordForStructuredDataFilters() {
|
|
1303
|
-
return
|
|
1304
|
-
? currentExecution.input
|
|
1305
|
-
: {};
|
|
1297
|
+
return invokeRuntimeInput;
|
|
1306
1298
|
}
|
|
1307
1299
|
const entryGateEv = await evaluatePlanEntryGates(plan.deferredGates.entryGates, recordForStructuredDataFilters(), {
|
|
1308
1300
|
executionMemory: currentExecution,
|
|
@@ -1311,7 +1303,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1311
1303
|
job,
|
|
1312
1304
|
}, runxClient);
|
|
1313
1305
|
if (!entryGateEv.ok) {
|
|
1314
|
-
const err = new Error("GRAPH_ENTRY_DATA_FILTERS_REJECTED: plan entry gates rejected runtime.
|
|
1306
|
+
const err = new Error("GRAPH_ENTRY_DATA_FILTERS_REJECTED: plan entry gates rejected runtime.input");
|
|
1315
1307
|
err.code = ExellixGraphErrorCode.GRAPH_ENTRY_DATA_FILTERS_REJECTED;
|
|
1316
1308
|
logGraphEngineErrorCode(ExellixGraphErrorCode.GRAPH_ENTRY_DATA_FILTERS_REJECTED, err.message, {
|
|
1317
1309
|
graphId: resolvedGraphId,
|
|
@@ -1571,6 +1563,9 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1571
1563
|
outputsMemory: outputsForNode,
|
|
1572
1564
|
variables: runtime.variables,
|
|
1573
1565
|
taskVariables: runtime.taskVariables,
|
|
1566
|
+
invokeRuntimeInput,
|
|
1567
|
+
invokeRuntimeInputs,
|
|
1568
|
+
requireCompiledNodePlan: true,
|
|
1574
1569
|
modelConfig: effectiveModelConfig,
|
|
1575
1570
|
runTaskIdentity: merged.runTaskIdentity,
|
|
1576
1571
|
runTaskExecutionMode: merged.runTaskExecutionMode,
|
|
@@ -56,6 +56,9 @@ export function buildExecutionSeedFromGraphEntry(graphEntry, sources = {}) {
|
|
|
56
56
|
const path = spec.path.trim();
|
|
57
57
|
if (!path)
|
|
58
58
|
continue;
|
|
59
|
+
// Invoke payload paths belong on runtime.input (graphenix 2.1) — not executionMemory.
|
|
60
|
+
if (path === 'input' || path.startsWith('input.'))
|
|
61
|
+
continue;
|
|
59
62
|
let value = undefined;
|
|
60
63
|
if (Object.prototype.hasOwnProperty.call(valuesByPath, path)) {
|
|
61
64
|
value = valuesByPath[path];
|
|
@@ -12,11 +12,11 @@ const GRAPH_ENGINE_DIAGNOSTIC_CATALOG = {
|
|
|
12
12
|
impact: 'The graph run cannot start because structured entry filters did not accept runtime input.',
|
|
13
13
|
possibleCauses: [
|
|
14
14
|
'metadata.graphEntry.dataFilters shape is unsupported or evaluated false.',
|
|
15
|
-
'runtime.
|
|
15
|
+
'runtime.input is missing expected fields for the filter contract.',
|
|
16
16
|
],
|
|
17
17
|
remediation: [
|
|
18
18
|
'Inspect metadata.graphEntry.dataFilters against exellix.dataFilters.v1.',
|
|
19
|
-
'Verify runtime.
|
|
19
|
+
'Verify runtime.input before executeGraph.',
|
|
20
20
|
],
|
|
21
21
|
retryable: false,
|
|
22
22
|
userActionRequired: true,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves `nodePlan.invokeContract.inputsConfig` → `RunTaskRequest.input` per graphenix 2.1.
|
|
3
|
+
* Invoke payload reads from `runtime.input` (`path: "input"`); cross-node reads use `executionMemoryPath`.
|
|
4
|
+
*/
|
|
5
|
+
import type { TaskNode } from '../types/refs.js';
|
|
6
|
+
export type InvokeBindingContext = {
|
|
7
|
+
/** Canonical invoke payload (`runtime.input`). */
|
|
8
|
+
invokeInput: Record<string, unknown>;
|
|
9
|
+
/** Caller bag (`runtime.inputs`). */
|
|
10
|
+
callerInputs?: Record<string, unknown>;
|
|
11
|
+
executionMemory: Record<string, unknown>;
|
|
12
|
+
jobVariables?: Record<string, unknown>;
|
|
13
|
+
taskVariables?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Resolves `inputsConfig` bindings into the outbound `RunTaskRequest.input` object.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveInputsConfigToRunTaskInput(args: {
|
|
19
|
+
inputsConfig: Record<string, unknown>;
|
|
20
|
+
ctx: InvokeBindingContext;
|
|
21
|
+
}): Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Builds MAIN `RunTaskRequest.input` from frozen invoke contract + runtime invoke payload.
|
|
24
|
+
* When `inputsConfig` is empty, returns a shallow copy of `runtimeInput`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildRunTaskInvokeInput(args: {
|
|
27
|
+
node: TaskNode;
|
|
28
|
+
runtimeInput: Record<string, unknown>;
|
|
29
|
+
executionMemory: Record<string, unknown>;
|
|
30
|
+
runtimeInputs?: Record<string, unknown>;
|
|
31
|
+
variables?: Record<string, unknown>;
|
|
32
|
+
extraFields?: Record<string, unknown>;
|
|
33
|
+
}): Record<string, unknown>;
|
|
34
|
+
/** Strips invoke-payload mirror fields before sending executionMemory on RunTask wire. */
|
|
35
|
+
export declare function executionMemoryForRunTaskWire(execution: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { readTaskNodeInputsConfig } from './readTaskNodeInputsConfig.js';
|
|
2
|
+
import { selectByPath } from './pathExpr.js';
|
|
3
|
+
function isPlainObject(v) {
|
|
4
|
+
return v != null && typeof v === 'object' && !Array.isArray(v);
|
|
5
|
+
}
|
|
6
|
+
function getByDotPath(root, path) {
|
|
7
|
+
if (!path)
|
|
8
|
+
return root;
|
|
9
|
+
const parts = path.split('.').filter(Boolean);
|
|
10
|
+
let cur = root;
|
|
11
|
+
for (const p of parts) {
|
|
12
|
+
if (cur == null || typeof cur !== 'object')
|
|
13
|
+
return undefined;
|
|
14
|
+
cur = cur[p];
|
|
15
|
+
}
|
|
16
|
+
return cur;
|
|
17
|
+
}
|
|
18
|
+
function resolvePathBinding(path, ctx) {
|
|
19
|
+
const p = path.trim();
|
|
20
|
+
if (!p)
|
|
21
|
+
return undefined;
|
|
22
|
+
if (p === 'input')
|
|
23
|
+
return ctx.invokeInput;
|
|
24
|
+
if (p.startsWith('input.'))
|
|
25
|
+
return selectByPath(ctx.invokeInput, p.slice('input.'.length));
|
|
26
|
+
if (p === 'inputs')
|
|
27
|
+
return ctx.callerInputs ?? {};
|
|
28
|
+
if (p.startsWith('inputs.')) {
|
|
29
|
+
const bag = ctx.callerInputs ?? {};
|
|
30
|
+
return selectByPath(bag, p.slice('inputs.'.length));
|
|
31
|
+
}
|
|
32
|
+
if (p.startsWith('variables.') || p.startsWith('jobVariables.')) {
|
|
33
|
+
const tail = p.startsWith('variables.') ? p.slice('variables.'.length) : p.slice('jobVariables.'.length);
|
|
34
|
+
return ctx.jobVariables != null ? selectByPath(ctx.jobVariables, tail) : undefined;
|
|
35
|
+
}
|
|
36
|
+
if (p.startsWith('taskVariables.')) {
|
|
37
|
+
return ctx.taskVariables != null ? selectByPath(ctx.taskVariables, p.slice('taskVariables.'.length)) : undefined;
|
|
38
|
+
}
|
|
39
|
+
if (p.startsWith('executionMemory.')) {
|
|
40
|
+
return selectByPath(ctx.executionMemory, p.slice('executionMemory.'.length));
|
|
41
|
+
}
|
|
42
|
+
return getByDotPath(ctx.executionMemory, p);
|
|
43
|
+
}
|
|
44
|
+
function resolveBindingValue(binding, ctx) {
|
|
45
|
+
if (!isPlainObject(binding))
|
|
46
|
+
return binding;
|
|
47
|
+
if (typeof binding.path === 'string') {
|
|
48
|
+
return resolvePathBinding(binding.path, ctx);
|
|
49
|
+
}
|
|
50
|
+
if (typeof binding.executionMemoryPath === 'string') {
|
|
51
|
+
const emp = binding.executionMemoryPath.trim();
|
|
52
|
+
if (emp === 'executionMemory.input' || emp.startsWith('executionMemory.input.')) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
if (emp.startsWith('executionMemory.')) {
|
|
56
|
+
return selectByPath(ctx.executionMemory, emp.slice('executionMemory.'.length));
|
|
57
|
+
}
|
|
58
|
+
return getByDotPath(ctx.executionMemory, emp);
|
|
59
|
+
}
|
|
60
|
+
if (binding.type === 'executionMemoryPath' && typeof binding.path === 'string') {
|
|
61
|
+
const p = binding.path.trim();
|
|
62
|
+
if (p === 'executionMemory.input' || p.startsWith('executionMemory.input.')) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
if (p === 'input' || p.startsWith('input.')) {
|
|
66
|
+
return resolvePathBinding(p, ctx);
|
|
67
|
+
}
|
|
68
|
+
if (p === 'inputs' || p.startsWith('inputs.')) {
|
|
69
|
+
return resolvePathBinding(p, ctx);
|
|
70
|
+
}
|
|
71
|
+
if (binding.optional === true) {
|
|
72
|
+
const v = getByDotPath(ctx.executionMemory, p);
|
|
73
|
+
return v === undefined || v === null ? undefined : v;
|
|
74
|
+
}
|
|
75
|
+
return getByDotPath(ctx.executionMemory, p);
|
|
76
|
+
}
|
|
77
|
+
if (typeof binding.$path === 'string') {
|
|
78
|
+
const p = binding.$path.trim();
|
|
79
|
+
if (p.startsWith('variables.') || p.startsWith('jobVariables.') || p.startsWith('taskVariables.')) {
|
|
80
|
+
return resolvePathBinding(p, ctx);
|
|
81
|
+
}
|
|
82
|
+
if (p === 'input' || p.startsWith('input.') || p === 'inputs' || p.startsWith('inputs.')) {
|
|
83
|
+
return resolvePathBinding(p, ctx);
|
|
84
|
+
}
|
|
85
|
+
return getByDotPath(ctx.executionMemory, p);
|
|
86
|
+
}
|
|
87
|
+
const nested = {};
|
|
88
|
+
for (const [k, v] of Object.entries(binding)) {
|
|
89
|
+
if (k === '$path' || k === 'type' || k === 'path' || k === 'executionMemoryPath' || k === 'optional')
|
|
90
|
+
continue;
|
|
91
|
+
const child = resolveBindingValue(v, ctx);
|
|
92
|
+
if (child !== undefined)
|
|
93
|
+
nested[k] = child;
|
|
94
|
+
}
|
|
95
|
+
return Object.keys(nested).length > 0 ? nested : binding;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Resolves `inputsConfig` bindings into the outbound `RunTaskRequest.input` object.
|
|
99
|
+
*/
|
|
100
|
+
export function resolveInputsConfigToRunTaskInput(args) {
|
|
101
|
+
const out = {};
|
|
102
|
+
for (const [key, val] of Object.entries(args.inputsConfig)) {
|
|
103
|
+
const resolved = resolveBindingValue(val, args.ctx);
|
|
104
|
+
if (resolved !== undefined)
|
|
105
|
+
out[key] = resolved;
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Builds MAIN `RunTaskRequest.input` from frozen invoke contract + runtime invoke payload.
|
|
111
|
+
* When `inputsConfig` is empty, returns a shallow copy of `runtimeInput`.
|
|
112
|
+
*/
|
|
113
|
+
export function buildRunTaskInvokeInput(args) {
|
|
114
|
+
const ctx = {
|
|
115
|
+
invokeInput: args.runtimeInput,
|
|
116
|
+
callerInputs: args.runtimeInputs,
|
|
117
|
+
executionMemory: args.executionMemory,
|
|
118
|
+
jobVariables: args.variables,
|
|
119
|
+
};
|
|
120
|
+
const recipe = readTaskNodeInputsConfig(args.node);
|
|
121
|
+
const fromConfig = Object.keys(recipe).length > 0
|
|
122
|
+
? resolveInputsConfigToRunTaskInput({ inputsConfig: recipe, ctx })
|
|
123
|
+
: { ...args.runtimeInput };
|
|
124
|
+
return {
|
|
125
|
+
...fromConfig,
|
|
126
|
+
...(args.extraFields ?? {}),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** Strips invoke-payload mirror fields before sending executionMemory on RunTask wire. */
|
|
130
|
+
export function executionMemoryForRunTaskWire(execution) {
|
|
131
|
+
const wire = { ...execution };
|
|
132
|
+
delete wire.input;
|
|
133
|
+
delete wire.inputs;
|
|
134
|
+
return wire;
|
|
135
|
+
}
|
|
@@ -5,6 +5,8 @@ export declare function resolveRunTaskNodePlan(args: {
|
|
|
5
5
|
nodePlan?: NodeExecutionPlan;
|
|
6
6
|
skillKey: string;
|
|
7
7
|
nodeId: string;
|
|
8
|
+
/** When true (executeGraph path), missing compiled nodePlan is an error. */
|
|
9
|
+
requireCompiledPlan?: boolean;
|
|
8
10
|
}): NodeExecutionPlan;
|
|
9
11
|
/** Standalone {@link executeNode} without compile: patch MAIN unit selection from resolved graph profiles. */
|
|
10
12
|
export declare function patchNodePlanMainModelFromWire(plan: NodeExecutionPlan, wire: RunTaskModelConfigWire): NodeExecutionPlan;
|
|
@@ -9,7 +9,12 @@ function selectionFromWireSlot(value) {
|
|
|
9
9
|
}
|
|
10
10
|
/** Resolve the frozen node plan required by `@exellix/ai-tasks` ≥ 9. */
|
|
11
11
|
export function resolveRunTaskNodePlan(args) {
|
|
12
|
-
|
|
12
|
+
if (args.nodePlan)
|
|
13
|
+
return args.nodePlan;
|
|
14
|
+
if (args.requireCompiledPlan) {
|
|
15
|
+
throw new Error(`MISSING_NODE_PLAN: compiled plan has no nodePlans[${args.nodeId}] — executeGraph requires full compiled node plans`);
|
|
16
|
+
}
|
|
17
|
+
return minimalNodePlanForSkillKey(args.skillKey, args.nodeId);
|
|
13
18
|
}
|
|
14
19
|
/** Standalone {@link executeNode} without compile: patch MAIN unit selection from resolved graph profiles. */
|
|
15
20
|
export function patchNodePlanMainModelFromWire(plan, wire) {
|
|
@@ -26,13 +26,9 @@ export type BuildTaskNodeRunTaskRequestArgs = {
|
|
|
26
26
|
taskMemory?: unknown;
|
|
27
27
|
taskVariables?: Record<string, unknown>;
|
|
28
28
|
prevNodeId?: string;
|
|
29
|
-
/** Same UUID used for every `runTask` in one `executeGraph` invocation. */
|
|
30
29
|
graphRunTaskId?: string;
|
|
31
|
-
/** Host job id on `job.jobId` / `job.id`; defaults from `job` when omitted. */
|
|
32
30
|
runTaskJobId?: string;
|
|
33
|
-
/** Frozen per-node plan from compile; when omitted a minimal plan is synthesized and patched from modelConfig. */
|
|
34
31
|
nodePlan?: NodeExecutionPlan;
|
|
35
|
-
/** Resolved graph model profiles (required for runnable MAIN when nodePlan is omitted). */
|
|
36
32
|
modelConfig: GraphAiModelConfig;
|
|
37
33
|
runTaskIdentity?: Record<string, unknown>;
|
|
38
34
|
runTaskExecutionMode?: 'default' | 'trace';
|
|
@@ -41,11 +37,11 @@ export type BuildTaskNodeRunTaskRequestArgs = {
|
|
|
41
37
|
taskKnowledgePatch?: Record<string, unknown>;
|
|
42
38
|
skillKeyResolution?: SkillKeyResolutionOptions;
|
|
43
39
|
clearSynthesizedContextPerNode?: boolean;
|
|
40
|
+
/** Canonical invoke payload (`runtime.input`). */
|
|
41
|
+
invokeRuntimeInput?: Record<string, unknown>;
|
|
42
|
+
invokeRuntimeInputs?: Record<string, unknown>;
|
|
43
|
+
requireCompiledNodePlan?: boolean;
|
|
44
44
|
};
|
|
45
|
-
/**
|
|
46
|
-
* Materialize the outbound `RunTaskRequest` graph-engine would send for a task node
|
|
47
|
-
* (mirrors `executeNode` request assembly; does not invoke `runTask`).
|
|
48
|
-
*/
|
|
49
45
|
export declare function buildTaskNodeRunTaskRequest(args: BuildTaskNodeRunTaskRequestArgs): Promise<BuildTaskNodeRunTaskRequestResult>;
|
|
50
46
|
export type ValidateTaskNodeRunTaskConfigArgs = BuildTaskNodeRunTaskRequestArgs;
|
|
51
47
|
export type ValidateTaskNodeRunTaskConfigResult = {
|
|
@@ -57,7 +53,6 @@ export type ValidateTaskNodeRunTaskConfigResult = {
|
|
|
57
53
|
skillKey: string;
|
|
58
54
|
request: RunTaskRequest;
|
|
59
55
|
} & RunTaskValidationResult);
|
|
60
|
-
/** Static ai-tasks validation on the graph-built {@link RunTaskRequest}. */
|
|
61
56
|
export declare function validateTaskNodeRunTaskConfig(args: ValidateTaskNodeRunTaskConfigArgs): Promise<ValidateTaskNodeRunTaskConfigResult>;
|
|
62
57
|
export type ValidateTaskNodeRunTaskInvokeArgs = BuildTaskNodeRunTaskRequestArgs & Omit<ValidateRunTaskInvokeParams, 'request'>;
|
|
63
58
|
export type ValidateTaskNodeRunTaskInvokeResult = {
|
|
@@ -69,5 +64,4 @@ export type ValidateTaskNodeRunTaskInvokeResult = {
|
|
|
69
64
|
skillKey: string;
|
|
70
65
|
request: RunTaskRequest;
|
|
71
66
|
} & RunTaskInvokeValidationResult);
|
|
72
|
-
/** Config + payload + template path validation via ai-tasks {@link validateRunTaskInvoke}. */
|
|
73
67
|
export declare function validateTaskNodeRunTaskInvoke(args: ValidateTaskNodeRunTaskInvokeArgs): Promise<ValidateTaskNodeRunTaskInvokeResult>;
|
|
@@ -3,15 +3,14 @@ import { toRunTaskModelConfig } from './graphAiModelConfig.js';
|
|
|
3
3
|
import { resolveTaskKey } from './resolveTaskKey.js';
|
|
4
4
|
import { isLocalSkillKey } from './localSkills/index.js';
|
|
5
5
|
import { buildAiTasksRunTaskRequest, extractRunTaskStrategyOverrides, } from './buildAiTasksRunTaskRequest.js';
|
|
6
|
-
import { resolveTaskNodeInputsForRunTask } from './resolveTaskNodeInputs.js';
|
|
7
6
|
import { assertAiTasksNodeExtensionsValid } from '../inspection/validateAiTasksNodeExtensions.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { extractCallerInputsBag } from './resolveGraphEngineMemoryPaths.js';
|
|
8
|
+
import { buildRunTaskInvokeInput, executionMemoryForRunTaskWire, } from './resolveRunTaskInvokeInput.js';
|
|
10
9
|
import { xynthesizedOutboundForNode } from './graphRunExecutionSeed.js';
|
|
11
10
|
import { buildTaskNodeJobContext } from './buildTaskNodeJobContext.js';
|
|
12
11
|
import { resolveNarrixForTaskNode } from './resolveNarrixForTaskNode.js';
|
|
13
12
|
import { buildRunTaskIdentityEnvelope, shouldForwardRunTaskTraceMode, } from './runTaskAugments.js';
|
|
14
|
-
import {
|
|
13
|
+
import { readExecutionVariableBuckets } from './executionVariableBuckets.js';
|
|
15
14
|
import { newGraphRunTaskId } from './graphRunIdentity.js';
|
|
16
15
|
import { patchNodePlanMainModelFromWire, resolveRunTaskNodePlan } from './runTaskNodePlan.js';
|
|
17
16
|
function isPlainRecord(v) {
|
|
@@ -30,10 +29,6 @@ function mergeKnowledgePatchIntoRunTaskMemory(memory, patch) {
|
|
|
30
29
|
},
|
|
31
30
|
};
|
|
32
31
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Materialize the outbound `RunTaskRequest` graph-engine would send for a task node
|
|
35
|
-
* (mirrors `executeNode` request assembly; does not invoke `runTask`).
|
|
36
|
-
*/
|
|
37
32
|
export async function buildTaskNodeRunTaskRequest(args) {
|
|
38
33
|
const node = args.node;
|
|
39
34
|
if (node.type === 'finalizer') {
|
|
@@ -53,18 +48,14 @@ export async function buildTaskNodeRunTaskRequest(args) {
|
|
|
53
48
|
let execution = args.execution != null && typeof args.execution === 'object' && !Array.isArray(args.execution)
|
|
54
49
|
? { ...args.execution }
|
|
55
50
|
: {};
|
|
56
|
-
mirrorTaskVariablesOnExecution({
|
|
57
|
-
execution,
|
|
58
|
-
node: node,
|
|
59
|
-
runtimeTaskVariables: args.taskVariables,
|
|
60
|
-
});
|
|
61
51
|
const wireModelConfig = toRunTaskModelConfig(args.modelConfig);
|
|
62
52
|
let runTaskNodePlan = resolveRunTaskNodePlan({
|
|
63
53
|
nodePlan: args.nodePlan,
|
|
64
54
|
skillKey,
|
|
65
55
|
nodeId: String(node.id),
|
|
56
|
+
requireCompiledPlan: args.requireCompiledNodePlan === true,
|
|
66
57
|
});
|
|
67
|
-
if (!args.nodePlan) {
|
|
58
|
+
if (!args.nodePlan && args.requireCompiledNodePlan !== true) {
|
|
68
59
|
runTaskNodePlan = patchNodePlanMainModelFromWire(runTaskNodePlan, wireModelConfig);
|
|
69
60
|
}
|
|
70
61
|
const hasSynthesizedContextPreStep = runTaskNodePlan.executionUnits.some((u) => u.unitKind === 'externalPreUtility' || u.unitKind === 'pipelinePhase');
|
|
@@ -74,7 +65,11 @@ export async function buildTaskNodeRunTaskRequest(args) {
|
|
|
74
65
|
hasExistingSynthesizedContext;
|
|
75
66
|
const variableBuckets = readExecutionVariableBuckets(execution);
|
|
76
67
|
const jobVariables = variableBuckets.jobVariables;
|
|
77
|
-
const
|
|
68
|
+
const invokeRuntimeInput = isPlainRecord(args.invokeRuntimeInput)
|
|
69
|
+
? args.invokeRuntimeInput
|
|
70
|
+
: isPlainRecord(args.execution?.input)
|
|
71
|
+
? args.execution.input
|
|
72
|
+
: {};
|
|
78
73
|
const jobContext = buildTaskNodeJobContext({
|
|
79
74
|
node,
|
|
80
75
|
jobMemory: args.jobMemory,
|
|
@@ -98,19 +93,20 @@ export async function buildTaskNodeRunTaskRequest(args) {
|
|
|
98
93
|
return c;
|
|
99
94
|
})()
|
|
100
95
|
: execution;
|
|
101
|
-
const callerInputs =
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
96
|
+
const callerInputs = args.invokeRuntimeInputs ??
|
|
97
|
+
extractCallerInputsBag({
|
|
98
|
+
execution,
|
|
99
|
+
jobMemory: isPlainRecord(args.jobMemory) ? args.jobMemory : undefined,
|
|
100
|
+
});
|
|
101
|
+
const taskInput = buildRunTaskInvokeInput({
|
|
102
|
+
node,
|
|
103
|
+
runtimeInput: invokeRuntimeInput,
|
|
104
|
+
executionMemory: execution,
|
|
105
|
+
runtimeInputs: callerInputs,
|
|
106
|
+
variables: jobVariables,
|
|
107
|
+
extraFields: node.data?.upstreamNodeIds !== undefined ? { upstreamNodeIds: node.data.upstreamNodeIds } : undefined,
|
|
112
108
|
});
|
|
113
|
-
|
|
109
|
+
const executionMemoryForWire = executionMemoryForRunTaskWire(executionForTask);
|
|
114
110
|
const runTaskJobMemory = mergeKnowledgePatchIntoRunTaskMemory(args.jobMemory, args.jobKnowledgePatch);
|
|
115
111
|
const runTaskTaskMemory = mergeKnowledgePatchIntoRunTaskMemory(args.taskMemory, args.taskKnowledgePatch);
|
|
116
112
|
const forwardRunTaskTrace = shouldForwardRunTaskTraceMode({
|
|
@@ -142,7 +138,7 @@ export async function buildTaskNodeRunTaskRequest(args) {
|
|
|
142
138
|
variables: jobVariables,
|
|
143
139
|
jobMemory: runTaskJobMemory,
|
|
144
140
|
taskMemory: runTaskTaskMemory,
|
|
145
|
-
executionMemory:
|
|
141
|
+
executionMemory: executionMemoryForWire,
|
|
146
142
|
jobContext,
|
|
147
143
|
prevNodeId: args.prevNodeId,
|
|
148
144
|
narrix: narrix ?? undefined,
|
|
@@ -170,7 +166,6 @@ export async function buildTaskNodeRunTaskRequest(args) {
|
|
|
170
166
|
});
|
|
171
167
|
return { runnable: true, skillKey, request };
|
|
172
168
|
}
|
|
173
|
-
/** Static ai-tasks validation on the graph-built {@link RunTaskRequest}. */
|
|
174
169
|
export async function validateTaskNodeRunTaskConfig(args) {
|
|
175
170
|
const built = await buildTaskNodeRunTaskRequest(args);
|
|
176
171
|
if (!built.runnable) {
|
|
@@ -179,7 +174,6 @@ export async function validateTaskNodeRunTaskConfig(args) {
|
|
|
179
174
|
const validation = validateRunTaskConfig(built.request);
|
|
180
175
|
return { skipped: false, skillKey: built.skillKey, request: built.request, ...validation };
|
|
181
176
|
}
|
|
182
|
-
/** Config + payload + template path validation via ai-tasks {@link validateRunTaskInvoke}. */
|
|
183
177
|
export async function validateTaskNodeRunTaskInvoke(args) {
|
|
184
178
|
const built = await buildTaskNodeRunTaskRequest(args);
|
|
185
179
|
if (!built.runnable) {
|
|
@@ -411,6 +411,17 @@ function assertForbidInputRawExecutionPath(dotPath, label, context) {
|
|
|
411
411
|
throw new ExellixGraphError(ExellixGraphErrorCode.NON_CANONICAL_TASK_NODE, `${label}: executionMemoryPath "${dotPath}" is forbidden — bind to "input" (flat MAIN bucket). input.raw mirroring was removed.`, context);
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
|
+
function assertForbidHubPathExecutionInput(binding, label, context) {
|
|
415
|
+
const hubPaths = [
|
|
416
|
+
typeof binding.executionMemoryPath === 'string' ? binding.executionMemoryPath.trim() : undefined,
|
|
417
|
+
binding.type === 'executionMemoryPath' && typeof binding.path === 'string' ? binding.path.trim() : undefined,
|
|
418
|
+
].filter((p) => p != null && p.length > 0);
|
|
419
|
+
for (const p of hubPaths) {
|
|
420
|
+
if (p === 'executionMemory.input' || p.startsWith('executionMemory.input.')) {
|
|
421
|
+
throw new ExellixGraphError(ExellixGraphErrorCode.NON_CANONICAL_TASK_NODE, `${label}: TASK_INPUT_BINDING_HUB_PATH_FORBIDDEN — use path "input" instead of executionMemoryPath "executionMemory.input".`, context);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
414
425
|
function assertGraphResponseShapeNoLegacy(shape, path, context) {
|
|
415
426
|
if (Array.isArray(shape)) {
|
|
416
427
|
shape.forEach((item, index) => assertGraphResponseShapeNoLegacy(item, `${path}[${index}]`, context));
|
|
@@ -553,6 +564,9 @@ export function assertCanonicalTaskNode(node, context, options) {
|
|
|
553
564
|
throw new ExellixGraphError(ExellixGraphErrorCode.NON_CANONICAL_TASK_NODE, `Task node "${String(node.id)}": inputsConfig must be a plain object when present.`, { jobId: context?.jobId, graphId: context?.graphId, nodeId: String(node.id) });
|
|
554
565
|
}
|
|
555
566
|
for (const [bindingKey, bindingVal] of Object.entries(inputsConfig)) {
|
|
567
|
+
if (isPlainObject(bindingVal)) {
|
|
568
|
+
assertForbidHubPathExecutionInput(bindingVal, `Task node "${String(node.id)}": inputsConfig.${bindingKey}`, { jobId: context?.jobId, graphId: context?.graphId, nodeId: String(node.id) });
|
|
569
|
+
}
|
|
556
570
|
if (isExecutionMemoryPathBinding(bindingVal)) {
|
|
557
571
|
assertForbidInputRawExecutionPath(bindingVal.path, `Task node "${String(node.id)}": inputsConfig.${bindingKey}`, { jobId: context?.jobId, graphId: context?.graphId, nodeId: String(node.id) });
|
|
558
572
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exellix/graph-engine",
|
|
3
|
-
"version": "8.1.
|
|
3
|
+
"version": "8.1.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Graph executor SDK",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -52,22 +52,22 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@exellix/ai-skills": "^6.9.
|
|
56
|
-
"@exellix/ai-tasks": "^9.1.
|
|
55
|
+
"@exellix/ai-skills": "^6.9.1",
|
|
56
|
+
"@exellix/ai-tasks": "^9.1.1",
|
|
57
57
|
"@x12i/activix": "^8.6.3",
|
|
58
58
|
"@x12i/catalox": "^5.2.0",
|
|
59
59
|
"@x12i/env": "^4.0.1",
|
|
60
|
-
"@x12i/funcx": "^4.9.
|
|
60
|
+
"@x12i/funcx": "^4.9.13",
|
|
61
61
|
"@x12i/graphenix": "^2.5.0",
|
|
62
|
-
"@x12i/graphenix-authoring-format": "^2.0.
|
|
62
|
+
"@x12i/graphenix-authoring-format": "^2.0.1",
|
|
63
63
|
"@x12i/graphenix-core": "^2.0.1",
|
|
64
|
-
"@x12i/graphenix-executable-contracts": "^2.0.
|
|
65
|
-
"@x12i/graphenix-executable-format": "^2.2.
|
|
64
|
+
"@x12i/graphenix-executable-contracts": "^2.0.1",
|
|
65
|
+
"@x12i/graphenix-executable-format": "^2.2.1",
|
|
66
66
|
"@x12i/graphenix-execute-envelope": "^2.0.0",
|
|
67
67
|
"@x12i/graphenix-format": "^2.0.0",
|
|
68
|
-
"@x12i/graphenix-plan-compiler": "^2.0.
|
|
69
|
-
"@x12i/graphenix-plan-format": "^2.0.
|
|
70
|
-
"@x12i/graphenix-trace-format": "^2.0.
|
|
68
|
+
"@x12i/graphenix-plan-compiler": "^2.0.1",
|
|
69
|
+
"@x12i/graphenix-plan-format": "^2.0.1",
|
|
70
|
+
"@x12i/graphenix-trace-format": "^2.0.1",
|
|
71
71
|
"@x12i/logxer": "^4.6.0",
|
|
72
72
|
"@x12i/memorix-descriptors": "^1.6.0",
|
|
73
73
|
"@x12i/memorix-retrieval": "^1.11.2",
|