@exellix/graph-engine 8.1.7 → 8.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  # Changelog
2
2
 
3
- ## 8.1.3 (unreleased)
3
+ ## 8.1.8
4
+
5
+ ### Changed
6
+
7
+ - **Graphenix 2.1.0 alignment (Tier 2 + 3):** `@x12i/graphenix-core` ^2.0.1 (`formatVersion: "2.1.0"`); lifecycle `@x12i/graphenix-*` ^2.0.0; testkit emits `metadata.modelConfig` (no `metadata.extensions`, no `parameters.profile` / `nodeType`).
8
+ - **`@exellix/ai-tasks` ^9.1.0** — accepts parent plan `"executable-plan"` v2 and trace `"execution-trace"` v2; dedupes nested `graphenix-*@1.1.x` under ai-tasks.
9
+ - **`check:no-legacy`** — fails when ai-tasks < 9.1.0, graphenix-core < 2.0.1, or ai-tasks nests duplicate `@x12i/graphenix-*`.
10
+
11
+ ### Added
12
+
13
+ - **`tests/reference-fixtures-compile.test.ts`** — compiles `graph-content-pipeline` and `graph-subnets-analysis` authoring fixtures; asserts `validateExecutablePlanV2`.
14
+
15
+ ## 8.1.3
4
16
 
5
17
  ### Changed
6
18
 
@@ -1,7 +1,7 @@
1
1
  import type { ExecuteGraphInput } from './ExellixGraphRuntime.js';
2
2
  /**
3
3
  * Removed from the graphs-studio execute envelope (7.8.3+). No reader, no fallback.
4
- * Default model selection belongs on authoring graph executable profile only.
4
+ * Default model selection belongs on `graph.metadata.modelConfig` only.
5
5
  */
6
6
  export declare const STUDIO_GRAPH_EXECUTE_REMOVED_KEYS: readonly ["graphDefaultModel"];
7
7
  export type StudioGraphExecuteRemovedKey = (typeof STUDIO_GRAPH_EXECUTE_REMOVED_KEYS)[number];
@@ -3,7 +3,7 @@ import { ExellixGraphError } from '../errors/ExellixGraphError.js';
3
3
  import { ExellixGraphErrorCode } from '../errors/exellixGraphErrorCodes.js';
4
4
  /**
5
5
  * Removed from the graphs-studio execute envelope (7.8.3+). No reader, no fallback.
6
- * Default model selection belongs on authoring graph executable profile only.
6
+ * Default model selection belongs on `graph.metadata.modelConfig` only.
7
7
  */
8
8
  export const STUDIO_GRAPH_EXECUTE_REMOVED_KEYS = ['graphDefaultModel'];
