@exellix/graph-engine 8.0.0 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/README.md +11 -12
  3. package/dist/src/compile/authoringDocumentHelpers.d.ts +9 -0
  4. package/dist/src/compile/authoringDocumentHelpers.js +18 -0
  5. package/dist/src/compile/compileExellixExecutablePlan.d.ts +8 -0
  6. package/dist/src/compile/compileExellixExecutablePlan.js +75 -0
  7. package/dist/src/index.d.ts +4 -6
  8. package/dist/src/index.js +2 -4
  9. package/dist/src/runtime/ExellixGraphRuntime.d.ts +11 -37
  10. package/dist/src/runtime/ExellixGraphRuntime.js +78 -173
  11. package/dist/src/runtime/aiTasksStrategyPhases.js +7 -3
  12. package/dist/src/runtime/buildAiTasksRunTaskRequest.d.ts +6 -8
  13. package/dist/src/runtime/buildAiTasksRunTaskRequest.js +2 -7
  14. package/dist/src/runtime/executionMatrixHost.d.ts +6 -3
  15. package/dist/src/runtime/executionMatrixHost.js +6 -4
  16. package/dist/src/runtime/runTaskNodePlan.d.ts +15 -0
  17. package/dist/src/runtime/runTaskNodePlan.js +46 -0
  18. package/dist/src/runtime/studioGraphExecuteRequest.d.ts +5 -30
  19. package/dist/src/runtime/studioGraphExecuteRequest.js +14 -50
  20. package/dist/src/runtime/taskNodeRunTaskPreflight.d.ts +7 -5
  21. package/dist/src/runtime/taskNodeRunTaskPreflight.js +31 -26
  22. package/dist/src/types/refs.d.ts +1 -1
  23. package/dist/testkit/authoringGraphFixtures.d.ts +8 -0
  24. package/dist/testkit/authoringGraphFixtures.js +249 -0
  25. package/dist/testkit/buildExecuteGraphInput.d.ts +3 -3
  26. package/dist/testkit/buildExecuteGraphInput.js +8 -4
  27. package/dist/testkit/flatGraphToAuthoring.d.ts +29 -0
  28. package/dist/testkit/flatGraphToAuthoring.js +281 -0
  29. package/dist/testkit/index.d.ts +3 -0
  30. package/dist/testkit/index.js +3 -0
  31. package/dist/testkit/runTaskNodePlanAssertions.d.ts +34 -0
  32. package/dist/testkit/runTaskNodePlanAssertions.js +32 -0
  33. package/package.json +8 -7
  34. package/dist/src/adapters/compileExellixExecutablePlan.d.ts +0 -8
  35. package/dist/src/adapters/compileExellixExecutablePlan.js +0 -18
  36. package/dist/src/adapters/migrateExellixGraphModelToAuthoring.d.ts +0 -6
  37. package/dist/src/adapters/migrateExellixGraphModelToAuthoring.js +0 -273
  38. package/dist/src/adapters/patchFinalizerPlans.d.ts +0 -7
  39. package/dist/src/adapters/patchFinalizerPlans.js +0 -63
  40. package/dist/src/runtime/graphResponseMigration.d.ts +0 -7
  41. package/dist/src/runtime/graphResponseMigration.js +0 -44
@@ -2,16 +2,12 @@ import { createExecutionTrace, appendExecutionEvent, validateExecutionTrace } fr
2
2
  import { preparePlanExecuteEntry, computePlanAudit } from "../plan/planExecuteEntry.js";
3
3
  import { embeddedGraphToExellixGraph } from "../plan/embeddedGraphToExellixGraph.js";
4
4
  import { graphAiModelConfigFromFinalizerPlan, graphAiModelConfigFromNodePlan } from "../plan/planModelConfig.js";
5
- import { executionPipelineFromNodePlan } from "../plan/planExecutionPipeline.js";
6
5
  import { applyNodePlanInvoke, finalizerPlanForId, nodePlanForId } from "../plan/applyNodePlanInvoke.js";
7
6
  import { evaluateDeferredNodeGate, evaluateDeferredEdgeGate, nodeDeferredGate, hasPlanConditionalEdges, evaluatePlanEntryGates, planNeedsRunx, } from "../plan/planDeferredGates.js";
8
7
  import { mergeExecutionObject, copyExecutionContextFields, } from "./memory.js";
9
8
  import { buildAiTasksRunTaskRequest, extractRunTaskStrategyOverrides, resolveJobTypeId, } from "./buildAiTasksRunTaskRequest.js";
10
9
  import { runTaskResponseSucceeded } from "./runTaskResponse.js";
11
- import { getAiTaskProfileStrategyKeys, runEngineAiTasksStrategyPhase, } from "./aiTasksStrategyPhases.js";
12
10
  import { mergeGraphDocumentModel, EXELLIX_GRAPH_MODEL_VARIABLE_KEY, } from "../types/refs.js";
13
- import { normalizeSynthesizedContextConfig } from "./synthesizedContextPipeline.js";
14
- import { resolveExecutionPipelineForTaskNode } from "./resolveExecutionPipelineForTaskNode.js";
15
11
  import { resolveTaskNodeInputsForRunTask } from "./resolveTaskNodeInputs.js";
16
12
  import { assertAiTasksNodeExtensionsValid } from "../inspection/validateAiTasksNodeExtensions.js";
17
13
  import { buildRunTaskMainInput, extractCallerInputsBag } from "./resolveGraphEngineMemoryPaths.js";
