@exellix/ai-tasks 8.8.0 → 9.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/RUNTASK_REQUEST.md +10 -2
  3. package/dist/builders/task-request-builder.d.ts +2 -0
  4. package/dist/builders/task-request-builder.d.ts.map +1 -1
  5. package/dist/builders/task-request-builder.js +8 -0
  6. package/dist/builders/task-request-builder.js.map +1 -1
  7. package/dist/core/task-sdk.d.ts.map +1 -1
  8. package/dist/core/task-sdk.js +83 -976
  9. package/dist/core/task-sdk.js.map +1 -1
  10. package/dist/errors/nodePlanValidationError.d.ts +18 -0
  11. package/dist/errors/nodePlanValidationError.d.ts.map +1 -0
  12. package/dist/errors/nodePlanValidationError.js +29 -0
  13. package/dist/errors/nodePlanValidationError.js.map +1 -0
  14. package/dist/index.d.ts +4 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +4 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/methods/convenience-methods.d.ts.map +1 -1
  19. package/dist/methods/convenience-methods.js +2 -0
  20. package/dist/methods/convenience-methods.js.map +1 -1
  21. package/dist/narrix/narrixUnitExecution.d.ts +8 -0
  22. package/dist/narrix/narrixUnitExecution.d.ts.map +1 -0
  23. package/dist/narrix/narrixUnitExecution.js +132 -0
  24. package/dist/narrix/narrixUnitExecution.js.map +1 -0
  25. package/dist/node-execution/buildRequestFromNodePlan.d.ts +10 -0
  26. package/dist/node-execution/buildRequestFromNodePlan.d.ts.map +1 -0
  27. package/dist/node-execution/buildRequestFromNodePlan.js +96 -0
  28. package/dist/node-execution/buildRequestFromNodePlan.js.map +1 -0
  29. package/dist/node-execution/createNodeExecutionHost.d.ts +18 -0
  30. package/dist/node-execution/createNodeExecutionHost.d.ts.map +1 -0
  31. package/dist/node-execution/createNodeExecutionHost.js +236 -0
  32. package/dist/node-execution/createNodeExecutionHost.js.map +1 -0
  33. package/dist/node-execution/dispatchExecutionUnit.d.ts +11 -0
  34. package/dist/node-execution/dispatchExecutionUnit.d.ts.map +1 -0
  35. package/dist/node-execution/dispatchExecutionUnit.js +80 -0
  36. package/dist/node-execution/dispatchExecutionUnit.js.map +1 -0
  37. package/dist/node-execution/executeNodeFromPlan.d.ts +4 -0
  38. package/dist/node-execution/executeNodeFromPlan.d.ts.map +1 -0
  39. package/dist/node-execution/executeNodeFromPlan.js +58 -0
  40. package/dist/node-execution/executeNodeFromPlan.js.map +1 -0
  41. package/dist/node-execution/index.d.ts +7 -0
  42. package/dist/node-execution/index.d.ts.map +1 -0
  43. package/dist/node-execution/index.js +6 -0
  44. package/dist/node-execution/index.js.map +1 -0
  45. package/dist/node-execution/minimalNodePlan.d.ts +4 -0
  46. package/dist/node-execution/minimalNodePlan.d.ts.map +1 -0
  47. package/dist/node-execution/minimalNodePlan.js +31 -0
  48. package/dist/node-execution/minimalNodePlan.js.map +1 -0
  49. package/dist/node-execution/rejectForbiddenWireFields.d.ts +4 -0
  50. package/dist/node-execution/rejectForbiddenWireFields.d.ts.map +1 -0
  51. package/dist/node-execution/rejectForbiddenWireFields.js +23 -0
  52. package/dist/node-execution/rejectForbiddenWireFields.js.map +1 -0
  53. package/dist/node-execution/resolveUnitModelSelection.d.ts +4 -0
  54. package/dist/node-execution/resolveUnitModelSelection.d.ts.map +1 -0
  55. package/dist/node-execution/resolveUnitModelSelection.js +63 -0
  56. package/dist/node-execution/resolveUnitModelSelection.js.map +1 -0
  57. package/dist/node-execution/skipUnit.d.ts +3 -0
  58. package/dist/node-execution/skipUnit.d.ts.map +1 -0
  59. package/dist/node-execution/skipUnit.js +11 -0
  60. package/dist/node-execution/skipUnit.js.map +1 -0
  61. package/dist/node-execution/types.d.ts +26 -0
  62. package/dist/node-execution/types.d.ts.map +1 -0
  63. package/dist/node-execution/types.js +2 -0
  64. package/dist/node-execution/types.js.map +1 -0
  65. package/dist/node-execution/unitTrace.d.ts +12 -0
  66. package/dist/node-execution/unitTrace.d.ts.map +1 -0
  67. package/dist/node-execution/unitTrace.js +52 -0
  68. package/dist/node-execution/unitTrace.js.map +1 -0
  69. package/dist/observability/graphExecutionRunLogContract.d.ts +8 -7
  70. package/dist/observability/graphExecutionRunLogContract.d.ts.map +1 -1
  71. package/dist/observability/graphExecutionRunLogContract.js +4 -5
  72. package/dist/observability/graphExecutionRunLogContract.js.map +1 -1
  73. package/dist/post-steps/polish/runPolishCall.d.ts.map +1 -1
  74. package/dist/post-steps/polish/runPolishCall.js +1 -0
  75. package/dist/post-steps/polish/runPolishCall.js.map +1 -1
  76. package/dist/types/task-types.d.ts +12 -6
  77. package/dist/types/task-types.d.ts.map +1 -1
  78. package/dist/utils/runTaskRequestShape.d.ts +1 -1
  79. package/dist/utils/runTaskRequestShape.d.ts.map +1 -1
  80. package/dist/utils/runTaskRequestShape.js +5 -3
  81. package/dist/utils/runTaskRequestShape.js.map +1 -1
  82. package/dist/utils/xynthesizedWrite.d.ts +12 -1
  83. package/dist/utils/xynthesizedWrite.d.ts.map +1 -1
  84. package/dist/utils/xynthesizedWrite.js +38 -0
  85. package/dist/utils/xynthesizedWrite.js.map +1 -1
  86. package/dist/validation/validateRunTaskConfig.d.ts.map +1 -1
  87. package/dist/validation/validateRunTaskConfig.js +30 -14
  88. package/dist/validation/validateRunTaskConfig.js.map +1 -1
  89. package/documenations/node-execution-graphenix.md +40 -0
  90. package/documenations/schemas/v1/run-task-request.json +21 -3
  91. package/package.json +7 -2
@@ -6,36 +6,27 @@ import { buildExecutionStrategyRequestPayload } from "../execution-strategies/ex
6
6
  import { runOptimizerViaXynthesis, runPlannerViaXynthesis, } from "../execution-strategies/runExecutionStrategyViaXynthesis.js";
7
7
  import { resolveSafeExecutionStrategyCatalogDefaultSidekickAction } from "../execution-strategies/executionStrategyCatalogMetadata.js";
8
8
  import { SYNTHESIZED_CONTEXT } from "../types/index.js";
9
- import { runAuditPostStep } from "../post-steps/audit/runAudit.js";
10
9
  import { buildRunTaskResultMetaFromModelId } from "../invocation/buildRunTaskResultMeta.js";
11
10
  import { logRunTaskInvocationPlan } from "../observability/logLlmProviderInvocation.js";
12
- import { runPolishPostStep } from "../post-steps/polish/runPolish.js";
13
- import { getLocalTask } from "../localTasks/registry.js";
14
11
  import { registerBuiltInLocalTasks } from "../localTasks/index.js";
15
12
  import { getByPath } from "../utils/jsonPaths.js";
16
13
  import { passthroughJobTemplateVariables } from "../utils/skillTemplateVariables.js";
17
14
  import { emitRunTaskRequestWarnings } from "../utils/runTaskRequestShape.js";
