@exellix/graph-engine 8.0.1 → 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 (34) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +1 -1
  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 +4 -5
  6. package/dist/src/compile/compileExellixExecutablePlan.js +67 -16
  7. package/dist/src/index.d.ts +2 -5
  8. package/dist/src/index.js +1 -3
  9. package/dist/src/runtime/ExellixGraphRuntime.d.ts +11 -37
  10. package/dist/src/runtime/ExellixGraphRuntime.js +77 -171
  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 +5 -2
  15. package/dist/src/runtime/executionMatrixHost.js +4 -2
  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/testkit/authoringGraphFixtures.d.ts +8 -0
  23. package/dist/testkit/authoringGraphFixtures.js +249 -0
  24. package/dist/testkit/buildExecuteGraphInput.d.ts +3 -3
  25. package/dist/testkit/buildExecuteGraphInput.js +7 -3
  26. package/dist/testkit/flatGraphToAuthoring.d.ts +29 -0
  27. package/dist/testkit/flatGraphToAuthoring.js +281 -0
  28. package/dist/testkit/index.d.ts +3 -0
  29. package/dist/testkit/index.js +3 -0
  30. package/dist/testkit/runTaskNodePlanAssertions.d.ts +34 -0
  31. package/dist/testkit/runTaskNodePlanAssertions.js +32 -0
  32. package/package.json +8 -8
  33. package/dist/src/runtime/graphResponseMigration.d.ts +0 -7
  34. 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";
@@ -26,11 +22,12 @@ import { createFinalizerError } from "./finalizers/errors.js";
26
22
  import { assertCanonicalGraphRuntimeObject } from "./validateCanonicalGraphRuntime.js";
27
23
  import { applyGraphResponseDefinition } from "./graphResponseMapping.js";
28
24
  import { buildAiTasksObservabilityRecord } from "./aiTasksObservability.js";
29
- import { buildMainLlmCallForRunTask, buildRunTaskIdentityEnvelope, shouldForwardRunTaskTraceMode, } from "./runTaskAugments.js";
25
+ import { buildRunTaskIdentityEnvelope, shouldForwardRunTaskTraceMode, } from "./runTaskAugments.js";
30
26
  import { buildRunLog, extractLogxerCorrelationFromMetadata, extractTaskRunLogFromMetadata, resolveRunLogLimits, } from "./buildRunLog.js";
31
27
  import { setRuntimeObjectsLastJobId, summarizeRuntimeObjectsForPlayground } from "./runtimeObjects.js";
32
28
  import { DebugLogAbstract, bindGraphEngineRunLogxer, clearGraphEngineRunLogxer, createGraphEngineLogxer, ensureGraphEngineLogxerOnRuntimeObjects, logGraphEngineErrorCode, patchGraphNodeLogContext, runGraphWithLogContext, traceExecutionMemory, } from "./graphEngineLogxer.js";
33
29
  import { runWithAiTasksStackLogging } from "@exellix/ai-tasks";
30
+ import { nodePlanFromFinalizerPlan, patchNodePlanMainModelFromWire, resolveRunTaskNodePlan, } from "./runTaskNodePlan.js";
34
31
  import { assertHostJobId, newGraphRunTaskId } from "./graphRunIdentity.js";
35
32
  import { resolveTaskKey } from "./resolveTaskKey.js";
36
33
  import { buildPredicateEvalContextForNode, mirrorTaskVariablesOnExecution, readExecutionVariableBuckets, seedGraphVariableBucketsFromRuntime, } from "./variables.js";
@@ -366,7 +363,6 @@ export function createExellixGraphRuntime(opts) {
366
363
  });
367
364
  }
368
365
  const wireModelConfig = toRunTaskModelConfig(effectiveModelConfig);
369
- const effectiveLlmCall = buildMainLlmCallForRunTask(wireModelConfig, input.node?.taskConfiguration?.llmCall);
370
366
  const forwardRunTaskTrace = shouldForwardRunTaskTraceMode({
371
367
  runTaskExecutionMode: input.runTaskExecutionMode ?? opts.runTaskExecutionMode,
372
368
  });