@@ -25,13 +21,13 @@ import { executeDeterministicFinalizer, executeSynthesizeFinalizer } from "./fin
25
21
  import { createFinalizerError } from "./finalizers/errors.js";
26
22
  import { assertCanonicalGraphRuntimeObject } from "./validateCanonicalGraphRuntime.js";
27
23
  import { applyGraphResponseDefinition } from "./graphResponseMapping.js";
28
- import { migrateLegacyGraphResponse } from "./graphResponseMigration.js";
29
24
  import { buildAiTasksObservabilityRecord } from "./aiTasksObservability.js";
30
- import { buildMainLlmCallForRunTask, buildRunTaskIdentityEnvelope, shouldForwardRunTaskTraceMode, } from "./runTaskAugments.js";
25
+ import { buildRunTaskIdentityEnvelope, shouldForwardRunTaskTraceMode, } from "./runTaskAugments.js";
31
26
  import { buildRunLog, extractLogxerCorrelationFromMetadata, extractTaskRunLogFromMetadata, resolveRunLogLimits, } from "./buildRunLog.js";
32
27
  import { setRuntimeObjectsLastJobId, summarizeRuntimeObjectsForPlayground } from "./runtimeObjects.js";
33
28
  import { DebugLogAbstract, bindGraphEngineRunLogxer, clearGraphEngineRunLogxer, createGraphEngineLogxer, ensureGraphEngineLogxerOnRuntimeObjects, logGraphEngineErrorCode, patchGraphNodeLogContext, runGraphWithLogContext, traceExecutionMemory, } from "./graphEngineLogxer.js";
34
29
  import { runWithAiTasksStackLogging } from "@exellix/ai-tasks";
30
+ import { nodePlanFromFinalizerPlan, patchNodePlanMainModelFromWire, resolveRunTaskNodePlan, } from "./runTaskNodePlan.js";
35
31
  import { assertHostJobId, newGraphRunTaskId } from "./graphRunIdentity.js";
36
32
  import { resolveTaskKey } from "./resolveTaskKey.js";
37
33
  import { buildPredicateEvalContextForNode, mirrorTaskVariablesOnExecution, readExecutionVariableBuckets, seedGraphVariableBucketsFromRuntime, } from "./variables.js";
@@ -367,7 +363,6 @@ export function createExellixGraphRuntime(opts) {
367
363
  });
368
364
  }
369
365
  const wireModelConfig = toRunTaskModelConfig(effectiveModelConfig);
370
- const effectiveLlmCall = buildMainLlmCallForRunTask(wireModelConfig, input.node?.taskConfiguration?.llmCall);
371
366
  const forwardRunTaskTrace = shouldForwardRunTaskTraceMode({
372
367
  runTaskExecutionMode: input.runTaskExecutionMode ?? opts.runTaskExecutionMode,
373
368
  });