18
- import { DebugLogAbstract, fieldEvidence } from "@x12i/logxer";
19
15
  import { configureFuncxLogging } from "@x12i/funcx";
20
- import { AI_TASKS_DIAGNOSTIC_CODES } from "../logxer/aiTasksDiagnosticCodes.js";
21
16
  import { patchRunTaskLogContext, runAiTasksWithObservabilityContext, } from "../logxer/aiTasksLogContext.js";
22
17
  import { logAndEnrichRunTaskFailure } from "../observability/logRunTaskFailure.js";
23
- import { getAiTasksLogxer } from "../logxer/packageLogxers.js";
24
18
  import { assertRequiredRunSkillCorrelation } from "../utils/assertRequiredRunSkillCorrelation.js";
25
- import { compileTaskConfigurationOnRunTaskRequest } from "../compile/compileTaskConfiguration.js";
19
+ import { validateNodeExecutionPlan } from "@x12i/graphenix-plan-format";
20
+ import { NodePlanValidationError } from "../errors/nodePlanValidationError.js";
21
+ import { executeNodeFromPlan } from "../node-execution/executeNodeFromPlan.js";
22
+ import { createNodeExecutionHost } from "../node-execution/createNodeExecutionHost.js";
23
+ import { assertNodePlanPresent, rejectForbiddenWireFields, } from "../node-execution/rejectForbiddenWireFields.js";
26
24
  import { assertValidSmartInputConfig } from "../utils/assertValidSmartInputConfig.js";
27
25
  import { extractSmartInputRenderResult } from "../utils/extractSmartInputRenderResult.js";
28
26
  import { normalizeSmartInputConfig } from "../utils/normalizeSmartInputConfig.js";
29
- import { applyXynthesizedOutputWrite, mergeXynthesizedPatchSlices, } from "../utils/xynthesizedWrite.js";
30
27
  import { validateParsedOutput } from "../utils/outputValidation.js";
31
- import { narrixRunHandler } from "../narrix/task.js";
32
28
  import { buildNarrixContextMarkdown, buildNarrixPreProcessorContextMarkdown } from "../narrix/narrixContextMarkdown.js";
33
29
  import { buildWebContextEvidenceMarkdown } from "../narrix/webContextMarkdown.js";
34
- import { applyNarrixScope } from "../narrix/applyNarrixScope.js";
35
- import { adaptMemorixToNarrixInput } from "@exellix/memorix-narrix-adapter";
36
- import { buildNarrixAttachment } from "../narrix/buildNarrixAttachment.js";
37
- import { runWebScope, runWebScopeQuestionPack, webScopeActivixCorrelationPatch } from "../narrix/webScoper.js";
38
- import { resolveWebScopeQuestionAndTemplates } from "../narrix/buildWebScopeScopeInput.js";
39
30
  import { runAiScoping } from "../aiScoping/runAiScoping.js";
40
31
  import { getActivixClient } from "../activix/activixClient.js";
41
32
  import { withPhaseRecord } from "../activix/phaseTracking.js";