@@ -401,34 +397,43 @@ export function createExellixGraphRuntime(opts) {
401
397
  config: finalizer.config,
402
398
  executionMemory: execution,
403
399
  outputsMemory,
404
- runTask: (req) => opts.tasksClient.runTask({
405
- ...req,
406
- agentId: input.job?.agentId ?? "standalone-agent",
407
- jobTypeId: resolveJobTypeId(input.job),
408
- taskTypeId: `exellix-graph-finalizer:${String(finalizer.config?.utilityKey ?? "synthesize")}`,
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
- identity: {
416
- ...finalizerIdentity,
417
- ...(req.identity &&
418
- typeof req.identity === "object" &&
419
- !Array.isArray(req.identity)
420
- ? 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 }
421
434
  : {}),
422
- kind: "finalizer",
423
- },
424
- modelConfig: wireModelConfig,
425
- llmCall: effectiveLlmCall,
426
- executionStrategies: [],
427
- ...(forwardRunTaskTrace ? { executionMode: "trace" } : {}),
428
- ...((input.runTaskDiagnostics ?? opts.runTaskDiagnostics) != null
429
- ? { diagnostics: input.runTaskDiagnostics ?? opts.runTaskDiagnostics }
430
- : {}),
431
- }),
435
+ });
436
+ },
432
437
  context: {
433
438
  graphId: input.graphId,
434
439
  jobId: input.job?.jobId,
@@ -658,34 +663,6 @@ export function createExellixGraphRuntime(opts) {
658
663
  markNodeLifecycleEmitted(pe);
659
664
  throw pe;
660
665
  }
661
- let executionPipeline;
662
- try {
663
- executionPipeline = resolveExecutionPipelineForTaskNode({
664
- node: input.node,
665
- optionsExecutionPipeline: input.graphExecutionPipeline,
666
- executionExecutionPipeline: input.execution?.executionPipeline,
667
- });
668
- }
669
- catch (pe) {
670
- if (input.eventEmitter) {
671
- input.eventEmitter.emit(createNodeFailEvent(lifecycleJobId, input.graphId, graphRunTaskId, input.node, skillKey, {
672
- error: { message: pe?.message, code: pe?.code, stack: pe?.stack },
673
- memoryAfter: { jobMemory: input.jobMemory, taskMemory: input.taskMemory, execution },
674
- response: undefined,
675
- }, input.jobCorrelation));
676
- }
677
- const err = new Error(pe?.message ?? "Execution pipeline resolution failed");
678
- err.code = pe?.code ?? "INPUT_SYNTHESIS_PIPELINE_CONFLICT";
679
- err.nodeId = input.node?.id;
680
- markNodeLifecycleEmitted(err);
681
- throw err;
682
- }
683
- const hasSynthesizedContextPreStep = Array.isArray(executionPipeline) &&
684
- executionPipeline.some((s) => s.phase === "pre" && s.type === "synthesized-context");
685
- const preStepConfig = hasSynthesizedContextPreStep && Array.isArray(executionPipeline)
686
- ? normalizeSynthesizedContextConfig(executionPipeline.find((s) => s.phase === "pre" && s.type === "synthesized-context")?.config)
687
- : undefined;
688
- const includeContextInPrompt = hasSynthesizedContextPreStep && preStepConfig?.autoEnableContext !== true;
689
666
  const executionRec = execution;
690
667
  mirrorTaskVariablesOnExecution({
691
668
  execution: executionRec,
@@ -694,12 +671,6 @@ export function createExellixGraphRuntime(opts) {
694
671
  });
695
672
  const variableBuckets = readExecutionVariableBuckets(executionRec);
696
673
  const jobVariables = variableBuckets.jobVariables;
697
- const hasExistingSynthesizedContext = execution != null &&
698
- typeof execution === "object" &&
699
- execution.synthesizedContext != null;
700
- const clearSynthForTask = input.clearSynthesizedContextPerNode === true &&
701
- hasSynthesizedContextPreStep &&
702
- hasExistingSynthesizedContext;
703
674
  const nodeBindings = resolveTaskNodeInputsForRunTask({
704
675
  node: input.node,
705
676
  execution: executionRec,
@@ -720,51 +691,22 @@ export function createExellixGraphRuntime(opts) {
720
691
  const metaTk = input.node?.taskConfiguration?.taskKind;
721
692
  const taskKindForward = metaTk === "decision" || metaTk === "utility" || metaTk === "content" ? metaTk : undefined;
722
693
  const autoValDec = input.node?.taskConfiguration?.autoValidateDecisionOutput;
723
- const strategyKeys = getAiTaskProfileStrategyKeys(input.node?.taskConfiguration);
724
- const startedAt = Date.now();
725
- if (strategyKeys.preStrategyKey != null) {
726
- const preRes = await runEngineAiTasksStrategyPhase({
727
- phase: "pre",
728
- strategySkillKey: strategyKeys.preStrategyKey,
729
- parentSkillKey: skillKey,
730
- aiTasks: opts.tasksClient,
731
- job: input.job,
732
- nodeId: String(input.node.id),
733
- graphId: input.graphId,
734
- taskId: graphRunTaskId,
735
- runTaskJobId: lifecycleJobId,
736
- execution: executionRec,
737
- variables: jobVariables,
738
- jobMemory: input.jobMemory,
739
- taskMemory: input.taskMemory,
740
- jobContext,
741
- prevNodeId: input.prevNodeId,
742
- modelConfig: effectiveModelConfig,
743
- runTaskIdentity: runTaskIdentityBase,
744
- nodeTaskConfiguration: input.node?.taskConfiguration,
745
- forwardRunTaskTrace,
746
- runTaskDiagnostics: (input.runTaskDiagnostics ?? opts.runTaskDiagnostics),
747
- nodeTimeoutMs: input.nodeTimeoutMs,
748
- });
749
- if (!preRes.ok) {
750
- const err = new Error(preRes.response.error?.message ?? "ENGINE_PRE_STRATEGY_FAILED");
751
- err.code = preRes.response.error?.code ?? "ENGINE_PRE_STRATEGY_FAILED";
752
- err.nodeId = input.node?.id;
753
- if (input.eventEmitter) {
754
- input.eventEmitter.emit(createNodeFailEvent(lifecycleJobId, input.graphId, graphRunTaskId, input.node, skillKey, {
755
- error: {
756
- message: err.message,
757
- code: err.code,
758
- ...(preRes.response.error != null ? { details: preRes.response.error } : {}),
759
- },
760
- memoryAfter: { jobMemory: input.jobMemory, taskMemory: input.taskMemory, execution },
761
- response: preRes.response,
762
- }, input.jobCorrelation));
763
- }
764
- markNodeLifecycleEmitted(err);
765
- throw err;
766
- }
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);
767
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;
768
710
  const executionForTask = clearSynthForTask
769
711
  ? (() => {
770
712
  const c = { ...executionRec };
@@ -830,7 +772,18 @@ export function createExellixGraphRuntime(opts) {
830
772
  }
831
773
  const runTaskJobMemory = mergeKnowledgePatchIntoRunTaskMemory(input.jobMemory, input.jobKnowledgePatch);
832
774
  const runTaskTaskMemory = mergeKnowledgePatchIntoRunTaskMemory(input.taskMemory, input.taskKnowledgePatch);
833
- 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;
834
787
  const req = buildAiTasksRunTaskRequest({
835
788
  skillKey,
836
789
  job: input.job,
@@ -847,19 +800,16 @@ export function createExellixGraphRuntime(opts) {
847
800
  executionMemory: executionForTask,
848
801
  jobContext,
849
802
  prevNodeId: input.prevNodeId,
850
- executionPipeline: executionPipeline,
851
- includeContextInPrompt: includeContextInPrompt === true ? true : undefined,
852
803
  narrix: narrix ?? undefined,
853
804
  ...extractRunTaskStrategyOverrides(input.node?.taskConfiguration),
854
- outputValidation: input.node?.taskConfiguration?.aiTasksOutputValidation != null &&
855
- typeof input.node.taskConfiguration.aiTasksOutputValidation === "object" &&
856
- input.node.taskConfiguration.aiTasksOutputValidation !== null &&
857
- "schema" in input.node.taskConfiguration.aiTasksOutputValidation
858
- ? input.node.taskConfiguration.aiTasksOutputValidation
859
- : 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),
860
812
  diagnostics: (input.runTaskDiagnostics ?? opts.runTaskDiagnostics),
861
- modelConfig: wireModelConfig,
862
- llmCall: effectiveLlmCall,
863
813
  identity: buildRunTaskIdentityEnvelope({
864
814
  base: runTaskIdentityBase,
865
815
  nodeMeta: input.node?.taskConfiguration,
@@ -874,6 +824,8 @@ export function createExellixGraphRuntime(opts) {
874
824
  executionStrategies: Array.isArray(metaStrats) ? metaStrats : [],
875
825
  xynthesized: xynthesizedOutboundForNode(executionRec, String(input.node.id)),
876
826
  smartInput: input.node.smartInput,
827
+ nodePlan: runTaskNodePlan,
828
+ ...(input.executionTrace != null ? { executionTrace: input.executionTrace } : {}),
877
829
  });
878
830
  // TRACE: Validate request object before sending
879
831
  traceExecutionMemory('executeNode', 'runTask request built', {
@@ -1021,53 +973,6 @@ export function createExellixGraphRuntime(opts) {
1021
973
  };
1022
974
  // Handle execution object updates from response (patch merged above)
1023
975
  // Note: We don't modify jobMemory or taskMemory - they're set before the job starts and passed through as-is
1024
- if (strategyKeys.postStrategyKey != null) {
1025
- const postExec = updatedExecution != null && typeof updatedExecution === "object" && !Array.isArray(updatedExecution)
1026
- ? updatedExecution
1027
- : executionRec;
1028
- const postRes = await runEngineAiTasksStrategyPhase({
1029
- phase: "post",
1030
- strategySkillKey: strategyKeys.postStrategyKey,
1031
- parentSkillKey: skillKey,
1032
- aiTasks: opts.tasksClient,
1033
- job: input.job,
1034
- nodeId: String(input.node.id),
1035
- graphId: input.graphId,
1036
- taskId: graphRunTaskId,
1037
- runTaskJobId: lifecycleJobId,
1038
- execution: postExec,
1039
- variables: jobVariables,
1040
- jobMemory: input.jobMemory,
1041
- taskMemory: input.taskMemory,
1042
- jobContext,
1043
- prevNodeId: input.prevNodeId,
1044
- modelConfig: effectiveModelConfig,
1045
- runTaskIdentity: runTaskIdentityBase,
1046
- nodeTaskConfiguration: input.node?.taskConfiguration,
1047
- forwardRunTaskTrace,
1048
- runTaskDiagnostics: (input.runTaskDiagnostics ?? opts.runTaskDiagnostics),
1049
- nodeTimeoutMs: input.nodeTimeoutMs,
1050
- });
1051
- if (!postRes.ok) {
1052
- const err = new Error(postRes.response.error?.message ?? "ENGINE_POST_STRATEGY_FAILED");
1053
- err.code = postRes.response.error?.code ?? "ENGINE_POST_STRATEGY_FAILED";
1054
- err.nodeId = input.node?.id;
1055
- if (input.eventEmitter) {
1056
- input.eventEmitter.emit(createNodeFailEvent(lifecycleJobId, input.graphId, graphRunTaskId, input.node, skillKey, {
1057
- error: {
1058
- message: err.message,
1059
- code: err.code,
1060
- ...(postRes.response.error != null ? { details: postRes.response.error } : {}),
1061
- },
1062
- memoryAfter: { jobMemory: input.jobMemory, taskMemory: input.taskMemory, execution: postExec },
1063
- response: postRes.response,
1064
- }, input.jobCorrelation));
1065
- }
1066
- markNodeLifecycleEmitted(err);
1067
- throw err;
1068
- }
1069
- updatedExecution = postExec;
1070
- }
1071
976
  // TRACE: Log execution object from response
1072
977
  traceExecutionMemory('executeNode', 'Processing runTask response', {
1073
978
  nodeId: input.node?.id,
@@ -1649,12 +1554,14 @@ export function createExellixGraphRuntime(opts) {
1649
1554
  : nodePlanEntryResolved && node.type !== "finalizer"
1650
1555
  ? graphAiModelConfigFromNodePlan(nodePlanEntryResolved)
1651
1556
  : undefined;
1652
- const nodeExecutionPipeline = nodePlanEntryResolved != null ? executionPipelineFromNodePlan(nodePlanEntryResolved) : undefined;
1653
1557
  const r = await executeNode({
1654
1558
  graphId: resolvedGraphId,
1655
1559
  graph,
1656
1560
  graphRunTaskId: graphTaskId,
1657
1561
  node: taskNodeForExecute,
1562
+ nodePlan: nodePlanEntryResolved,
1563
+ finalizerPlan: finalizerPlanEntryResolved,
1564
+ executionTrace,
1658
1565
  job,
1659
1566
  jobMemory: currentJobMemory,
1660
1567
  taskMemory: nodeTaskMemory,
@@ -1668,7 +1575,6 @@ export function createExellixGraphRuntime(opts) {
1668
1575
  runTaskIdentity: merged.runTaskIdentity,
1669
1576
  runTaskExecutionMode: merged.runTaskExecutionMode,
1670
1577
  runTaskDiagnostics: merged.runTaskDiagnostics,
1671
- graphExecutionPipeline: nodeExecutionPipeline ?? merged.executionPipeline,
1672
1578
  skillKeyResolution: merged.skillKeyResolution,
1673
1579
  nodeTimeoutMs: merged.nodeTimeoutMs,
1674
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
  }
@@ -5,12 +5,15 @@
5
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
  /**
@@ -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
+ }
@@ -1,40 +1,15 @@
1
- import type { Graph } from '../types/refs.js';
2
- import type { ExecuteGraphInput, GraphRuntimeObject } from './ExellixGraphRuntime.js';
1
+ import type { ExecuteGraphInput } from './ExellixGraphRuntime.js';
3
2
  /**
4
3
  * Removed from the graphs-studio execute envelope (7.8.3+). No reader, no fallback.
5
- * Default model selection belongs on {@link Graph}.modelConfig only.
4
+ * Default model selection belongs on authoring graph executable profile only.
6
5
  */
7
6
  export declare const STUDIO_GRAPH_EXECUTE_REMOVED_KEYS: readonly ["graphDefaultModel"];
8
7
  export type StudioGraphExecuteRemovedKey = (typeof STUDIO_GRAPH_EXECUTE_REMOVED_KEYS)[number];
9
- /**
10
- * Graphs-studio / playground graph execute envelope before host adaptation to
11
- * {@link ExecuteGraphInput}. Credential and simulate-only fields are host concerns;
12
- * graph-engine validates shape and forbidden keys only.
13
- */
14
- export type StudioGraphExecuteRequest = {
15
- mode: 'graph';
16
- graph: Graph;
17
- jobId: string;
18
- runtime: Pick<GraphRuntimeObject, 'input' | 'inputs' | 'jobMemory' | 'taskMemory' | 'executionMemory' | 'outputsMemory' | 'variables' | 'jobVariables' | 'taskVariables' | 'nodes'>;
19
- studioId?: string;
20
- executionMode?: string;
21
- runLogMode?: GraphRuntimeObject['runLogMode'];
22
- maxRunLogEntries?: number;
23
- maxRunLogDataJsonChars?: number;
24
- graphExecution?: {
25
- mode?: GraphRuntimeObject['mode'];
26
- goalNodeId?: string;
27
- dimension?: string;
28
- };
29
- runTaskDiagnostics?: GraphRuntimeObject['runTaskDiagnostics'];
30
- exampleIndex?: number;
31
- validateGraphEntrySeed?: boolean;
32
- openrouterApiKey?: string;
33
- };
8
+ /** @deprecated Prefer {@link AuthoringGraphDocument} from `@x12i/graphenix-executable-contracts`. */
9
+ export type StudioGraphExecuteRequest = import('@x12i/graphenix-executable-contracts').StudioGraphExecuteRequest;
34
10
  export declare function getStudioGraphExecuteRemovedKeyViolations(request: unknown): StudioGraphExecuteRemovedKey[];
35
11
  /**
36
12
  * Rejects removed studio execute keys (notably `graphDefaultModel`).
37
- * Hosts must persist model defaults on `graph.modelConfig` and stop sending request-level mirrors.
38
13
  */
39
14
  export declare function assertCanonicalStudioGraphExecuteRequest(request: unknown, context?: {
40
15
  jobId?: string;
@@ -46,6 +21,6 @@ export type BuildGraphExecutionRequestFromStudioExecuteOptions = {
46
21
  };
47
22
  /**
48
23
  * Maps a validated studio execute envelope to {@link ExecuteGraphInput}.
49
- * Does not read or merge removed request-level model defaults — graph.modelConfig is authoritative.
24
+ * Delegates validate + compile to `@x12i/graphenix-execute-envelope`.
50
25
  */
51
26
  export declare function buildGraphExecutionRequestFromStudioExecute(request: StudioGraphExecuteRequest, options?: BuildGraphExecutionRequestFromStudioExecuteOptions): ExecuteGraphInput;