@@ -402,34 +397,43 @@ export function createExellixGraphRuntime(opts) {
402
397
  config: finalizer.config,
403
398
  executionMemory: execution,
404
399
  outputsMemory,
405
- runTask: (req) => opts.tasksClient.runTask({
406
- ...req,
407
- agentId: input.job?.agentId ?? "standalone-agent",
408
- jobTypeId: resolveJobTypeId(input.job),
409
- taskTypeId: `exellix-graph-finalizer:${String(finalizer.config?.utilityKey ?? "synthesize")}`,
410
- coreSkillId: String(finalizer.id),
411
- nodeId: String(finalizer.id),
412
- graphId: input.graphId,
413
- masterSkillId: input.graphId,
414
- masterSkillActivityId: `${lifecycleJobId}:${finalizer.id}`,
415
- input: req.input ?? {},
416
- identity: {
417
- ...finalizerIdentity,
418
- ...(req.identity &&
419
- typeof req.identity === "object" &&
420
- !Array.isArray(req.identity)
421
- ? req.identity
400
+ runTask: (req) => {
401
+ const utilityKey = String(req.skillKey ??
402
+ finalizer.config?.utilityKey ??
403
+ "synthesize");
404
+ return opts.tasksClient.runTask({
405
+ ...req,
406
+ agentId: input.job?.agentId ?? "standalone-agent",
407
+ jobTypeId: resolveJobTypeId(input.job),
408
+ taskTypeId: `exellix-graph-finalizer:${utilityKey}`,
409
+ coreSkillId: String(finalizer.id),
410
+ nodeId: String(finalizer.id),
411
+ graphId: input.graphId,
412
+ masterSkillId: input.graphId,
413
+ masterSkillActivityId: `${lifecycleJobId}:${finalizer.id}`,
414
+ input: req.input ?? {},
415
+ skillKey: utilityKey,
416
+ executionStrategies: [],
417
+ nodePlan: nodePlanFromFinalizerPlan({
418
+ finalizerId: String(finalizer.id),
419
+ utilityKey,
420
+ finalizerPlan: input.finalizerPlan,
421
+ }),
422
+ identity: {
423
+ ...finalizerIdentity,
424
+ ...(req.identity &&
425
+ typeof req.identity === "object" &&
426
+ !Array.isArray(req.identity)
427
+ ? req.identity
428
+ : {}),
429
+ kind: "finalizer",
430
+ },
431
+ ...(forwardRunTaskTrace ? { executionMode: "trace" } : {}),
432
+ ...((input.runTaskDiagnostics ?? opts.runTaskDiagnostics) != null
433
+ ? { diagnostics: input.runTaskDiagnostics ?? opts.runTaskDiagnostics }
422
434
  : {}),
423
- kind: "finalizer",
424
- },
425
- modelConfig: wireModelConfig,
426
- llmCall: effectiveLlmCall,
427
- executionStrategies: [],
428
- ...(forwardRunTaskTrace ? { executionMode: "trace" } : {}),
429
- ...((input.runTaskDiagnostics ?? opts.runTaskDiagnostics) != null
430
- ? { diagnostics: input.runTaskDiagnostics ?? opts.runTaskDiagnostics }
431
- : {}),
432
- }),
435
+ });
436
+ },
433
437
  context: {
434
438
  graphId: input.graphId,
435
439
  jobId: input.job?.jobId,
@@ -659,34 +663,6 @@ export function createExellixGraphRuntime(opts) {
659
663
  markNodeLifecycleEmitted(pe);
660
664
  throw pe;
661
665
  }
662
- let executionPipeline;
663
- try {
664
- executionPipeline = resolveExecutionPipelineForTaskNode({
665
- node: input.node,
666
- optionsExecutionPipeline: input.graphExecutionPipeline,
667
- executionExecutionPipeline: input.execution?.executionPipeline,
668
- });
669
- }
670
- catch (pe) {
671
- if (input.eventEmitter) {
672
- input.eventEmitter.emit(createNodeFailEvent(lifecycleJobId, input.graphId, graphRunTaskId, input.node, skillKey, {
673
- error: { message: pe?.message, code: pe?.code, stack: pe?.stack },
674
- memoryAfter: { jobMemory: input.jobMemory, taskMemory: input.taskMemory, execution },
675
- response: undefined,
676
- }, input.jobCorrelation));
677
- }
678
- const err = new Error(pe?.message ?? "Execution pipeline resolution failed");
679
- err.code = pe?.code ?? "INPUT_SYNTHESIS_PIPELINE_CONFLICT";
680
- err.nodeId = input.node?.id;
681
- markNodeLifecycleEmitted(err);
682
- throw err;
683
- }
684
- const hasSynthesizedContextPreStep = Array.isArray(executionPipeline) &&
685
- executionPipeline.some((s) => s.phase === "pre" && s.type === "synthesized-context");
686
- const preStepConfig = hasSynthesizedContextPreStep && Array.isArray(executionPipeline)
687
- ? normalizeSynthesizedContextConfig(executionPipeline.find((s) => s.phase === "pre" && s.type === "synthesized-context")?.config)
688
- : undefined;
689
- const includeContextInPrompt = hasSynthesizedContextPreStep && preStepConfig?.autoEnableContext !== true;
690
666
  const executionRec = execution;
691
667
  mirrorTaskVariablesOnExecution({
692
668
  execution: executionRec,
@@ -695,12 +671,6 @@ export function createExellixGraphRuntime(opts) {
695
671
  });
696
672
  const variableBuckets = readExecutionVariableBuckets(executionRec);
697
673
  const jobVariables = variableBuckets.jobVariables;
698
- const hasExistingSynthesizedContext = execution != null &&
699
- typeof execution === "object" &&
700
- execution.synthesizedContext != null;
701
- const clearSynthForTask = input.clearSynthesizedContextPerNode === true &&
702
- hasSynthesizedContextPreStep &&
703
- hasExistingSynthesizedContext;
704
674
  const nodeBindings = resolveTaskNodeInputsForRunTask({
705
675
  node: input.node,
706
676
  execution: executionRec,
@@ -721,51 +691,22 @@ export function createExellixGraphRuntime(opts) {
721
691
  const metaTk = input.node?.taskConfiguration?.taskKind;
722
692
  const taskKindForward = metaTk === "decision" || metaTk === "utility" || metaTk === "content" ? metaTk : undefined;
723
693
  const autoValDec = input.node?.taskConfiguration?.autoValidateDecisionOutput;
724
- const strategyKeys = getAiTaskProfileStrategyKeys(input.node?.taskConfiguration);
725
- const startedAt = Date.now();
726
- if (strategyKeys.preStrategyKey != null) {
727
- const preRes = await runEngineAiTasksStrategyPhase({
728
- phase: "pre",
729
- strategySkillKey: strategyKeys.preStrategyKey,
730
- parentSkillKey: skillKey,
731
- aiTasks: opts.tasksClient,
732
- job: input.job,
733
- nodeId: String(input.node.id),
734
- graphId: input.graphId,
735
- taskId: graphRunTaskId,
736
- runTaskJobId: lifecycleJobId,
737
- execution: executionRec,
738
- variables: jobVariables,
739
- jobMemory: input.jobMemory,
740
- taskMemory: input.taskMemory,
741
- jobContext,
742
- prevNodeId: input.prevNodeId,
743
- modelConfig: effectiveModelConfig,
744
- runTaskIdentity: runTaskIdentityBase,
745
- nodeTaskConfiguration: input.node?.taskConfiguration,
746
- forwardRunTaskTrace,
747
- runTaskDiagnostics: (input.runTaskDiagnostics ?? opts.runTaskDiagnostics),
748
- nodeTimeoutMs: input.nodeTimeoutMs,
749
- });
750
- if (!preRes.ok) {
751
- const err = new Error(preRes.response.error?.message ?? "ENGINE_PRE_STRATEGY_FAILED");
752
- err.code = preRes.response.error?.code ?? "ENGINE_PRE_STRATEGY_FAILED";
753
- err.nodeId = input.node?.id;
754
- if (input.eventEmitter) {
755
- input.eventEmitter.emit(createNodeFailEvent(lifecycleJobId, input.graphId, graphRunTaskId, input.node, skillKey, {
756
- error: {
757
- message: err.message,
758
- code: err.code,
759
- ...(preRes.response.error != null ? { details: preRes.response.error } : {}),
760
- },
761
- memoryAfter: { jobMemory: input.jobMemory, taskMemory: input.taskMemory, execution },
762
- response: preRes.response,
763
- }, input.jobCorrelation));
764
- }
765
- markNodeLifecycleEmitted(err);
766
- throw err;
767
- }
694
+ let runTaskNodePlan = resolveRunTaskNodePlan({
695
+ nodePlan: input.nodePlan,
696
+ skillKey,
697
+ nodeId: String(input.node.id),
698
+ });
699
+ if (!input.nodePlan) {
700
+ runTaskNodePlan = patchNodePlanMainModelFromWire(runTaskNodePlan, wireModelConfig);
768
701
  }
702
+ const startedAt = Date.now();
703
+ const hasSynthesizedContextPreStep = runTaskNodePlan.executionUnits.some((u) => u.unitKind === "externalPreUtility" || u.unitKind === "pipelinePhase");
704
+ const hasExistingSynthesizedContext = execution != null &&
705
+ typeof execution === "object" &&
706
+ execution.synthesizedContext != null;
707
+ const clearSynthForTask = input.clearSynthesizedContextPerNode === true &&
708
+ hasSynthesizedContextPreStep &&
709
+ hasExistingSynthesizedContext;
769
710
  const executionForTask = clearSynthForTask
770
711
  ? (() => {
771
712
  const c = { ...executionRec };
@@ -831,7 +772,18 @@ export function createExellixGraphRuntime(opts) {
831
772
  }
832
773
  const runTaskJobMemory = mergeKnowledgePatchIntoRunTaskMemory(input.jobMemory, input.jobKnowledgePatch);
833
774
  const runTaskTaskMemory = mergeKnowledgePatchIntoRunTaskMemory(input.taskMemory, input.taskKnowledgePatch);
834
- const metaStrats = input.node?.taskConfiguration?.executionStrategies;
775
+ const metaStrats = runTaskNodePlan.invokeContract?.pipeline &&
776
+ typeof runTaskNodePlan.invokeContract.pipeline === "object" &&
777
+ Array.isArray(runTaskNodePlan.invokeContract.pipeline.executionStrategies)
778
+ ? runTaskNodePlan.invokeContract.pipeline
779
+ .executionStrategies
780
+ : input.node?.taskConfiguration?.executionStrategies;
781
+ const outputValidationFromPlan = runTaskNodePlan.invokeContract?.validation &&
782
+ typeof runTaskNodePlan.invokeContract.validation === "object" &&
783
+ "aiTasksOutputValidation" in runTaskNodePlan.invokeContract.validation
784
+ ? runTaskNodePlan.invokeContract.validation
785
+ .aiTasksOutputValidation
786
+ : undefined;
835
787
  const req = buildAiTasksRunTaskRequest({
836
788
  skillKey,
837
789
  job: input.job,
@@ -848,19 +800,16 @@ export function createExellixGraphRuntime(opts) {
848
800
  executionMemory: executionForTask,
849
801
  jobContext,
850
802
  prevNodeId: input.prevNodeId,
851
- executionPipeline: executionPipeline,
852
- includeContextInPrompt: includeContextInPrompt === true ? true : undefined,
853
803
  narrix: narrix ?? undefined,
854
804
  ...extractRunTaskStrategyOverrides(input.node?.taskConfiguration),
855
- outputValidation: input.node?.taskConfiguration?.aiTasksOutputValidation != null &&
856
- typeof input.node.taskConfiguration.aiTasksOutputValidation === "object" &&
857
- input.node.taskConfiguration.aiTasksOutputValidation !== null &&
858
- "schema" in input.node.taskConfiguration.aiTasksOutputValidation
859
- ? input.node.taskConfiguration.aiTasksOutputValidation
860
- : undefined,
805
+ outputValidation: outputValidationFromPlan ??
806
+ (input.node?.taskConfiguration?.aiTasksOutputValidation != null &&
807
+ typeof input.node.taskConfiguration.aiTasksOutputValidation === "object" &&
808
+ input.node.taskConfiguration.aiTasksOutputValidation !== null &&
809
+ "schema" in input.node.taskConfiguration.aiTasksOutputValidation
810
+ ? input.node.taskConfiguration.aiTasksOutputValidation
811
+ : undefined),
861
812
  diagnostics: (input.runTaskDiagnostics ?? opts.runTaskDiagnostics),
862
- modelConfig: wireModelConfig,
863
- llmCall: effectiveLlmCall,
864
813
  identity: buildRunTaskIdentityEnvelope({
865
814
  base: runTaskIdentityBase,
866
815
  nodeMeta: input.node?.taskConfiguration,
@@ -875,6 +824,8 @@ export function createExellixGraphRuntime(opts) {
875
824
  executionStrategies: Array.isArray(metaStrats) ? metaStrats : [],
876
825
  xynthesized: xynthesizedOutboundForNode(executionRec, String(input.node.id)),
877
826
  smartInput: input.node.smartInput,
827
+ nodePlan: runTaskNodePlan,
828
+ ...(input.executionTrace != null ? { executionTrace: input.executionTrace } : {}),
878
829
  });
879
830
  // TRACE: Validate request object before sending
880
831
  traceExecutionMemory('executeNode', 'runTask request built', {
@@ -1022,53 +973,6 @@ export function createExellixGraphRuntime(opts) {
1022
973
  };
1023
974
  // Handle execution object updates from response (patch merged above)
1024
975
  // Note: We don't modify jobMemory or taskMemory - they're set before the job starts and passed through as-is
1025
- if (strategyKeys.postStrategyKey != null) {
1026
- const postExec = updatedExecution != null && typeof updatedExecution === "object" && !Array.isArray(updatedExecution)
1027
- ? updatedExecution
1028
- : executionRec;
1029
- const postRes = await runEngineAiTasksStrategyPhase({
1030
- phase: "post",
1031
- strategySkillKey: strategyKeys.postStrategyKey,
1032
- parentSkillKey: skillKey,
1033
- aiTasks: opts.tasksClient,
1034
- job: input.job,
1035
- nodeId: String(input.node.id),
1036
- graphId: input.graphId,
1037
- taskId: graphRunTaskId,
1038
- runTaskJobId: lifecycleJobId,
1039
- execution: postExec,
1040
- variables: jobVariables,
1041
- jobMemory: input.jobMemory,
1042
- taskMemory: input.taskMemory,
1043
- jobContext,
1044
- prevNodeId: input.prevNodeId,
1045
- modelConfig: effectiveModelConfig,
1046
- runTaskIdentity: runTaskIdentityBase,
1047
- nodeTaskConfiguration: input.node?.taskConfiguration,
1048
- forwardRunTaskTrace,
1049
- runTaskDiagnostics: (input.runTaskDiagnostics ?? opts.runTaskDiagnostics),
1050
- nodeTimeoutMs: input.nodeTimeoutMs,
1051
- });
1052
- if (!postRes.ok) {
1053
- const err = new Error(postRes.response.error?.message ?? "ENGINE_POST_STRATEGY_FAILED");
1054
- err.code = postRes.response.error?.code ?? "ENGINE_POST_STRATEGY_FAILED";
1055
- err.nodeId = input.node?.id;
1056
- if (input.eventEmitter) {
1057
- input.eventEmitter.emit(createNodeFailEvent(lifecycleJobId, input.graphId, graphRunTaskId, input.node, skillKey, {
1058
- error: {
1059
- message: err.message,
1060
- code: err.code,
1061
- ...(postRes.response.error != null ? { details: postRes.response.error } : {}),
1062
- },
1063
- memoryAfter: { jobMemory: input.jobMemory, taskMemory: input.taskMemory, execution: postExec },
1064
- response: postRes.response,
1065
- }, input.jobCorrelation));
1066
- }
1067
- markNodeLifecycleEmitted(err);
1068
- throw err;
1069
- }
1070
- updatedExecution = postExec;
1071
- }
1072
976
  // TRACE: Log execution object from response
1073
977
  traceExecutionMemory('executeNode', 'Processing runTask response', {
1074
978
  nodeId: input.node?.id,
@@ -1160,7 +1064,7 @@ export function createExellixGraphRuntime(opts) {
1160
1064
  const { plan: suppliedPlan, runtime } = input;
1161
1065
  const { plan } = preparePlanExecuteEntry(suppliedPlan, runtime);
1162
1066
  const materialized = embeddedGraphToExellixGraph(plan);
1163
- const graph = migrateLegacyGraphResponse(materialized).graph;
1067
+ const graph = materialized;
1164
1068
  const merged = mergeExellixGraphRuntimeInvocation(runtime, opts);
1165
1069
  const scheduling = plan.schedulingPolicy;
1166
1070
  const plannerMode = scheduling?.mode ?? runtime.mode;
@@ -1650,12 +1554,14 @@ export function createExellixGraphRuntime(opts) {
1650
1554
  : nodePlanEntryResolved && node.type !== "finalizer"
1651
1555
  ? graphAiModelConfigFromNodePlan(nodePlanEntryResolved)
1652
1556
  : undefined;
1653
- const nodeExecutionPipeline = nodePlanEntryResolved != null ? executionPipelineFromNodePlan(nodePlanEntryResolved) : undefined;
1654
1557
  const r = await executeNode({
1655
1558
  graphId: resolvedGraphId,
1656
1559
  graph,
1657
1560
  graphRunTaskId: graphTaskId,
1658
1561
  node: taskNodeForExecute,
1562
+ nodePlan: nodePlanEntryResolved,
1563
+ finalizerPlan: finalizerPlanEntryResolved,
1564
+ executionTrace,
1659
1565
  job,
1660
1566
  jobMemory: currentJobMemory,
1661
1567
  taskMemory: nodeTaskMemory,
@@ -1669,7 +1575,6 @@ export function createExellixGraphRuntime(opts) {
1669
1575
  runTaskIdentity: merged.runTaskIdentity,
1670
1576
  runTaskExecutionMode: merged.runTaskExecutionMode,
1671
1577
  runTaskDiagnostics: merged.runTaskDiagnostics,
1672
- graphExecutionPipeline: nodeExecutionPipeline ?? merged.executionPipeline,
1673
1578
  skillKeyResolution: merged.skillKeyResolution,
1674
1579
  nodeTimeoutMs: merged.nodeTimeoutMs,
1675
1580
  clearSynthesizedContextPerNode: merged.clearSynthesizedContextPerNode,
@@ -3,6 +3,7 @@ import { buildAiTasksRunTaskRequest } from './buildAiTasksRunTaskRequest.js';
3
3
  import { buildRunTaskIdentityEnvelope } from './runTaskAugments.js';
4
4
  import { runTaskResponseSucceeded } from './runTaskResponse.js';
5
5
  import { withTimeout } from './withTimeout.js';
6
+ import { patchNodePlanMainModelFromWire, resolveRunTaskNodePlan } from './runTaskNodePlan.js';
6
7
  function nonEmptyStrategyKey(v) {
7
8
  return typeof v === 'string' && v.trim().length > 0;
8
9
  }
@@ -31,11 +32,15 @@ export async function runEngineAiTasksStrategyPhase(args) {
31
32
  const taskTypeIdOverride = args.phase === 'pre'
32
33
  ? `exellix-graph-xynthesis-pre:${args.parentSkillKey}`
33
34
  : `exellix-graph-xynthesis-post:${args.parentSkillKey}`;
35
+ const wireModelConfig = toRunTaskModelConfig(args.modelConfig);
36
+ const runTaskNodePlan = patchNodePlanMainModelFromWire(resolveRunTaskNodePlan({
37
+ skillKey: args.strategySkillKey,
38
+ nodeId: args.nodeId,
39
+ }), wireModelConfig);
34
40
  const req = buildAiTasksRunTaskRequest({
35
41
  skillKey: args.strategySkillKey,
36
42
  job: args.job,
37
43
  nodeId: args.nodeId,
38
- taskConfiguration: undefined,
39
44
  graphId: args.graphId,
40
45
  taskId: args.taskId,
41
46
  runTaskJobId: args.runTaskJobId,
@@ -52,14 +57,13 @@ export async function runEngineAiTasksStrategyPhase(args) {
52
57
  executionMemory: args.execution,
53
58
  jobContext: args.jobContext,
54
59
  prevNodeId: args.prevNodeId,
55
- executionPipeline: [{ phase: 'main', type: 'direct' }],
56
60
  executionStrategies: [],
57
- modelConfig: toRunTaskModelConfig(args.modelConfig),
58
61
  identity,
59
62
  ...(args.forwardRunTaskTrace ? { executionMode: 'trace' } : {}),
60
63
  ...(args.runTaskDiagnostics != null && { diagnostics: args.runTaskDiagnostics }),
61
64
  taskKind: 'utility',
62
65
  taskTypeIdOverride,
66
+ nodePlan: runTaskNodePlan,
63
67
  });
64
68
  const run = () => args.aiTasks.runTask(req);
65
69
  const response = await (args.nodeTimeoutMs
@@ -7,11 +7,10 @@
7
7
  * v7 closed schema: no root `executionType`, `outputConstraints`, `question`, or `jobInput`.
8
8
  * Graph-engine forwards optional `inputs` (caller bag, as-is) separately from `input` (MAIN as-is + node bindings) — see `.docs/CR-input-and-inputs-dual-root.md`.
9
9
  */
10
- import type { LlmCallConfig, RunTaskRequest } from '@exellix/ai-tasks';
10
+ import type { RunTaskRequest } from '@exellix/ai-tasks';
11
+ import type { GraphExecutionTraceV2, NodeExecutionPlan } from '@x12i/graphenix-executable-contracts';
11
12
  import type { SmartInputConfig, XynthesizedMemory } from '../types/aiTasksDerivedTypes.js';
12
13
  import type { Job } from '../types/refs.js';
13
- import type { RunTaskModelConfigWire } from './graphAiModelConfig.js';
14
- import type { ExecutionStepOption } from '../types/options.js';
15
14
  import type { ResolvedNarrixWirePayload } from '../types/narrix.js';
16
15
  /** Request/metadata keys that must never carry provider API secrets (env-only). */
17
16
  export declare const FORBIDDEN_RUN_TASK_SECRET_KEYS: readonly ["openrouterApiKey", "OPENROUTER_API_KEY", "OPEN_ROUTER_KEY", "apiKey", "api_key", "openRouterApiKey"];
@@ -43,14 +42,9 @@ export type BuildAiTasksRunTaskRequestArgs = {
43
42
  executionMemory?: Record<string, unknown>;
44
43
  jobContext?: Record<string, unknown>;
45
44
  prevNodeId?: string;
46
- executionPipeline?: ExecutionStepOption[];
47
- includeContextInPrompt?: boolean;
48
45
  narrix?: ResolvedNarrixWirePayload;
49
46
  outputValidation?: RunTaskRequest['outputValidation'];
50
47
  diagnostics?: RunTaskRequest['diagnostics'];
51
- /** Required on every `runTask` (@exellix/ai-tasks 8.4+). */
52
- modelConfig: RunTaskModelConfigWire;
53
- llmCall?: LlmCallConfig;
54
48
  identity?: Record<string, unknown>;
55
49
  executionMode?: 'default' | 'trace';
56
50
  taskKind?: RunTaskRequest['taskKind'];
@@ -65,6 +59,10 @@ export type BuildAiTasksRunTaskRequestArgs = {
65
59
  executionStrategies?: RunTaskRequest['executionStrategies'];
66
60
  xynthesized?: XynthesizedMemory;
67
61
  smartInput?: SmartInputConfig;
62
+ /** Frozen graphenix node plan — required for `@exellix/ai-tasks` ≥ 9 (`runTask` hot path). */
63
+ nodePlan: NodeExecutionPlan;
64
+ /** Optional graphenix v2 trace handle; ai-tasks appends unit / model invocation events. */
65
+ executionTrace?: GraphExecutionTraceV2;
68
66
  };
69
67
  export declare function resolveJobTypeId(job?: Job): string;
70
68
  export declare function resolveTaskTypeId(skillKey: string, nodeId: string, taskConfiguration?: Record<string, unknown>): string;
@@ -1,4 +1,3 @@
1
- import { buildRunTaskTaskConfigurationForward } from './buildRunTaskTaskConfigurationForward.js';
2
1
  import { normalizeSmartInputConfigForRunTask } from './smartInputPaths.js';
3
2
  /** Request/metadata keys that must never carry provider API secrets (env-only). */
4
3
  export const FORBIDDEN_RUN_TASK_SECRET_KEYS = [
@@ -135,11 +134,12 @@ export function buildAiTasksRunTaskRequest(args) {
135
134
  const masterSkillActivityId = `${args.runTaskJobId}:${args.nodeId}`;
136
135
  const executionStrategies = args.executionStrategies ?? [];
137
136
  const metaPassthrough = extractRunTaskMetadataPassthrough(args.taskConfiguration);
138
- const taskConfigurationForward = buildRunTaskTaskConfigurationForward(args.taskConfiguration);
139
137
  const smartInputForward = normalizeSmartInputConfigForRunTask(args.smartInput);
140
138
  const req = {
141
139
  ...metaPassthrough,
142
140
  skillKey: args.skillKey,
141
+ nodePlan: args.nodePlan,
142
+ ...(args.executionTrace != null ? { executionTrace: args.executionTrace } : {}),
143
143
  jobId: args.runTaskJobId,
144
144
  taskId: args.taskId,
145
145
  agentId,
@@ -162,13 +162,9 @@ export function buildAiTasksRunTaskRequest(args) {
162
162
  ...(args.executionMemory != null ? { executionMemory: args.executionMemory } : {}),
163
163
  ...(args.jobContext != null ? { jobContext: args.jobContext } : {}),
164
164
  ...(args.prevNodeId != null && args.prevNodeId !== '' ? { prevNodeId: args.prevNodeId } : {}),
165
- ...(args.executionPipeline != null ? { executionPipeline: args.executionPipeline } : {}),
166
- ...(args.includeContextInPrompt === true ? { includeContextInPrompt: true } : {}),
167
165
  ...(args.narrix != null ? { narrix: args.narrix } : {}),
168
166
  ...(args.outputValidation != null ? { outputValidation: args.outputValidation } : {}),
169
167
  ...(args.diagnostics != null ? { diagnostics: args.diagnostics } : {}),
170
- modelConfig: args.modelConfig,
171
- ...(args.llmCall != null ? { llmCall: args.llmCall } : {}),
172
168
  ...(args.identity != null ? { identity: args.identity } : {}),
173
169
  ...(args.executionMode != null ? { executionMode: args.executionMode } : {}),
174
170
  ...(args.taskKind != null ? { taskKind: args.taskKind } : {}),
@@ -179,7 +175,6 @@ export function buildAiTasksRunTaskRequest(args) {
179
175
  executionStrategies,
180
176
  ...(args.xynthesized != null ? { xynthesized: args.xynthesized } : {}),
181
177
  ...(smartInputForward != null ? { smartInput: smartInputForward } : {}),
182
- ...(taskConfigurationForward != null ? { taskConfiguration: taskConfigurationForward } : {}),
183
178
  };
184
179
  return req;
185
180
  }
@@ -2,15 +2,18 @@
2
2
  * Host helpers for execution-matrix style orchestrators (e.g. `@exellix/exellix-runtime`).
3
3
  *
4
4
  * Graph-engine does not call matrix claim APIs; the host injects `executeGraph` and supplies
5
- * a `{ model, runtime }` request with per-graph `GraphEntryContract` + seeded
5
+ * a `{ plan, runtime }` request with per-graph `GraphEntryContract` + seeded
6
6
  * `runtime.executionMemory` objects built here.
7
7
  */
8
+ import type { AuthoringGraphDocument } from '@x12i/graphenix-executable-contracts';
8
9
  import type { Graph, GraphEntryContract, GraphEntryExecutionInputSpec, Job } from '../types/refs.js';
9
10
  import type { ExellixGraphRuntimeOptions, ExecuteGraphInput, ExecuteGraphResult, GraphRuntimeObject } from './ExellixGraphRuntime.js';
10
11
  import type { GraphLoader } from './ExellixGraphRuntime.js';
12
+ export { resolveGraphEntryFromAuthoringDocument, authoringDocumentGraphId } from '../compile/authoringDocumentHelpers.js';
11
13
  /**
12
14
  * Reads Layer 01 contract from the canonical graph document (`metadata.graphEntry`).
13
- * Does not fetch Catalox or bundle stores those are host concerns before load.
15
+ * For execute-time materialized {@link Graph} (from plan). Authoring loaders should use
16
+ * {@link resolveGraphEntryFromAuthoringDocument}.
14
17
  */
15
18
  export declare function resolveGraphEntryFromGraph(graph: Graph): GraphEntryContract | undefined;
16
19
  /**
@@ -47,7 +50,7 @@ export type BuildExecutionSeedResult = {
47
50
  export declare function buildExecutionSeedFromGraphEntry(graphEntry: GraphEntryContract | undefined, sources?: BuildExecutionSeedSources): BuildExecutionSeedResult;
48
51
  /** Builds the canonical graph-engine execution request for matrix-style hosts. */
49
52
  export declare function buildGraphExecutionRequest(input: {
50
- model: Graph;
53
+ doc: AuthoringGraphDocument;
51
54
  runtime: GraphRuntimeObject;
52
55
  }): ExecuteGraphInput;
53
56
  /**
@@ -2,10 +2,10 @@
2
2
  * Host helpers for execution-matrix style orchestrators (e.g. `@exellix/exellix-runtime`).
3
3
  *
4
4
  * Graph-engine does not call matrix claim APIs; the host injects `executeGraph` and supplies
5
- * a `{ model, runtime }` request with per-graph `GraphEntryContract` + seeded
5
+ * a `{ plan, runtime }` request with per-graph `GraphEntryContract` + seeded
6
6
  * `runtime.executionMemory` objects built here.
7
7
  */
8
- import { compileExellixExecutablePlan } from '../adapters/compileExellixExecutablePlan.js';
8
+ import { compileExellixExecutablePlan } from '../compile/compileExellixExecutablePlan.js';
9
9
  import { mergeGraphDocumentModel } from '../types/refs.js';
10
10
  import { createExellixGraphRuntime } from './ExellixGraphRuntime.js';
11
11
  import { selectByPath, writeByPath } from './pathExpr.js';
@@ -15,9 +15,11 @@ function isExecutionInputSpec(spec) {
15
15
  function isValueInputSpec(spec) {
16
16
  return spec.kind !== 'execution' && typeof spec.path === 'string';
17
17
  }
18
+ export { resolveGraphEntryFromAuthoringDocument, authoringDocumentGraphId } from '../compile/authoringDocumentHelpers.js';
18
19
  /**
19
20
  * Reads Layer 01 contract from the canonical graph document (`metadata.graphEntry`).
20
- * Does not fetch Catalox or bundle stores those are host concerns before load.
21
+ * For execute-time materialized {@link Graph} (from plan). Authoring loaders should use
22
+ * {@link resolveGraphEntryFromAuthoringDocument}.
21
23
  */
22
24
  export function resolveGraphEntryFromGraph(graph) {
23
25
  const meta = mergeGraphDocumentModel(graph);
@@ -77,7 +79,7 @@ export function buildExecutionSeedFromGraphEntry(graphEntry, sources = {}) {
77
79
  /** Builds the canonical graph-engine execution request for matrix-style hosts. */
78
80
  export function buildGraphExecutionRequest(input) {
79
81
  return {
80
- plan: compileExellixExecutablePlan(input.model, input.runtime),
82
+ plan: compileExellixExecutablePlan(input.doc, input.runtime),
81
83
  runtime: input.runtime,
82
84
  };
83
85
  }
@@ -0,0 +1,15 @@
1
+ import type { FinalizerExecutionPlan, NodeExecutionPlan } from '@x12i/graphenix-executable-contracts';
2
+ import type { RunTaskModelConfigWire } from './graphAiModelConfig.js';
3
+ /** Resolve the frozen node plan required by `@exellix/ai-tasks` ≥ 9. */
4
+ export declare function resolveRunTaskNodePlan(args: {
5
+ nodePlan?: NodeExecutionPlan;
6
+ skillKey: string;
7
+ nodeId: string;
8
+ }): NodeExecutionPlan;
9
+ /** Standalone {@link executeNode} without compile: patch MAIN unit selection from resolved graph profiles. */
10
+ export declare function patchNodePlanMainModelFromWire(plan: NodeExecutionPlan, wire: RunTaskModelConfigWire): NodeExecutionPlan;
11
+ export declare function nodePlanFromFinalizerPlan(args: {
12
+ finalizerId: string;
13
+ utilityKey: string;
14
+ finalizerPlan?: FinalizerExecutionPlan;
15
+ }): NodeExecutionPlan;
@@ -0,0 +1,46 @@
1
+ import { minimalNodePlanForSkillKey } from '@exellix/ai-tasks';
2
+ function mainSkillUnit(plan) {
3
+ return plan.executionUnits.find((u) => u.unitKind === 'mainSkill');
4
+ }
5
+ function selectionFromWireSlot(value) {
6
+ if (typeof value !== 'string' || value.trim().length === 0)
7
+ return undefined;
8
+ return { kind: 'profileChoice', key: value.trim() };
9
+ }
10
+ /** Resolve the frozen node plan required by `@exellix/ai-tasks` ≥ 9. */
11
+ export function resolveRunTaskNodePlan(args) {
12
+ return args.nodePlan ?? minimalNodePlanForSkillKey(args.skillKey, args.nodeId);
13
+ }
14
+ /** Standalone {@link executeNode} without compile: patch MAIN unit selection from resolved graph profiles. */
15
+ export function patchNodePlanMainModelFromWire(plan, wire) {
16
+ const next = structuredClone(plan);
17
+ const main = mainSkillUnit(next);
18
+ const selection = selectionFromWireSlot(wire.skillModel);
19
+ if (main && selection) {
20
+ main.modelSelection = selection;
21
+ main.modelSlot = 'skillModel';
22
+ }
23
+ return next;
24
+ }
25
+ export function nodePlanFromFinalizerPlan(args) {
26
+ const slots = args.finalizerPlan?.modelSlots;
27
+ const plan = minimalNodePlanForSkillKey(args.utilityKey, args.finalizerId);
28
+ if (!slots)
29
+ return plan;
30
+ const main = mainSkillUnit(plan);
31
+ if (!main)
32
+ return plan;
33
+ const selection = slots.postActionModel?.selection ??
34
+ slots.skillModel?.selection ??
35
+ slots.preActionModel?.selection;
36
+ if (selection) {
37
+ main.modelSelection = selection;
38
+ main.modelSlot =
39
+ slots.postActionModel?.selection != null
40
+ ? 'postActionModel'
41
+ : slots.skillModel?.selection != null
42
+ ? 'skillModel'
43
+ : 'preActionModel';
44
+ }
45
+ return plan;
46
+ }