@@ -45,18 +36,12 @@ import { loadSynthesisTemplates, buildSynthesisSystemPrompt, buildSynthesisUserP
45
36
  import { resolveOutputExpectation as resolveOutputExpectationXynthesis } from "@exellix/xynthesis/ai-actions";
46
37
  import { llmCallEnvPrefix, resolveLlmCall } from "../post-steps/resolvePostStepConfig.js";
47
38
  import { buildXynthesisWorkScopeIdentity } from "../internal/buildXynthesisWorkScopeIdentity.js";
48
- import { assertMainSkillModelConfigReadyForInvoke, getPostActionModelFromSlots, prepareMainSkillModelConfigForInvoke, resolvePreActionModel, } from "../utils/routeModelConfigSlots.js";
39
+ import { getPostActionModelFromSlots, prepareMainSkillModelConfigForInvoke, resolvePreActionModel, } from "../utils/routeModelConfigSlots.js";
49
40
  import { assertPhaseModelAlias } from "../errors/modelConfigRequiredError.js";
50
41
  import { isRunTaskModelResolutionError } from "../errors/runTaskModelResolutionError.js";
51
- import { resolveRunTaskModelReferences } from "../utils/resolveRunTaskModelReferences.js";
52
42
  import { runPostStepLlmCall } from "../internal/runPostStepLlmCall.js";
53
43
  registerBuiltInLocalTasks();
54
44
  const DEFAULT_SYNTH_INPUT_MAX_CHARS = 200_000;
55
- function synthesizedResultForXynthesizedPatch(artifact, contextMarkdown) {
56
- if (artifact !== undefined)
57
- return artifact;
58
- return { contextMarkdown };
59
- }
60
45
  function maxSynthesizedInputChars() {
61
46
  const raw = process.env.SYNTHESIZED_INPUT_MAX_CHARS;
62
47
  if (!raw)
@@ -280,6 +265,44 @@ function resolveSynthesisMode(config) {
280
265
  }
281
266
  return "markdown";
282
267
  }
268
+ function detectedTemplateCoresFromExecutionMemory(executionMemory) {
269
+ const artifact = executionMemory?.synthesizedContext;
270
+ if (!artifact?.templateCores || !Array.isArray(artifact.templateCores)) {
271
+ return [];
272
+ }
273
+ return artifact.templateCores
274
+ .map((core) => (typeof core === "string" ? core : core.name))
275
+ .filter((name) => typeof name === "string" && name.length > 0);
276
+ }
277
+ function synthesisObservabilityFromNodePlan(nodePlan, result) {
278
+ const synthUnits = nodePlan.executionUnits.filter((u) => u.unitKind === "externalPreUtility" || u.unitKind === "pipelinePhase");
279
+ const synthParams = (synthUnits[0]?.unitParams ?? {});
280
+ const executionMemory = result.executionMemory ?? undefined;
281
+ const synthesizedContext = executionMemory?.synthesizedContext;
282
+ const effectiveExecutionPipeline = [];
283
+ for (const unit of nodePlan.executionUnits) {
284
+ if (unit.unitKind === "externalPreUtility" || unit.unitKind === "pipelinePhase") {
285
+ effectiveExecutionPipeline.push({ phase: "pre", type: SYNTHESIZED_CONTEXT });
286
+ }
287
+ else if (unit.unitKind === "mainSkill" || unit.unitKind === "localSkill") {
288
+ effectiveExecutionPipeline.push({ phase: "main", type: "direct" });
289
+ }
290
+ else if (unit.unitKind === "externalPostUtility") {
291
+ effectiveExecutionPipeline.push({
292
+ phase: "post",
293
+ type: unit.strategyKey ?? unit.actionKey ?? "post",
294
+ });
295
+ }
296
+ }
297
+ return {
298
+ synthesisEnabled: synthUnits.length > 0,
299
+ effectiveExecutionPipeline: effectiveExecutionPipeline.length > 0 ? effectiveExecutionPipeline : undefined,
300
+ synthesizedContextPresent: !!synthesizedContext,
301
+ mainContextSource: synthesizedContext ? "synthesizedContext" : "unsynthesized",
302
+ synthesisMode: resolveSynthesisMode(synthParams),
303
+ detectedTemplateCores: detectedTemplateCoresFromExecutionMemory(executionMemory),
304
+ };
305
+ }
283
306
  /**
284
307
  * If parsed is an object with intermediateSteps, lift them to the response and remove from parsed
285
308
  * so that response.intermediateSteps is the canonical place and parsed holds only task output.
@@ -460,11 +483,12 @@ export class WorexClientTasks {
460
483
  modelConfig: req.modelConfig,
461
484
  });
462
485
  try {
463
- const compiled = compileTaskConfigurationOnRunTaskRequest(input);
464
- input = await resolveRunTaskModelReferences(compiled.request);
465
- await assertMainSkillModelConfigReadyForInvoke(input.modelConfig, input.llmCall, {
466
- skillKey: input.skillKey,
467
- });
486
+ assertNodePlanPresent(input);
487
+ rejectForbiddenWireFields(input);
488
+ const planValidation = validateNodeExecutionPlan(input.nodePlan);
489
+ if (!planValidation.valid) {
490
+ throw new NodePlanValidationError(planValidation);
491
+ }
468
492
  emitRunTaskRequestWarnings(input);
469
493
  assertRequiredRunSkillCorrelation(input);
470
494
  assertValidSmartInputConfig(input.smartInput, input.skillKey);
@@ -572,6 +596,11 @@ export class WorexClientTasks {
572
596
  if (patchJob || patchTask || patchExecution) {
573
597
  result.xynthesizedPatch = xynthesizedPatchAccumulator;
574
598
  }
599
+ liftIntermediateSteps(result);
600
+ if (result.metadata !== undefined) {
601
+ result.meta = result
602
+ .metadata;
603
+ }
575
604
  return result;
576
605
  };
577
606
  const hasPipeline = Array.isArray(input.executionPipeline) && input.executionPipeline.length > 0;
@@ -851,956 +880,23 @@ export class WorexClientTasks {
851
880
  }
852
881
  return mergePrefixSteps(last);
853
882
  };
854
- // NARRIX task-level pre-processor + structured handler: `narrixMode` (+ inference) via `resolveRunTaskRuntimeKnobs`.
855
- if (knobs.narrixMode === "preprocessor" && request.narrix) {
856
- const narrixCfg = request.narrix;
857
- await traceWrap(traceCollector, {
858
- taskType: "pre-execution",
859
- details: "narrix preprocessor",
860
- metadata: {
861
- ...baseTraceMeta(),
862
- phase: "narrix",
863
- datasetId: narrixCfg.datasetId,
864
- attachToField: narrixCfg.attachToField ?? "_narrix",
865
- enableWebScope: narrixCfg.enableWebScope === true,
866
- },
867
- }, async () => withPhaseRecord({
868
- ax,
869
- correlationId,
870
- phase: "narrix",
871
- meta: {
872
- ...baseMeta,
873
- narrixAttachToField: narrixCfg.attachToField ?? "_narrix",
874
- outer: activixOuterTier({
875
- kind: "narrix.preProcessor.request",
876
- datasetId: narrixCfg.datasetId,
877
- attachToField: narrixCfg.attachToField ?? "_narrix",
878
- enableWebScope: narrixCfg.enableWebScope === true,
879
- webScoping: narrixCfg.webScoping ? summarizeForOuter(narrixCfg.webScoping, 2_000) : undefined,
880
- requestInput: summarizeForOuter(request.input, 4_000),
881
- }, null, { phase: "narrix" }),
882
- },
883
- fn: async () => {
884
- const adaptResult = adaptMemorixToNarrixInput({
885
- datasetId: narrixCfg.datasetId,
886
- mediumHint: "record",
887
- memorix: {
888
- jobMemory: request.jobMemory,
889
- executionMemory: request.executionMemory,
890
- input: request.input,
891
- },
892
- }, {
893
- record: {
894
- minKeys: 1,
895
- preferPaths: [
896
- "executionMemory.input.raw",
897
- "executionMemory.inputs.*.raw",
898
- "jobMemory.record",
899
- "jobMemory.currentRecord",
900
- "executionMemory.input.record",
901
- "executionMemory.record",
902
- "taskMemory.currentRecord",
903
- "*.currentRecord",
904
- "*.record",
905
- ],
906
- },
907
- });
908
- if (!adaptResult.ok) {
909
- const attempted = adaptResult.attempted?.length ? ` Attempted: ${adaptResult.attempted.join(", ")}.` : "";
910
- const summary = adaptResult.foundSummary ? ` Seen: ${adaptResult.foundSummary}` : "";
911
- throw new Error(`NARRIX pre-processor: no usable input. ${adaptResult.message}.${attempted}${summary}`);
912
- }
913
- const ctx = {
914
- skillKey: request.skillKey,
915
- jobMemory: request.jobMemory,
916
- taskMemory: request.taskMemory,
917
- executionMemory: request.executionMemory,
918
- variables: input.variables,
919
- xynthesized: request.xynthesized,
920
- smartInput: request.smartInput,
921
- jobId: input.jobId,
922
- taskId: request.taskId,
923
- agentId: input.agentId,
924
- graphId: input.graphId,
925
- nodeId: input.nodeId,
926
- prevNodeId: input.prevNodeId,
927
- coreSkillId: input.coreSkillId,
928
- masterSkillId: request.masterSkillId,
929
- masterSkillActivityId: request.masterSkillActivityId,
930
- };
931
- const narrixResult = await narrixRunHandler({ input: adaptResult.narrixInput, ctx });
932
- if (!narrixResult.ok) {
933
- const fail = narrixResult;
934
- throw new Error(`NARRIX pre-processor failed: ${fail.error}${fail.message ? ` - ${fail.message}` : ""}`);
935
- }
936
- const attachment = buildNarrixAttachment(narrixResult);
937
- const attachToField = narrixCfg.attachToField ?? "_narrix";
938
- let webContextEntry = undefined;
939
- let webContextAvailable;
940
- let webContextReason;
941
- const externalWebMdPreNarrix = typeof request.executionMemory?.webContextMarkdown === "string" &&
942
- request.executionMemory.webContextMarkdown.trim().length > 0;
943
- const skipWebScopeForExternalMd = narrixCfg.skipWebScopeWhenExternalWebMarkdownPresent === true && externalWebMdPreNarrix;
944
- if (narrixCfg.enableWebScope === true && !skipWebScopeForExternalMd) {
945
- const successResult = narrixResult;
946
- const entity = adaptResult.narrixInput.medium === "record"
947
- ? adaptResult.narrixInput.record
948
- : undefined;
949
- const scopeFields = resolveWebScopeQuestionAndTemplates({
950
- narrix: narrixCfg,
951
- requestInput: request.input,
952
- successResult,
953
- entity,
954
- });
955
- const webScopeOpts = hasNonEmptyWebScoping(narrixCfg.webScoping)
956
- ? { scoping: narrixCfg.webScoping }
957
- : undefined;
958
- const activixPatch = webScopeActivixCorrelationPatch({
959
- jobId: request.jobId,
960
- taskId: request.taskId,
961
- sessionId: request.taskId,
962
- });
963
- const packQs = scopeFields.packQuestions;
964
- if (Array.isArray(packQs) && packQs.length > 0) {
965
- webContextEntry = await runWebScopeQuestionPack({
966
- datasetId: narrixCfg.datasetId,
967
- subjectId: successResult.entity.entityKey,
968
- entityKind: successResult.entity.entityKind,
969
- entity,
970
- cni: successResult.cni,
971
- ...activixPatch,
972
- questions: packQs,
973
- }, webScopeOpts);
974
- }
975
- else {
976
- const { packQuestions: _pq, ...genericScope } = scopeFields;
977
- void _pq;
978
- webContextEntry = await runWebScope({
979
- datasetId: narrixCfg.datasetId,
980
- subjectId: successResult.entity.entityKey,
981
- entityKind: successResult.entity.entityKind,
982
- entity,
983
- cni: successResult.cni,
984
- ...activixPatch,
985
- ...genericScope,
986
- }, webScopeOpts);
987
- }
988
- if (webContextEntry && typeof webContextEntry === "object") {
989
- const wc = webContextEntry;
990
- webContextAvailable = typeof wc.available === "boolean" ? wc.available : undefined;
991
- webContextReason = typeof wc.reason === "string" ? wc.reason : undefined;
992
- }
993
- if (webContextEntry &&
994
- typeof webContextEntry === "object" &&
995
- webContextEntry.available === false) {
996
- const miss = webContextEntry;
997
- if (process.env.NARRIX_DEBUG === "1") {
998
- getAiTasksLogxer().warnCode(AI_TASKS_DIAGNOSTIC_CODES.NARRIX_WEB_SCOPE_MISS, {
999
- source: "@exellix/ai-tasks",
1000
- debugKind: DebugLogAbstract.ANOMALY,
1001
- diagnostics: {
1002
- summary: "Narrix web scope miss",
1003
- actual: miss.error ?? miss.reason ?? "web context unavailable",
1004
- },
1005
- evidence: [
1006
- fieldEvidence("webContext.reason", miss.reason ?? null),
1007
- fieldEvidence("webContext.error", miss.error ?? null),
1008
- ],
1009
- });
1010
- }
1011
- if (traceCollector) {
1012
- traceCollector.push({
1013
- taskType: "pre-execution",
1014
- details: "narrix web scope miss",
1015
- metadata: {
1016
- ...baseTraceMeta(),
1017
- phase: "narrix",
1018
- webContext: { available: false, reason: miss.reason, error: miss.error },
1019
- },
1020
- modelUsed: null,
1021
- });
1022
- }
1023
- }
1024
- }
1025
- request = {
1026
- ...request,
1027
- executionMemory: {
1028
- ...(request.executionMemory || {}),
1029
- [attachToField]: attachment,
1030
- ...(webContextEntry !== undefined ? { webContext: webContextEntry } : {}),
1031
- },
1032
- jobMemory: request.jobMemory ? { ...request.jobMemory, _narrix: attachment } : { _narrix: attachment },
1033
- };
1034
- const scopingSignalsCount = Array.isArray(attachment?.scoping?.signals) ? attachment.scoping.signals.length : undefined;
1035
- const scopingStoriesCount = Array.isArray(attachment?.scoping?.stories) ? attachment.scoping.stories.length : undefined;
1036
- const discoverySignalsCount = Array.isArray(attachment?.discovery?.signals) ? attachment.discovery.signals.length : undefined;
1037
- const discoveryStoriesCount = Array.isArray(attachment?.discovery?.stories) ? attachment.discovery.stories.length : undefined;
1038
- const entityKey = narrixResult?.entity?.entityKey;
1039
- const entityKind = narrixResult?.entity?.entityKind;
1040
- return {
1041
- datasetId: narrixCfg.datasetId,
1042
- attachToField,
1043
- enableWebScope: narrixCfg.enableWebScope === true,
1044
- webContextAvailable,
1045
- webContextReason,
1046
- attachmentMeta: isRecord(attachment?.meta) ? attachment.meta : undefined,
1047
- scopingSignalsCount,
1048
- scopingStoriesCount,
1049
- discoverySignalsCount,
1050
- discoveryStoriesCount,
1051
- entityKey: typeof entityKey === "string" ? entityKey : undefined,
1052
- entityKind: typeof entityKind === "string" ? entityKind : undefined,
1053
- medium: typeof adaptResult.narrixInput?.medium === "string" ? adaptResult.narrixInput.medium : undefined,
1054
- };
1055
- },
1056
- onSuccessUpdates: (r) => ({
1057
- outer: activixOuterTier({
1058
- kind: "narrix.preProcessor.request",
1059
- datasetId: narrixCfg.datasetId,
1060
- attachToField: narrixCfg.attachToField ?? "_narrix",
1061
- enableWebScope: narrixCfg.enableWebScope === true,
1062
- webScoping: narrixCfg.webScoping ? summarizeForOuter(narrixCfg.webScoping, 2_000) : undefined,
1063
- requestInput: summarizeForOuter(request.input, 4_000),
1064
- }, {
1065
- kind: "narrix.preProcessor.result",
1066
- datasetId: r.datasetId,
1067
- attachToField: r.attachToField,
1068
- enableWebScope: r.enableWebScope,
1069
- entity: r.entityKey ? { entityKey: r.entityKey, entityKind: r.entityKind } : undefined,
1070
- counts: {
1071
- scopingSignals: r.scopingSignalsCount,
1072
- scopingStories: r.scopingStoriesCount,
1073
- discoverySignals: r.discoverySignalsCount,
1074
- discoveryStories: r.discoveryStoriesCount,
1075
- },
1076
- webContext: r.enableWebScope
1077
- ? { available: r.webContextAvailable, reason: r.webContextReason }
1078
- : undefined,
1079
- attachmentMeta: r.attachmentMeta,
1080
- }, { phase: "narrix" }),
1081
- }),
1082
- }));
1083
- }
1084
- // Structured Narrix (`narrixInput`): same enrichment as legacy `narrix-then-direct`, but runs before local tasks / pipeline PRE.
1085
- if (knobs.narrixMode === "handler") {
1086
- if (!request.narrixInput) {
1087
- throw new Error(`narrixMode "handler" requires narrixInput. ` +
1088
- `Provide { medium, datasetId, ... } or { $path: "jobMemory.currentRecord" } on the request.`);
1089
- }
1090
- const resolvedNarrixInput = resolveNarrixInput(request.narrixInput, request.jobMemory);
1091
- if (!resolvedNarrixInput) {
1092
- throw new Error(`narrixMode "handler": narrixInput could not be resolved. ` +
1093
- `Ensure it has medium and datasetId, or that $path points to a valid object in jobMemory.`);
1094
- }
1095
- let narrixThenDirectPhaseRecordId = null;
1096
- if (ax && correlationId) {
1097
- try {
1098
- narrixThenDirectPhaseRecordId = (await ax.startRecord({
1099
- correlationId,
1100
- phase: "narrix_then_direct",
1101
- ...baseMeta,
1102
- narrixDatasetId: resolvedNarrixInput.datasetId,
1103
- narrixMedium: resolvedNarrixInput.medium,
1104
- outer: activixOuterTier({
1105
- kind: "narrixThenDirect.request",
1106
- skillKey: request.skillKey,
1107
- jobId: request.jobId,
1108
- agentId: request.agentId,
1109
- narrixInput: summarizeForOuter(resolvedNarrixInput, 6_000),
1110
- }, null, { phase: "narrix_then_direct" }),
1111
- })).recordId;
1112
- }
1113
- catch {
1114
- narrixThenDirectPhaseRecordId = null;
1115
- }
1116
- }
1117
- try {
1118
- const narrixStarted = Date.now();
1119
- const narrixHandlerCtx = {
1120
- skillKey: request.skillKey,
1121
- jobMemory: request.jobMemory,
1122
- taskMemory: request.taskMemory,
1123
- executionMemory: request.executionMemory,
1124
- variables: request.variables,
1125
- xynthesized: request.xynthesized,
1126
- smartInput: request.smartInput,
1127
- jobId: request.jobId,
1128
- taskId: request.taskId,
1129
- agentId: request.agentId,
1130
- graphId: request.graphId,
1131
- nodeId: request.nodeId,
1132
- prevNodeId: request.prevNodeId,
1133
- coreSkillId: request.coreSkillId,
1134
- masterSkillId: request.masterSkillId,
1135
- masterSkillActivityId: request.masterSkillActivityId,
1136
- };
1137
- const narrixResult = await traceWrap(traceCollector, {
1138
- taskType: "pre-execution",
1139
- details: "narrix structured handler (narrixInput)",
1140
- metadata: {
1141
- ...baseTraceMeta(),
1142
- phase: "narrix_then_direct",
1143
- datasetId: resolvedNarrixInput.datasetId,
1144
- medium: resolvedNarrixInput.medium,
1145
- },
1146
- }, async () => narrixRunHandler({ input: resolvedNarrixInput, ctx: narrixHandlerCtx }), (r) => ({
1147
- metadata: { ok: r?.ok === true },
1148
- modelUsed: null,
1149
- }));
1150
- const narrixDurationMs = Date.now() - narrixStarted;
1151
- if (!narrixResult.ok) {
1152
- const fail = narrixResult;
1153
- if (ax && correlationId && narrixThenDirectPhaseRecordId) {
1154
- await ax
1155
- .failRecord(narrixThenDirectPhaseRecordId, new Error(`Narrix handler failed: ${fail.error}${fail.message ? ` - ${fail.message}` : ""}`), {
1156
- errorMessage: fail.message ? `${fail.error} - ${fail.message}` : fail.error,
1157
- errorCode: fail.code,
1158
- narrixDurationMs,
1159
- })
1160
- .catch(() => undefined);
1161
- }
1162
- return withTrace({
1163
- skillKey: request.skillKey,
1164
- rawText: JSON.stringify(narrixResult, null, 2),
1165
- flexMd: { frame: "narrixThenDirect.v1", payloads: { narrix: JSON.stringify(narrixResult) } },
1166
- parsed: {
1167
- ok: false,
1168
- error: narrixResult.error,
1169
- phase: "narrix",
1170
- message: narrixResult.message,
1171
- },
1172
- metadata: {
1173
- instructionVersion: "narrix-then-direct",
1174
- narrix: { ...narrixResult, durationMs: narrixDurationMs },
1175
- narrixMode: knobs.narrixMode,
1176
- inputStrategyKey: knobs.inputStrategyKey,
1177
- executionStrategiesSummary: executionStrategiesSummaryFromKnobs(knobs),
1178
- },
1179
- });
1180
- }
1181
- const filteredEntry = applyNarrixScope(narrixResult, request.narrixScope);
1182
- const existingNarrix = Array.isArray(request.taskMemory?.narrix)
1183
- ? request.taskMemory.narrix
1184
- : [];
1185
- const updatedTaskMemory = {
1186
- ...(request.taskMemory ?? {}),
1187
- narrix: [...existingNarrix, filteredEntry],
1188
- };
1189
- const skillInput = typeof request.input === "object" && request.input !== null
1190
- ? { ...request.input, narrixContext: filteredEntry }
1191
- : { narrixContext: filteredEntry };
1192
- request = {
1193
- ...request,
1194
- taskMemory: updatedTaskMemory,
1195
- input: skillInput,
1196
- };
1197
- if (ax && correlationId && narrixThenDirectPhaseRecordId) {
1198
- await ax
1199
- .completeRecord(narrixThenDirectPhaseRecordId, {
1200
- narrixDurationMs,
1201
- outer: activixOuterTier({
1202
- kind: "narrixThenDirect.request",
1203
- skillKey: request.skillKey,
1204
- jobId: request.jobId,
1205
- agentId: request.agentId,
1206
- narrixInput: summarizeForOuter(resolvedNarrixInput, 6_000),
1207
- }, {
1208
- kind: "narrixThenDirect.result",
1209
- ok: true,
1210
- durationMs: narrixDurationMs,
1211
- }, { phase: "narrix_then_direct" }),
1212
- })
1213
- .catch(() => undefined);
1214
- }
1215
- }
1216
- catch (error) {
1217
- if (ax && correlationId && narrixThenDirectPhaseRecordId) {
1218
- await ax
1219
- .failRecord(narrixThenDirectPhaseRecordId, error instanceof Error ? error : new Error(String(error)), {
1220
- errorMessage: error instanceof Error ? error.message : String(error),
1221
- errorCode: error?.code,
1222
- outer: activixOuterTier({
1223
- kind: "narrixThenDirect.request",
1224
- skillKey: request.skillKey,
1225
- jobId: request.jobId,
1226
- agentId: request.agentId,
1227
- narrixInput: summarizeForOuter(resolvedNarrixInput, 6_000),
1228
- }, {
1229
- kind: "narrixThenDirect.error",
1230
- message: error instanceof Error ? error.message : String(error),
1231
- }, { phase: "narrix_then_direct" }),
1232
- })
1233
- .catch(() => undefined);
1234
- }
1235
- throw error;
1236
- }
1237
- }
1238
- // Local task dispatch: if a handler is registered, run it and return (no enrichment)
1239
- const handler = getLocalTask(request.skillKey);
1240
- if (handler) {
1241
- const result = await traceWrap(traceCollector, {
1242
- taskType: "pre-execution",
1243
- details: "local task handler",
1244
- metadata: {
1245
- ...baseTraceMeta(),
1246
- phase: "local",
1247
- localSkillKey: request.skillKey,
1248
- },
1249
- modelUsed: null,
1250
- }, async () => withPhaseRecord({
1251
- ax,
1252
- correlationId,
1253
- phase: "local",
1254
- meta: {
1255
- ...baseMeta,
1256
- localSkillKey: request.skillKey,
1257
- outer: activixOuterTier({
1258
- kind: "localTask.request",
1259
- skillKey: request.skillKey,
1260
- jobId: request.jobId,
1261
- agentId: request.agentId,
1262
- input: summarizeForOuter(request.input, 4_000),
1263
- }, null, { phase: "local" }),
1264
- },
1265
- fn: async () => {
1266
- const started = Date.now();
1267
- const ctx = {
1268
- skillKey: request.skillKey,
1269
- jobMemory: request.jobMemory,
1270
- taskMemory: request.taskMemory,
1271
- executionMemory: request.executionMemory,
1272
- variables: input.variables,
1273
- xynthesized: request.xynthesized,
1274
- smartInput: request.smartInput,
1275
- jobId: input.jobId,
1276
- taskId: input.taskId,
1277
- agentId: input.agentId,
1278
- graphId: input.graphId,
1279
- nodeId: input.nodeId,
1280
- prevNodeId: input.prevNodeId,
1281
- coreSkillId: input.coreSkillId,
1282
- masterSkillId: request.masterSkillId,
1283
- masterSkillActivityId: request.masterSkillActivityId,
1284
- };
1285
- const value = await handler({ input: request.input, ctx });
1286
- const durationMs = Date.now() - started;
1287
- let parsed = value;
1288
- let intermediateSteps;
1289
- if (value !== null &&
1290
- typeof value === "object" &&
1291
- !Array.isArray(value) &&
1292
- "intermediateSteps" in value) {
1293
- const steps = value.intermediateSteps;
1294
- if (Array.isArray(steps) &&
1295
- steps.length > 0 &&
1296
- steps.every((s) => typeof s === "object" && s !== null && "step" in s && "id" in s && "ok" in s)) {
1297
- intermediateSteps = steps;
1298
- const { intermediateSteps: _removed, ...rest } = value;
1299
- parsed = (Object.keys(rest).length > 0 ? rest : undefined);
1300
- }
1301
- }
1302
- const response = {
1303
- skillKey: request.skillKey,
1304
- rawText: JSON.stringify(value, null, 2),
1305
- flexMd: {
1306
- frame: "localTask.v1",
1307
- payloads: { value: JSON.stringify(value, null, 2) },
1308
- },
1309
- parsed,
1310
- metadata: {
1311
- instructionVersion: "local",
1312
- activityId: undefined,
1313
- durationMs,
1314
- localSkillKey: request.skillKey,
1315
- },
1316
- };
1317
- if (intermediateSteps)
1318
- response.intermediateSteps = intermediateSteps;
1319
- if (isStrictDecisionTask(request)) {
1320
- const parsedMissing = response.parsed === undefined || response.parsed === null;
1321
- if (parsedMissing) {
1322
- throw new Error(`Decision task "${request.skillKey}" did not return response.parsed`);
1323
- }
1324
- }
1325
- const outputValidation = request.outputValidation;
1326
- if (outputValidation?.schema) {
1327
- const validateWhenMissing = outputValidation.validateWhenMissing !== false;
1328
- if (validateWhenMissing || response.parsed !== undefined) {
1329
- const vr = validateParsedOutput(response.parsed, outputValidation.schema);
1330
- vr.correlationId = taskId;
1331
- response.metadata = { ...response.metadata, outputValidation: vr };
1332
- if (!vr.ok && (outputValidation.mode ?? "fail") === "fail") {
1333
- throw new Error(`outputValidation failed for skillKey ${request.skillKey}: ` +
1334
- vr.errors.map((e) => `${e.path} ${e.message}`).join("; "));
1335
- }
1336
- if (!vr.ok && (outputValidation.mode ?? "fail") === "warn") {
1337
- }
1338
- }
1339
- }
1340
- return response;
1341
- },
1342
- onSuccessUpdates: (result) => {
1343
- const steps = result?.intermediateSteps;
1344
- return {
1345
- localSkillKey: result?.metadata?.localSkillKey,
1346
- durationMs: result?.metadata?.durationMs,
1347
- hasIntermediateSteps: Array.isArray(steps) && steps.length > 0,
1348
- stepCount: Array.isArray(steps) ? steps.length : undefined,
1349
- outer: activixOuterTier({
1350
- kind: "localTask.request",
1351
- skillKey: request.skillKey,
1352
- jobId: request.jobId,
1353
- agentId: request.agentId,
1354
- input: summarizeForOuter(request.input, 4_000),
1355
- }, {
1356
- kind: "localTask.response",
1357
- skillKey: result?.skillKey,
1358
- metadata: summarizeForOuter(result?.metadata, 4_000),
1359
- parsed: summarizeForOuter(result?.parsed, 8_000),
1360
- }, { phase: "local" }),
1361
- };
1362
- },
1363
- }), (r) => ({
1364
- metadata: {
1365
- durationMs: r?.metadata?.durationMs,
1366
- },
1367
- modelUsed: null,
1368
- }));
1369
- return withTrace(finalize(result));
1370
- }
1371
- // Execution pipeline: when request.executionPipeline is set, run PRE steps then main then POST
1372
- const pipeline = request.executionPipeline;
1373
- if (pipeline && Array.isArray(pipeline) && pipeline.length > 0) {
1374
- const mainSteps = pipeline.filter((s) => s.phase === "main");
1375
- if (mainSteps.length !== 1) {
1376
- throw new Error(`executionPipeline must have exactly one step with phase "main"; got ${mainSteps.length}. skillKey: ${request.skillKey}`);
1377
- }
1378
- const preSteps = pipeline.filter((s) => s.phase === "pre");
1379
- let overrideContext;
1380
- let synthesizedArtifact;
1381
- let detectedTemplateCores = [];
1382
- // Aggregated trace-mode-only LlmCallObservations from PRE synthesis (markdown/structured/questionDriven).
1383
- // Lifted into `result.metadata.synthesizedContextLlmCalls` once the pipeline finishes.
1384
- const aggregatedSynthLlmCalls = [];
1385
- for (const step of preSteps) {
1386
- if (step.type !== SYNTHESIZED_CONTEXT) {
1387
- throw new Error(`executionPipeline: unsupported PRE step type "${String(step.type)}". Only "${SYNTHESIZED_CONTEXT}" (Xynthesis synthesized-context) is supported.`);
1388
- }
1389
- {
1390
- const config = (step.config ?? {});
1391
- if (request.includeContextInPrompt !== true && config.autoEnableContext !== true) {
1392
- throw new Error("synthesized-context PRE step requires includeContextInPrompt: true or synthesisConfig.autoEnableContext: true");
1393
- }
1394
- const reqWithContext = { ...request, includeContextInPrompt: true };
1395
- const cachedSynth = request.executionMemory?.synthesizedContext;
1396
- const preStepResult = config.reuseCachedSynthesizedContext === true &&
1397
- cachedSynth &&
1398
- reuseableSynthesizedArtifact(cachedSynth)
1399
- ? {
1400
- contextMarkdown: contextMarkdownFromArtifact(cachedSynth),
1401
- artifact: cachedSynth,
1402
- synthesizedInput: request.executionMemory?.synthesizedInput,
1403
- }
1404
- : await traceWrap(traceCollector, {
1405
- taskType: "pre-execution",
1406
- details: "synthesized-context pre step",
1407
- metadata: {
1408
- ...baseTraceMeta(),
1409
- phase: "pipeline_pre",
1410
- preStepType: "synthesized-context",
1411
- synthesisMode: resolveSynthesisMode(config),
1412
- reusedCache: false,
1413
- ...(config.xynthesizedOutput && traceCollector
1414
- ? {
1415
- xynthesized: {
1416
- inputPathsUsed: [...(config.memoryPaths ?? [])],
1417
- outputDestination: config.xynthesizedOutput.destination,
1418
- outputKey: config.xynthesizedOutput.outputKey,
1419
- patchKeys: [config.xynthesizedOutput.outputKey],
1420
- },
1421
- smartInput: {
1422
- paths: reqWithContext.smartInput?.paths ?? [],
1423
- },
1424
- }
1425
- : traceCollector
1426
- ? {
1427
- smartInput: {
1428
- paths: reqWithContext.smartInput?.paths ?? [],
1429
- },
1430
- }
1431
- : {}),
1432
- },
1433
- }, async () => withPhaseRecord({
1434
- ax,
1435
- correlationId,
1436
- phase: "pipeline_pre",
1437
- meta: {
1438
- ...baseMeta,
1439
- preStepType: "synthesized-context",
1440
- outer: activixOuterTier({
1441
- kind: "pipelinePre.synthesizedContext.request",
1442
- skillKey: reqWithContext.skillKey,
1443
- jobId: reqWithContext.jobId,
1444
- agentId: reqWithContext.agentId,
1445
- contextSourcePolicy: config?.contextSourcePolicy,
1446
- synthesisMode: resolveSynthesisMode(config),
1447
- input: summarizeForOuter(reqWithContext.input, 4_000),
1448
- }, null, { phase: "pipeline_pre" }),
1449
- },
1450
- fn: async () => this._runSynthesizedContextPreStep(reqWithContext, config, traceCollector),
1451
- onSuccessUpdates: (r) => ({
1452
- outer: activixOuterTier({
1453
- kind: "pipelinePre.synthesizedContext.request",
1454
- skillKey: reqWithContext.skillKey,
1455
- jobId: reqWithContext.jobId,
1456
- agentId: reqWithContext.agentId,
1457
- contextSourcePolicy: config?.contextSourcePolicy,
1458
- synthesisMode: resolveSynthesisMode(config),
1459
- input: summarizeForOuter(reqWithContext.input, 4_000),
1460
- }, {
1461
- kind: "pipelinePre.synthesizedContext.result",
1462
- contextMarkdown: summarizeForOuter(r.contextMarkdown, 8_000),
1463
- artifact: r.artifact
1464
- ? {
1465
- mode: r.artifact.mode,
1466
- templateCores: r.artifact?.templateCores ?? [],
1467
- question: typeof r.artifact?.question === "string"
1468
- ? summarizeForOuter(r.artifact.question, 2_000)
1469
- : undefined,
1470
- }
1471
- : undefined,
1472
- }, { phase: "pipeline_pre" }),
1473
- }),
1474
- }), (r) => ({
1475
- metadata: {
1476
- synthesizedContextChars: typeof r.contextMarkdown === "string" ? r.contextMarkdown.length : 0,
1477
- ...(config.xynthesizedOutput && traceCollector
1478
- ? {
1479
- xynthesized: {
1480
- inputPathsUsed: [...(config.memoryPaths ?? [])],
1481
- outputDestination: config.xynthesizedOutput.destination,
1482
- outputKey: config.xynthesizedOutput.outputKey,
1483
- patchKeys: [config.xynthesizedOutput.outputKey],
1484
- },
1485
- }
1486
- : {}),
1487
- },
1488
- }));
1489
- overrideContext = preStepResult.contextMarkdown;
1490
- synthesizedArtifact = preStepResult.artifact;
1491
- if (traceCollector && preStepResult.synthesizedContextLlmCalls) {
1492
- aggregatedSynthLlmCalls.push(...preStepResult.synthesizedContextLlmCalls);
1493
- }
1494
- if (synthesizedArtifact) {
1495
- detectedTemplateCores = synthesizedArtifact?.templateCores ?? [];
1496
- }
1497
- const xynthOut = config.xynthesizedOutput;
1498
- const writeLegacyToExecutionMemory = !xynthOut || xynthOut.alsoWriteLegacySynthesizedContext !== false;
1499
- if (synthesizedArtifact && writeLegacyToExecutionMemory) {
1500
- request = {
1501
- ...request,
1502
- executionMemory: {
1503
- ...(request.executionMemory ?? {}),
1504
- synthesizedContext: synthesizedArtifact,
1505
- ...(preStepResult.synthesizedInput ? { synthesizedInput: preStepResult.synthesizedInput } : {}),
1506
- },
1507
- };
1508
- }
1509
- if (xynthOut) {
1510
- const synthesizedResult = synthesizedResultForXynthesizedPatch(synthesizedArtifact, preStepResult.contextMarkdown);
1511
- const { nextXynthesized, patchSlice } = applyXynthesizedOutputWrite(request.xynthesized, xynthOut, synthesizedResult);
1512
- request = { ...request, xynthesized: nextXynthesized };
1513
- xynthesizedPatchAccumulator = mergeXynthesizedPatchSlices(xynthesizedPatchAccumulator, patchSlice);
1514
- }
1515
- if (traceCollector &&
1516
- config.reuseCachedSynthesizedContext === true &&
1517
- cachedSynth &&
1518
- reuseableSynthesizedArtifact(cachedSynth)) {
1519
- traceCollector.push({
1520
- taskType: "pre-execution",
1521
- details: "synthesized-context pre step (reused cached artifact)",
1522
- metadata: {
1523
- ...baseTraceMeta(),
1524
- phase: "pipeline_pre",
1525
- preStepType: "synthesized-context",
1526
- synthesisMode: resolveSynthesisMode(config),
1527
- reusedCache: true,
1528
- ...(config.xynthesizedOutput
1529
- ? {
1530
- xynthesized: {
1531
- inputPathsUsed: [...(config.memoryPaths ?? [])],
1532
- outputDestination: config.xynthesizedOutput.destination,
1533
- outputKey: config.xynthesizedOutput.outputKey,
1534
- patchKeys: [config.xynthesizedOutput.outputKey],
1535
- },
1536
- smartInput: {
1537
- paths: request.smartInput?.paths ?? [],
1538
- },
1539
- }
1540
- : {
1541
- smartInput: {
1542
- paths: request.smartInput?.paths ?? [],
1543
- },
1544
- }),
1545
- },
1546
- modelUsed: null,
1547
- });
1548
- }
1549
- break;
1550
- }
1551
- }
1552
- const synthesizedFromExecution = request.executionMemory?.synthesizedContext &&
1553
- typeof request.executionMemory.synthesizedContext === "object";
1554
- const mainContextSource = synthesizedFromExecution ? "synthesizedContext" : "unsynthesized";
1555
- if (mainContextSource === "synthesizedContext") {
1556
- const artifact = request.executionMemory?.synthesizedContext;
1557
- if (artifact && typeof artifact === "object" && typeof artifact.contextMarkdown === "string") {
1558
- overrideContext = artifact.contextMarkdown;
1559
- }
1560
- }
1561
- const postSteps = pipeline.filter((s) => s.phase === "post");
1562
- const observability = {
1563
- synthesisEnabled: preSteps.some((s) => s.type === SYNTHESIZED_CONTEXT),
1564
- effectiveExecutionPipeline: pipeline,
1565
- synthesizedContextPresent: synthesizedFromExecution,
1566
- mainContextSource,
1567
- detectedTemplateCores,
1568
- synthesisMode: synthesizedArtifact?.mode === "markdown" || synthesizedArtifact?.mode === "structured"
1569
- ? synthesizedArtifact.mode
1570
- : undefined,
1571
- };
1572
- const directOpts = {
1573
- overrideContext,
1574
- synthesisContextAuthoritative: mainContextSource === "synthesizedContext",
1575
- };
1576
- if (postSteps.length === 0) {
1577
- const result = finalize(await runMainWithExecutionStrategies(request, directOpts));
1578
- if (overrideContext !== undefined) {
1579
- const synthesisStep = {
1580
- step: 1,
1581
- id: "synthesis",
1582
- ok: true,
1583
- summary: "context synthesized",
1584
- outputExcerpt: {
1585
- mainContextSource,
1586
- synthesizedContextPresent: observability.synthesizedContextPresent,
1587
- detectedTemplateCores: observability.detectedTemplateCores ?? [],
1588
- },
1589
- };
1590
- const existingSteps = result.intermediateSteps ?? [];
1591
- result.intermediateSteps = [
1592
- synthesisStep,
1593
- ...existingSteps.map((s, i) => ({ ...s, step: i + 2 })),
1594
- ];
1595
- }
1596
- attachExecutionStateAndObservability(result, request, observability);
1597
- if (traceCollector && aggregatedSynthLlmCalls.length > 0) {
1598
- result.metadata = {
1599
- ...(result.metadata ?? {}),
1600
- synthesizedContextLlmCalls: aggregatedSynthLlmCalls,
1601
- };
1602
- }
1603
- return withTrace(result);
1604
- }
1605
- const capture = { contextMarkdown: "" };
1606
- let result = finalize(await runMainWithExecutionStrategies(request, { ...directOpts, captureContext: capture }));
1607
- if (overrideContext !== undefined) {
1608
- const synthesisStep = {
1609
- step: 1,
1610
- id: "synthesis",
1611
- ok: true,
1612
- summary: "context synthesized",
1613
- outputExcerpt: {
1614
- mainContextSource,
1615
- synthesizedContextPresent: observability.synthesizedContextPresent,
1616
- detectedTemplateCores: observability.detectedTemplateCores ?? [],
1617
- },
1618
- };
1619
- const existingSteps = result.intermediateSteps ?? [];
1620
- result.intermediateSteps = [
1621
- synthesisStep,
1622
- ...existingSteps.map((s, i) => ({ ...s, step: i + 2 })),
1623
- ];
1624
- }
1625
- let currentOutput = typeof result.rawText === "string"
1626
- ? result.rawText
1627
- : JSON.stringify(result.parsed ?? result.rawText ?? "", null, 2);
1628
- const postStepsMeta = {};
1629
- let nextStepNumber = (result.intermediateSteps?.length ?? 0) + 1;
1630
- const reRunMain = (overrideContextWithFeedback) => runDirect(request, { overrideContext: overrideContextWithFeedback });
1631
- for (const step of postSteps) {
1632
- if (step.type === "audit") {
1633
- const auditResult = await traceWrap(traceCollector, {
1634
- taskType: "post-execution",
1635
- details: "audit post step",
1636
- metadata: {
1637
- ...baseTraceMeta(),
1638
- phase: "audit",
1639
- postStepType: "audit",
1640
- },
1641
- }, async () => withPhaseRecord({
1642
- ax,
1643
- correlationId,
1644
- phase: "audit",
1645
- meta: {
1646
- ...baseMeta,
1647
- postStepType: "audit",
1648
- outer: activixOuterTier({
1649
- kind: "postStep.audit.request",
1650
- skillKey: request.skillKey,
1651
- jobId: request.jobId,
1652
- agentId: request.agentId,
1653
- input: summarizeForOuter({
1654
- currentOutput,
1655
- hasContextMarkdown: !!capture.contextMarkdown,
1656
- }, 8_000),
1657
- }, null, { phase: "audit" }),
1658
- },
1659
- fn: async () => runAuditPostStep({
1660
- request,
1661
- mainResult: result,
1662
- contextMarkdown: capture.contextMarkdown,
1663
- config: (step.config ?? {}),
1664
- reRunMain,
1665
- traceCollector,
1666
- }),
1667
- onSuccessUpdates: (auditResult) => ({
1668
- totalCycles: auditResult.metadata?.totalCycles,
1669
- allMustPassed: auditResult.metadata?.allMustPassed,
1670
- synthesisUsed: auditResult.metadata?.synthesisUsed,
1671
- durationMs: auditResult.metadata?.durationMs,
1672
- outer: activixOuterTier({
1673
- kind: "postStep.audit.request",
1674
- skillKey: request.skillKey,
1675
- jobId: request.jobId,
1676
- agentId: request.agentId,
1677
- input: summarizeForOuter({
1678
- currentOutput,
1679
- hasContextMarkdown: !!capture.contextMarkdown,
1680
- }, 8_000),
1681
- }, {
1682
- kind: "postStep.audit.result",
1683
- outputText: summarizeForOuter(auditResult.outputText, 8_000),
1684
- metadata: summarizeForOuter(auditResult.metadata, 6_000),
1685
- }, { phase: "audit" }),
1686
- }),
1687
- }), (r) => ({
1688
- metadata: {
1689
- durationMs: r?.metadata?.durationMs,
1690
- totalCycles: r?.metadata?.totalCycles,
1691
- allMustPassed: r?.metadata?.allMustPassed,
1692
- },
1693
- modelUsed: r?.metadata?.modelUsed ?? null,
1694
- }));
1695
- currentOutput = auditResult.outputText;
1696
- postStepsMeta.audit = auditResult.metadata;
1697
- const stepsWithNumbers = auditResult.intermediateSteps.map((s) => ({
1698
- ...s,
1699
- step: nextStepNumber++,
1700
- }));
1701
- result.intermediateSteps = [
1702
- ...(result.intermediateSteps ?? []),
1703
- ...stepsWithNumbers,
1704
- ];
1705
- }
1706
- else if (step.type === "polish") {
1707
- const polishResult = await traceWrap(traceCollector, {
1708
- taskType: "post-execution",
1709
- details: "polish post step",
1710
- metadata: {
1711
- ...baseTraceMeta(),
1712
- phase: "polish",
1713
- postStepType: "polish",
1714
- },
1715
- }, async () => withPhaseRecord({
1716
- ax,
1717
- correlationId,
1718
- phase: "polish",
1719
- meta: {
1720
- ...baseMeta,
1721
- postStepType: "polish",
1722
- outer: activixOuterTier({
1723
- kind: "postStep.polish.request",
1724
- skillKey: request.skillKey,
1725
- jobId: request.jobId,
1726
- agentId: request.agentId,
1727
- input: summarizeForOuter({ currentOutput }, 8_000),
1728
- }, null, { phase: "polish" }),
1729
- },
1730
- fn: async () => runPolishPostStep({
1731
- currentOutput,
1732
- config: (step.config ?? {}),
1733
- originalInput: step.config?.includeOriginalContext ? request.input : undefined,
1734
- promptContext: step.config?.includeOriginalContext ? capture.contextMarkdown : undefined,
1735
- traceCollector,
1736
- jobId: request.jobId,
1737
- taskId: request.taskId,
1738
- skillKey: request.skillKey,
1739
- agentId: request.agentId,
1740
- graphId: request.graphId,
1741
- nodeId: request.nodeId,
1742
- prevNodeId: request.prevNodeId,
1743
- coreSkillId: request.coreSkillId,
1744
- masterSkillId: request.masterSkillId,
1745
- identity: request.identity,
1746
- modelConfig: request.modelConfig,
1747
- }),
1748
- onSuccessUpdates: (polishResult) => ({
1749
- totalPasses: polishResult.metadata?.totalPasses,
1750
- durationMs: polishResult.metadata?.durationMs,
1751
- outer: activixOuterTier({
1752
- kind: "postStep.polish.request",
1753
- skillKey: request.skillKey,
1754
- jobId: request.jobId,
1755
- agentId: request.agentId,
1756
- input: summarizeForOuter({ currentOutput }, 8_000),
1757
- }, {
1758
- kind: "postStep.polish.result",
1759
- outputText: summarizeForOuter(polishResult.outputText, 8_000),
1760
- metadata: summarizeForOuter(polishResult.metadata, 6_000),
1761
- }, { phase: "polish" }),
1762
- }),
1763
- }), (r) => ({
1764
- metadata: {
1765
- durationMs: r?.metadata?.durationMs,
1766
- totalPasses: r?.metadata?.totalPasses,
1767
- },
1768
- modelUsed: r?.metadata?.modelUsed ?? null,
1769
- }));
1770
- currentOutput = polishResult.outputText;
1771
- postStepsMeta.polish = polishResult.metadata;
1772
- const stepsWithNumbers = polishResult.intermediateSteps.map((s) => ({
1773
- ...s,
1774
- step: nextStepNumber++,
1775
- }));
1776
- result.intermediateSteps = [
1777
- ...(result.intermediateSteps ?? []),
1778
- ...stepsWithNumbers,
1779
- ];
1780
- }
1781
- }
1782
- result.rawText = currentOutput;
1783
- result.parsed = currentOutput;
1784
- result.metadata = {
1785
- ...(result.metadata ?? {}),
1786
- postSteps: postStepsMeta,
1787
- ...(traceCollector && aggregatedSynthLlmCalls.length > 0
1788
- ? { synthesizedContextLlmCalls: aggregatedSynthLlmCalls }
1789
- : {}),
1790
- };
1791
- attachExecutionStateAndObservability(result, request, observability, knobs);
1792
- return withTrace(result);
1793
- }
1794
- // MAIN path (direct / gateway skill). Narrix handler runs earlier when `narrixMode === "handler"`.
1795
- {
1796
- const result = finalize(await runMainWithExecutionStrategies(request));
1797
- attachExecutionStateAndObservability(result, request, {
1798
- synthesisEnabled: false,
1799
- synthesizedContextPresent: !!request.executionMemory?.synthesizedContext,
1800
- mainContextSource: "unsynthesized",
1801
- }, knobs);
1802
- return withTrace(result);
1803
- }
883
+ const xynthesizedPatchRef = {};
884
+ const host = createNodeExecutionHost({
885
+ runSynthesizedContextPreStep: (req, config) => this._runSynthesizedContextPreStep(req, config, traceCollector),
886
+ runMainWithExecutionStrategies,
887
+ traceCollector,
888
+ taskId,
889
+ isStrictDecisionTask,
890
+ xynthesizedPatchAccumulator: xynthesizedPatchRef,
891
+ });
892
+ const planResult = await executeNodeFromPlan({
893
+ request: { ...request, nodePlan: input.nodePlan, executionTrace: input.executionTrace },
894
+ host,
895
+ trace: input.executionTrace,
896
+ });
897
+ xynthesizedPatchAccumulator = xynthesizedPatchRef.value;
898
+ attachExecutionStateAndObservability(planResult, request, synthesisObservabilityFromNodePlan(input.nodePlan, planResult), knobs);
899
+ return withTrace(finalize(planResult));
1804
900
  }
1805
901
  catch (error) {
1806
902
  throw logAndEnrichRunTaskFailure({
@@ -1816,6 +912,17 @@ export class WorexClientTasks {
1816
912
  */
1817
913
  async _runSynthesizedContextPreStep(request, config, traceCollector) {
1818
914
  const input = request;
915
+ if (config.reuseCachedSynthesizedContext === true) {
916
+ const cached = input.executionMemory?.synthesizedContext;
917
+ const markdown = typeof cached?.contextMarkdown === "string" ? cached.contextMarkdown.trim() : "";
918
+ if (cached && markdown) {
919
+ return {
920
+ contextMarkdown: markdown,
921
+ artifact: cached,
922
+ synthesizedInput: input.executionMemory?.synthesizedInput,
923
+ };
924
+ }
925
+ }
1819
926
  let jobMemoryWithExecution = input.jobMemory || {};
1820
927
  if (input.executionMemory) {
1821
928
  const executionWithDefaults = {