9
9
  function isPlainObject(v) {
@@ -20,7 +20,7 @@ export function getStudioGraphExecuteRemovedKeyViolations(request) {
20
20
  export function assertCanonicalStudioGraphExecuteRequest(request, context) {
21
21
  const removed = getStudioGraphExecuteRemovedKeyViolations(request);
22
22
  if (removed.length > 0) {
23
- throw new ExellixGraphError(ExellixGraphErrorCode.NON_CANONICAL_STUDIO_GRAPH_EXECUTE_REQUEST, `Studio graph execute request must not include removed field(s): ${removed.join(', ')}. Model defaults belong on the authoring graph executable profile only; request-level graphDefaultModel was removed with no legacy fallback.`, { ...context, removedKeys: removed });
23
+ throw new ExellixGraphError(ExellixGraphErrorCode.NON_CANONICAL_STUDIO_GRAPH_EXECUTE_REQUEST, `Studio graph execute request must not include removed field(s): ${removed.join(', ')}. Model defaults belong on graph.metadata.modelConfig only; request-level graphDefaultModel was removed with no legacy fallback.`, { ...context, removedKeys: removed });
24
24
  }
25
25
  if (!isPlainObject(request) || request.mode !== 'graph' || typeof request.jobId !== 'string') {
26
26
  throw new ExellixGraphError(ExellixGraphErrorCode.NON_CANONICAL_STUDIO_GRAPH_EXECUTE_REQUEST, 'Studio graph execute request requires mode graph and jobId.', context);
@@ -1,32 +1,6 @@
1
1
  import { GRAPHENIX_FORMAT_VERSION } from '@x12i/graphenix-core';
2
- import { EXECUTABLE_PROFILE_NAMESPACE, EXECUTABLE_PROFILE_VERSION, FINALIZER_NODE_KIND, FINALIZER_NODE_PROFILE, TASK_NODE_KIND, TASK_NODE_PROFILE, } from '@x12i/graphenix-executable-contracts';
3
- function defaultExecutableModelConfig() {
4
- return {
5
- version: 'graph-model-config/v1',
6
- cases: [
7
- {
8
- id: 'default',
9
- modelConfig: {
10
- preActionModel: { kind: 'profileChoice', key: 'cheap/default' },
11
- skillModel: { kind: 'profileChoice', key: 'pro/default' },
12
- postActionModel: { kind: 'profileChoice', key: 'cheap/default' },
13
- },
14
- },
15
- ],
16
- fallbackPolicy: {
17
- enabled: true,
18
- allowedTriggers: [
19
- 'nodeSlotMissing',
20
- 'nodeModelUnavailable',
21
- 'nodeModelUnsupported',
22
- 'nodeProviderNotConfigured',
23
- 'nodeModelRateLimited',
24
- 'nodeModelTransientFailure',
25
- ],
26
- maxAttemptsPerSlot: 1,
27
- },
28
- };
29
- }
2
+ import { FINALIZER_NODE_KIND, TASK_NODE_KIND } from '@x12i/graphenix-executable-contracts';
3
+ import { defaultExecutableModelConfig } from './flatGraphToAuthoring.js';
30
4
  function authoringShell(graphId, nodes, edges, graphResponseShape, extra) {
31
5
  const taskNodes = nodes.filter((n) => n.kind === TASK_NODE_KIND);
32
6
  const finalizer = nodes.find((n) => n.kind === FINALIZER_NODE_KIND);
@@ -58,12 +32,7 @@ function authoringShell(graphId, nodes, edges, graphResponseShape, extra) {
58
32
  : [],
59
33
  metadata: {
60
34
  graphResponse: { shape: graphResponseShape },
61
- extensions: {
62
- [EXECUTABLE_PROFILE_NAMESPACE]: {
63
- profileVersion: EXECUTABLE_PROFILE_VERSION,
64
- modelConfig: defaultExecutableModelConfig(),
65
- },
66
- },
35
+ modelConfig: defaultExecutableModelConfig(),
67
36
  ...extra,
68
37
  },
69
38
  },
@@ -80,8 +49,6 @@ export function buildAiTaskAuthoringGraph(graphId) {
80
49
  inputs: [{ id: 'in:record', direction: 'input', type: 'builtin:object', required: true }],
81
50
  outputs: [{ id: 'out:answer', direction: 'output', type: 'builtin:object' }],
82
51
  parameters: {
83
- profile: TASK_NODE_PROFILE,
84
- nodeType: 'task',
85
52
  skillKey: 'professional-answer',
86
53
  executionMapping: {
87
54
  path: 'answers.ask1',
@@ -97,8 +64,6 @@ export function buildAiTaskAuthoringGraph(graphId) {
97
64
  inputs: [{ id: 'in:answer', direction: 'input', type: 'builtin:object', required: true }],
98
65
  outputs: [{ id: 'out:final', direction: 'output', type: 'builtin:object' }],
99
66
  parameters: {
100
- profile: FINALIZER_NODE_PROFILE,
101
- nodeType: 'finalizer',
102
67
  finalizerType: 'select',
103
68
  inputs: {
104
69
  answer: { type: 'executionMemoryPath', path: 'answers.ask1.answer' },
@@ -126,8 +91,6 @@ export function buildLocalSkillAuthoringGraph(graphId) {
126
91
  inputs: [{ id: 'in:record', direction: 'input', type: 'builtin:object', required: true }],
127
92
  outputs: [{ id: 'out:answer', direction: 'output', type: 'builtin:object' }],
128
93
  parameters: {
129
- profile: TASK_NODE_PROFILE,
130
- nodeType: 'task',
131
94
  skillKey: 'deterministic-rule',
132
95
  taskConfiguration: {
133
96
  rules: [{ id: 'always', condition: { all: [] }, output: { decision: 'go' } }],
@@ -146,8 +109,6 @@ export function buildLocalSkillAuthoringGraph(graphId) {
146
109
  inputs: [{ id: 'in:answer', direction: 'input', type: 'builtin:object', required: true }],
147
110
  outputs: [{ id: 'out:final', direction: 'output', type: 'builtin:object' }],
148
111
  parameters: {
149
- profile: FINALIZER_NODE_PROFILE,
150
- nodeType: 'finalizer',
151
112
  finalizerType: 'select',
152
113
  inputs: {
153
114
  decision: { type: 'executionMemoryPath', path: 'rule.decision' },
@@ -176,8 +137,6 @@ export function buildGraphResponseMappingAuthoringGraph(graphId) {
176
137
  inputs: [{ id: 'in:record', direction: 'input', type: 'builtin:object', required: true }],
177
138
  outputs: [{ id: 'out:answer', direction: 'output', type: 'builtin:object' }],
178
139
  parameters: {
179
- profile: TASK_NODE_PROFILE,
180
- nodeType: 'task',
181
140
  skillKey: 'professional-answer',
182
141
  taskVariable: { question },
183
142
  executionMapping: {
@@ -197,8 +156,6 @@ export function buildGraphResponseMappingAuthoringGraph(graphId) {
197
156
  ],
198
157
  outputs: [{ id: 'out:final', direction: 'output', type: 'builtin:object' }],
199
158
  parameters: {
200
- profile: FINALIZER_NODE_PROFILE,
201
- nodeType: 'finalizer',
202
159
  finalizerType: 'aggregate',
203
160
  config: {
204
161
  sections: [
@@ -239,11 +196,8 @@ export function buildGraphResponseMappingAuthoringGraph(graphId) {
239
196
  export function withAuthoringGraphModelConfig(doc, modelConfig) {
240
197
  const next = structuredClone(doc);
241
198
  const metadata = next.graph.metadata;
242
- if (!metadata?.extensions)
199
+ if (!metadata)
243
200
  return next;
244
- const profile = metadata.extensions[EXECUTABLE_PROFILE_NAMESPACE];
245
- if (profile && typeof profile === 'object') {
246
- Object.assign(profile, { modelConfig });
247
- }
201
+ metadata.modelConfig = modelConfig;
248
202
  return next;
249
203
  }
@@ -21,7 +21,7 @@ export declare function defaultExecutableModelConfig(): {
21
21
  }[];
22
22
  fallbackPolicy: {
23
23
  enabled: boolean;
24
- allowedTriggers: readonly ["nodeSlotMissing", "nodeModelUnavailable", "nodeModelUnsupported", "nodeProviderNotConfigured", "nodeModelRateLimited", "nodeModelTransientFailure"];
24
+ allowedTriggers: string[];
25
25
  maxAttemptsPerSlot: number;
26
26
  };
27
27
  };
@@ -1,5 +1,5 @@
1
1
  import { GRAPHENIX_FORMAT_VERSION } from '@x12i/graphenix-core';
2
- import { EXECUTABLE_PROFILE_NAMESPACE, EXECUTABLE_PROFILE_VERSION, FINALIZER_NODE_KIND, FINALIZER_NODE_PROFILE, TASK_NODE_KIND, TASK_NODE_PROFILE, } from '@x12i/graphenix-executable-contracts';
2
+ import { FINALIZER_NODE_KIND, TASK_NODE_KIND } from '@x12i/graphenix-executable-contracts';
3
3
  const ALIAS_TO_CHOICE = {
4
4
  cheap: 'cheap/default',
5
5
  balanced: 'vol/default',
@@ -130,10 +130,7 @@ function patchTaskConfigurationModelConfig(taskConfiguration) {
130
130
  }
131
131
  function flatTaskNodeToAuthoring(node) {
132
132
  const { id, skillKey, taskVariable, executionMapping, taskConfiguration, inputsConfig, conditions, variables, metadata, executionPipeline, taskKnowledge, smartInput, data, } = node;
133
- const parameters = {
134
- profile: TASK_NODE_PROFILE,
135
- nodeType: 'task',
136
- };
133
+ const parameters = {};
137
134
  if (typeof skillKey === 'string')
138
135
  parameters.skillKey = skillKey;
139
136
  if (taskVariable !== undefined)
@@ -182,8 +179,6 @@ function flatFinalizerNodeToAuthoring(node, incoming) {
182
179
  }))
183
180
  : [{ id: 'in:final', direction: 'input', type: 'builtin:object', required: false }];
184
181
  const parameters = {
185
- profile: FINALIZER_NODE_PROFILE,
186
- nodeType: 'finalizer',
187
182
  finalizerType: node.finalizerType,
188
183
  config: isPlainRecord(node.config) ? node.config : {},
189
184
  };
@@ -233,19 +228,12 @@ export function flatTestGraphToAuthoringDocument(flat) {
233
228
  metadata.jobKnowledge = normalizeKnowledgeRefs(flat.jobKnowledge);
234
229
  if (Array.isArray(flat.taskKnowledge))
235
230
  metadata.taskKnowledge = normalizeKnowledgeRefs(flat.taskKnowledge);
236
- const executableProfile = {
237
- profileVersion: EXECUTABLE_PROFILE_VERSION,
238
- modelConfig: flatModelConfigToAuthoring(flat.modelConfig) ?? defaultExecutableModelConfig(),
239
- };
240
231
  metadata.graphResponse = {
241
232
  ...(flatResponse.missing != null ? { missing: flatResponse.missing } : {}),
242
233
  ...(flatResponse.version != null ? { version: flatResponse.version } : {}),
243
234
  shape: responseShape,
244
235
  };
245
- metadata.extensions = {
246
- ...(isPlainRecord(metadata.extensions) ? metadata.extensions : {}),
247
- [EXECUTABLE_PROFILE_NAMESPACE]: executableProfile,
248
- };
236
+ metadata.modelConfig = flatModelConfigToAuthoring(flat.modelConfig) ?? defaultExecutableModelConfig();
249
237
  const taskNodes = nodes.filter((n) => n.kind === TASK_NODE_KIND);
250
238
  const finalizer = nodes.find((n) => n.kind === FINALIZER_NODE_KIND);
251
239
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exellix/graph-engine",
3
- "version": "8.1.7",
3
+ "version": "8.1.8",
4
4
  "type": "module",
5
5
  "description": "Graph executor SDK",
6
6
  "main": "dist/src/index.js",
@@ -25,8 +25,8 @@
25
25
  "scripts": {
26
26
  "prebuild": "node scripts/clean-dist.mjs",
27
27
  "build": "tsc",
28
- "test": "npm run build && npm run check:no-legacy && tsx --test --test-force-exit --test-timeout=60000 tests/model-alias-canonical.test.ts tests/model-alias-execute.test.ts tests/model-alias-strategy.test.ts tests/model-alias-subnets.test.ts tests/ai-tasks-error-propagation.test.ts tests/reports-fixtures-pre-synthesis.test.ts tests/passthrough-parity.test.ts tests/step-retry-llm-call.test.ts tests/run-log-diagnostics.test.ts",
29
- "test:full": "npm run build && npm run check:no-legacy && tsx --test --test-force-exit --test-timeout=60000 tests/graph-engine.test.ts tests/passthrough-parity.test.ts tests/task-node-run-task-preflight.test.ts tests/reports-fixtures-pre-synthesis.test.ts tests/model-alias-canonical.test.ts tests/model-alias-execute.test.ts tests/model-alias-strategy.test.ts tests/model-alias-subnets.test.ts tests/compile-host-patches.test.ts tests/step-retry-llm-call.test.ts",
28
+ "test": "npm run build && npm run check:no-legacy && tsx --test --test-force-exit --test-timeout=180000 --test-concurrency=2 tests/model-alias-canonical.test.ts tests/model-alias-execute.test.ts tests/model-alias-strategy.test.ts tests/model-alias-subnets.test.ts tests/ai-tasks-error-propagation.test.ts tests/reports-fixtures-pre-synthesis.test.ts tests/passthrough-parity.test.ts tests/step-retry-llm-call.test.ts tests/run-log-diagnostics.test.ts",
29
+ "test:full": "npm run build && npm run check:no-legacy && tsx --test --test-force-exit --test-timeout=180000 --test-concurrency=2 tests/graph-engine.test.ts tests/passthrough-parity.test.ts tests/task-node-run-task-preflight.test.ts tests/reports-fixtures-pre-synthesis.test.ts tests/model-alias-canonical.test.ts tests/model-alias-execute.test.ts tests/model-alias-strategy.test.ts tests/model-alias-subnets.test.ts tests/compile-host-patches.test.ts tests/reference-fixtures-compile.test.ts tests/step-retry-llm-call.test.ts",
30
30
  "test:live": "npm run run:pre-synthesis",
31
31
  "test:subnets-graph-fixture": "npm run build && node --test tests/subnets-graph.fixture.test.mjs",
32
32
  "test:subnets-graph-live": "npm run build && node --env-file=.env --test tests/subnets-graph.live.test.mjs",
@@ -52,27 +52,28 @@
52
52
  "access": "public"
53
53
  },
54
54
  "dependencies": {
55
- "@exellix/ai-skills": "^6.7.0",
56
- "@exellix/ai-tasks": "^9.0.6",
57
- "@x12i/activix": "^8.6.2",
58
- "@x12i/catalox": "5.1.3",
59
- "@x12i/env": "4.0.1",
55
+ "@exellix/ai-skills": "^6.9.0",
56
+ "@exellix/ai-tasks": "^9.1.0",
57
+ "@x12i/activix": "^8.6.3",
58
+ "@x12i/catalox": "^5.2.0",
59
+ "@x12i/env": "^4.0.1",
60
60
  "@x12i/funcx": "^4.9.6",
61
- "@x12i/graphenix": "2.5.0",
62
- "@x12i/graphenix-authoring-format": "^1.2.1",
63
- "@x12i/graphenix-executable-contracts": "^1.1.0",
64
- "@x12i/graphenix-executable-format": "^2.1.4",
65
- "@x12i/graphenix-execute-envelope": "^1.1.1",
66
- "@x12i/graphenix-format": "2.0.0",
67
- "@x12i/graphenix-plan-compiler": "^1.1.1",
68
- "@x12i/graphenix-plan-format": "^1.1.1",
69
- "@x12i/graphenix-trace-format": "^1.1.1",
61
+ "@x12i/graphenix": "^2.5.0",
62
+ "@x12i/graphenix-authoring-format": "^2.0.0",
63
+ "@x12i/graphenix-core": "^2.0.1",
64
+ "@x12i/graphenix-executable-contracts": "^2.0.0",
65
+ "@x12i/graphenix-executable-format": "^2.2.0",
66
+ "@x12i/graphenix-execute-envelope": "^2.0.0",
67
+ "@x12i/graphenix-format": "^2.0.0",
68
+ "@x12i/graphenix-plan-compiler": "^2.0.0",
69
+ "@x12i/graphenix-plan-format": "^2.0.0",
70
+ "@x12i/graphenix-trace-format": "^2.0.0",
70
71
  "@x12i/logxer": "^4.6.0",
71
- "@x12i/memorix-descriptors": "1.6.0",
72
- "@x12i/memorix-retrieval": "1.11.2",
73
- "@x12i/memorix-writer": "1.0.0",
74
- "@x12i/rendrix": "4.3.0",
75
- "@x12i/runx": "1.3.2"
72
+ "@x12i/memorix-descriptors": "^1.6.0",
73
+ "@x12i/memorix-retrieval": "^1.11.2",
74
+ "@x12i/memorix-writer": "^1.0.0",
75
+ "@x12i/rendrix": "^4.3.0",
76
+ "@x12i/runx": "^1.3.2"
76
77
  },
77
78
  "devDependencies": {
78
79
  "@types/node": "25.9.1",