@exellix/graph-engine 8.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -1
- package/README.md +11 -12
- package/dist/src/compile/authoringDocumentHelpers.d.ts +9 -0
- package/dist/src/compile/authoringDocumentHelpers.js +18 -0
- package/dist/src/compile/compileExellixExecutablePlan.d.ts +8 -0
- package/dist/src/compile/compileExellixExecutablePlan.js +75 -0
- package/dist/src/index.d.ts +4 -6
- package/dist/src/index.js +2 -4
- package/dist/src/runtime/ExellixGraphRuntime.d.ts +11 -37
- package/dist/src/runtime/ExellixGraphRuntime.js +78 -173
- package/dist/src/runtime/aiTasksStrategyPhases.js +7 -3
- package/dist/src/runtime/buildAiTasksRunTaskRequest.d.ts +6 -8
- package/dist/src/runtime/buildAiTasksRunTaskRequest.js +2 -7
- package/dist/src/runtime/executionMatrixHost.d.ts +6 -3
- package/dist/src/runtime/executionMatrixHost.js +6 -4
- package/dist/src/runtime/runTaskNodePlan.d.ts +15 -0
- package/dist/src/runtime/runTaskNodePlan.js +46 -0
- package/dist/src/runtime/studioGraphExecuteRequest.d.ts +5 -30
- package/dist/src/runtime/studioGraphExecuteRequest.js +14 -50
- package/dist/src/runtime/taskNodeRunTaskPreflight.d.ts +7 -5
- package/dist/src/runtime/taskNodeRunTaskPreflight.js +31 -26
- package/dist/src/types/refs.d.ts +1 -1
- package/dist/testkit/authoringGraphFixtures.d.ts +8 -0
- package/dist/testkit/authoringGraphFixtures.js +249 -0
- package/dist/testkit/buildExecuteGraphInput.d.ts +3 -3
- package/dist/testkit/buildExecuteGraphInput.js +8 -4
- package/dist/testkit/flatGraphToAuthoring.d.ts +29 -0
- package/dist/testkit/flatGraphToAuthoring.js +281 -0
- package/dist/testkit/index.d.ts +3 -0
- package/dist/testkit/index.js +3 -0
- package/dist/testkit/runTaskNodePlanAssertions.d.ts +34 -0
- package/dist/testkit/runTaskNodePlanAssertions.js +32 -0
- package/package.json +8 -7
- package/dist/src/adapters/compileExellixExecutablePlan.d.ts +0 -8
- package/dist/src/adapters/compileExellixExecutablePlan.js +0 -18
- package/dist/src/adapters/migrateExellixGraphModelToAuthoring.d.ts +0 -6
- package/dist/src/adapters/migrateExellixGraphModelToAuthoring.js +0 -273
- package/dist/src/adapters/patchFinalizerPlans.d.ts +0 -7
- package/dist/src/adapters/patchFinalizerPlans.js +0 -63
- package/dist/src/runtime/graphResponseMigration.d.ts +0 -7
- package/dist/src/runtime/graphResponseMigration.js +0 -44
|
@@ -0,0 +1,281 @@
|
|
|
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
|
+
const ALIAS_TO_CHOICE = {
|
|
4
|
+
cheap: 'cheap/default',
|
|
5
|
+
balanced: 'vol/default',
|
|
6
|
+
deep: 'deep/openai_deep',
|
|
7
|
+
pro: 'pro/default',
|
|
8
|
+
};
|
|
9
|
+
function isPlainRecord(v) {
|
|
10
|
+
return v != null && typeof v === 'object' && !Array.isArray(v);
|
|
11
|
+
}
|
|
12
|
+
export function isAuthoringGraphDocument(v) {
|
|
13
|
+
return isPlainRecord(v) && typeof v.formatVersion === 'string' && isPlainRecord(v.graph);
|
|
14
|
+
}
|
|
15
|
+
function toProfileChoice(value) {
|
|
16
|
+
if (isPlainRecord(value) && value.kind === 'profileChoice' && typeof value.key === 'string') {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
if (typeof value === 'string' && value.trim().length > 0) {
|
|
20
|
+
const key = value.includes('/') ? value : ALIAS_TO_CHOICE[value] ?? `${value}/default`;
|
|
21
|
+
return { kind: 'profileChoice', key };
|
|
22
|
+
}
|
|
23
|
+
return { kind: 'profileChoice', key: 'pro/default' };
|
|
24
|
+
}
|
|
25
|
+
export function defaultExecutableModelConfig() {
|
|
26
|
+
return {
|
|
27
|
+
version: 'graph-model-config/v1',
|
|
28
|
+
cases: [
|
|
29
|
+
{
|
|
30
|
+
id: 'default',
|
|
31
|
+
modelConfig: {
|
|
32
|
+
preActionModel: { kind: 'profileChoice', key: 'cheap/default' },
|
|
33
|
+
skillModel: { kind: 'profileChoice', key: 'pro/default' },
|
|
34
|
+
postActionModel: { kind: 'profileChoice', key: 'cheap/default' },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
fallbackPolicy: {
|
|
39
|
+
enabled: true,
|
|
40
|
+
allowedTriggers: [
|
|
41
|
+
'nodeSlotMissing',
|
|
42
|
+
'nodeModelUnavailable',
|
|
43
|
+
'nodeModelUnsupported',
|
|
44
|
+
'nodeProviderNotConfigured',
|
|
45
|
+
'nodeModelRateLimited',
|
|
46
|
+
'nodeModelTransientFailure',
|
|
47
|
+
],
|
|
48
|
+
maxAttemptsPerSlot: 1,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function flatModelConfigToAuthoring(modelConfig) {
|
|
53
|
+
if (!isPlainRecord(modelConfig) || !Array.isArray(modelConfig.cases)) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
version: 'graph-model-config/v1',
|
|
58
|
+
cases: modelConfig.cases.map((entry, index) => {
|
|
59
|
+
const row = isPlainRecord(entry) ? entry : {};
|
|
60
|
+
const mc = isPlainRecord(row.modelConfig) ? row.modelConfig : {};
|
|
61
|
+
const casesLen = modelConfig.cases.length;
|
|
62
|
+
return {
|
|
63
|
+
id: typeof row.id === 'string' && row.id.trim().length > 0 ? row.id : index === casesLen - 1 ? 'default' : `case-${index}`,
|
|
64
|
+
...(row.when != null ? { when: row.when } : {}),
|
|
65
|
+
modelConfig: {
|
|
66
|
+
preActionModel: toProfileChoice(mc.preActionModel),
|
|
67
|
+
skillModel: toProfileChoice(mc.skillModel),
|
|
68
|
+
postActionModel: toProfileChoice(mc.postActionModel),
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}),
|
|
72
|
+
fallbackPolicy: defaultExecutableModelConfig().fallbackPolicy,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function normalizeKnowledgeRefs(refs) {
|
|
76
|
+
if (!Array.isArray(refs))
|
|
77
|
+
return refs;
|
|
78
|
+
return refs.map((ref) => {
|
|
79
|
+
if (typeof ref === 'string')
|
|
80
|
+
return { id: ref };
|
|
81
|
+
return ref;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function normalizeSmartInput(smartInput) {
|
|
85
|
+
if (!isPlainRecord(smartInput) || !Array.isArray(smartInput.paths))
|
|
86
|
+
return smartInput;
|
|
87
|
+
return {
|
|
88
|
+
...smartInput,
|
|
89
|
+
paths: smartInput.paths.map((entry) => {
|
|
90
|
+
if (typeof entry === 'string') {
|
|
91
|
+
const path = entry.startsWith('taskVariables.') || entry.startsWith('jobVariables.')
|
|
92
|
+
? `executionMemory.${entry}`
|
|
93
|
+
: entry;
|
|
94
|
+
return { path };
|
|
95
|
+
}
|
|
96
|
+
if (isPlainRecord(entry) && typeof entry.path === 'string') {
|
|
97
|
+
const path = entry.path;
|
|
98
|
+
if (path.startsWith('taskVariables.') || path.startsWith('jobVariables.')) {
|
|
99
|
+
return { ...entry, path: `executionMemory.${path}` };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return entry;
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function normalizeJsonConditions(conditions) {
|
|
107
|
+
if (!isPlainRecord(conditions))
|
|
108
|
+
return conditions;
|
|
109
|
+
const next = { ...conditions };
|
|
110
|
+
const jc = next.jsonConditions;
|
|
111
|
+
if (jc != null && !Array.isArray(jc)) {
|
|
112
|
+
if (isPlainRecord(jc) && isPlainRecord(jc.condition) && Array.isArray(jc.condition.all)) {
|
|
113
|
+
next.jsonConditions = jc.condition.all;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
next.jsonConditions = [jc];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return next;
|
|
120
|
+
}
|
|
121
|
+
function patchTaskConfigurationModelConfig(taskConfiguration) {
|
|
122
|
+
if (!isPlainRecord(taskConfiguration) || !isPlainRecord(taskConfiguration.modelConfig)) {
|
|
123
|
+
return taskConfiguration;
|
|
124
|
+
}
|
|
125
|
+
const next = structuredClone(taskConfiguration);
|
|
126
|
+
const authored = flatModelConfigToAuthoring(next.modelConfig);
|
|
127
|
+
if (authored)
|
|
128
|
+
next.modelConfig = authored;
|
|
129
|
+
return next;
|
|
130
|
+
}
|
|
131
|
+
function flatTaskNodeToAuthoring(node) {
|
|
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
|
+
};
|
|
137
|
+
if (typeof skillKey === 'string')
|
|
138
|
+
parameters.skillKey = skillKey;
|
|
139
|
+
if (taskVariable !== undefined)
|
|
140
|
+
parameters.taskVariable = taskVariable;
|
|
141
|
+
if (executionMapping !== undefined)
|
|
142
|
+
parameters.executionMapping = executionMapping;
|
|
143
|
+
if (inputsConfig !== undefined)
|
|
144
|
+
parameters.inputsConfig = inputsConfig;
|
|
145
|
+
if (conditions !== undefined)
|
|
146
|
+
parameters.conditions = normalizeJsonConditions(conditions);
|
|
147
|
+
if (variables !== undefined)
|
|
148
|
+
parameters.variables = variables;
|
|
149
|
+
if (metadata !== undefined)
|
|
150
|
+
parameters.metadata = metadata;
|
|
151
|
+
if (executionPipeline !== undefined)
|
|
152
|
+
parameters.executionPipeline = executionPipeline;
|
|
153
|
+
if (taskKnowledge !== undefined)
|
|
154
|
+
parameters.taskKnowledge = normalizeKnowledgeRefs(taskKnowledge);
|
|
155
|
+
if (smartInput !== undefined)
|
|
156
|
+
parameters.smartInput = normalizeSmartInput(smartInput);
|
|
157
|
+
if (data !== undefined)
|
|
158
|
+
parameters.data = data;
|
|
159
|
+
if (taskConfiguration !== undefined) {
|
|
160
|
+
parameters.taskConfiguration = patchTaskConfigurationModelConfig(taskConfiguration);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
parameters.taskConfiguration = { executionStrategies: [] };
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
id: String(id),
|
|
167
|
+
kind: TASK_NODE_KIND,
|
|
168
|
+
inputs: [{ id: 'in:record', direction: 'input', type: 'builtin:object', required: true }],
|
|
169
|
+
outputs: [{ id: 'out:answer', direction: 'output', type: 'builtin:object' }],
|
|
170
|
+
parameters,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function flatFinalizerNodeToAuthoring(node, incoming) {
|
|
174
|
+
const finalizerId = String(node.id);
|
|
175
|
+
const upstream = incoming.filter((e) => e.to === finalizerId);
|
|
176
|
+
const inputs = upstream.length > 0
|
|
177
|
+
? upstream.map((edge) => ({
|
|
178
|
+
id: `in:${edge.from}`,
|
|
179
|
+
direction: 'input',
|
|
180
|
+
type: 'builtin:object',
|
|
181
|
+
required: true,
|
|
182
|
+
}))
|
|
183
|
+
: [{ id: 'in:final', direction: 'input', type: 'builtin:object', required: false }];
|
|
184
|
+
const parameters = {
|
|
185
|
+
profile: FINALIZER_NODE_PROFILE,
|
|
186
|
+
nodeType: 'finalizer',
|
|
187
|
+
finalizerType: node.finalizerType,
|
|
188
|
+
config: isPlainRecord(node.config) ? node.config : {},
|
|
189
|
+
};
|
|
190
|
+
if (node.inputs !== undefined)
|
|
191
|
+
parameters.inputs = node.inputs;
|
|
192
|
+
if (node.outputMapping !== undefined)
|
|
193
|
+
parameters.outputMapping = node.outputMapping;
|
|
194
|
+
return {
|
|
195
|
+
id: finalizerId,
|
|
196
|
+
kind: FINALIZER_NODE_KIND,
|
|
197
|
+
inputs,
|
|
198
|
+
outputs: [{ id: 'out:final', direction: 'output', type: 'builtin:object' }],
|
|
199
|
+
parameters,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function flatEdgeToAuthoring(edge, index) {
|
|
203
|
+
const from = String(edge.from);
|
|
204
|
+
const to = String(edge.to);
|
|
205
|
+
return {
|
|
206
|
+
id: typeof edge.id === 'string' ? edge.id : `edge:${index}:${from}:${to}`,
|
|
207
|
+
from: { nodeId: from, portId: 'out:answer' },
|
|
208
|
+
to: { nodeId: to, portId: `in:${from === to ? 'final' : from}` },
|
|
209
|
+
...(edge.when != null ? { when: edge.when } : {}),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/** Converts legacy flat exellix test graphs into Graphenix 2.x {@link AuthoringGraphDocument}. */
|
|
213
|
+
export function flatTestGraphToAuthoringDocument(flat) {
|
|
214
|
+
const graphId = String(flat.id ?? 'test-graph');
|
|
215
|
+
const nodesRaw = Array.isArray(flat.nodes) ? flat.nodes : [];
|
|
216
|
+
const edgesRaw = Array.isArray(flat.edges) ? flat.edges : [];
|
|
217
|
+
const edgesTyped = edgesRaw.filter(isPlainRecord).map((e) => ({ from: String(e.from), to: String(e.to) }));
|
|
218
|
+
const nodes = nodesRaw.filter(isPlainRecord).map((node) => {
|
|
219
|
+
const type = String(node.type ?? 'task');
|
|
220
|
+
if (type === 'finalizer')
|
|
221
|
+
return flatFinalizerNodeToAuthoring(node, edgesTyped);
|
|
222
|
+
return flatTaskNodeToAuthoring(node);
|
|
223
|
+
});
|
|
224
|
+
const edges = edgesRaw.filter(isPlainRecord).map((edge, index) => flatEdgeToAuthoring(edge, index));
|
|
225
|
+
const flatResponse = isPlainRecord(flat.response) ? flat.response : {};
|
|
226
|
+
const responseShape = isPlainRecord(flatResponse) && isPlainRecord(flatResponse.shape)
|
|
227
|
+
? flatResponse.shape
|
|
228
|
+
: isPlainRecord(flatResponse)
|
|
229
|
+
? flatResponse
|
|
230
|
+
: {};
|
|
231
|
+
const metadata = isPlainRecord(flat.metadata) ? { ...flat.metadata } : {};
|
|
232
|
+
if (Array.isArray(flat.jobKnowledge))
|
|
233
|
+
metadata.jobKnowledge = normalizeKnowledgeRefs(flat.jobKnowledge);
|
|
234
|
+
if (Array.isArray(flat.taskKnowledge))
|
|
235
|
+
metadata.taskKnowledge = normalizeKnowledgeRefs(flat.taskKnowledge);
|
|
236
|
+
const executableProfile = {
|
|
237
|
+
profileVersion: EXECUTABLE_PROFILE_VERSION,
|
|
238
|
+
modelConfig: flatModelConfigToAuthoring(flat.modelConfig) ?? defaultExecutableModelConfig(),
|
|
239
|
+
};
|
|
240
|
+
metadata.graphResponse = {
|
|
241
|
+
...(flatResponse.missing != null ? { missing: flatResponse.missing } : {}),
|
|
242
|
+
...(flatResponse.version != null ? { version: flatResponse.version } : {}),
|
|
243
|
+
shape: responseShape,
|
|
244
|
+
};
|
|
245
|
+
metadata.extensions = {
|
|
246
|
+
...(isPlainRecord(metadata.extensions) ? metadata.extensions : {}),
|
|
247
|
+
[EXECUTABLE_PROFILE_NAMESPACE]: executableProfile,
|
|
248
|
+
};
|
|
249
|
+
const taskNodes = nodes.filter((n) => n.kind === TASK_NODE_KIND);
|
|
250
|
+
const finalizer = nodes.find((n) => n.kind === FINALIZER_NODE_KIND);
|
|
251
|
+
return {
|
|
252
|
+
formatVersion: GRAPHENIX_FORMAT_VERSION,
|
|
253
|
+
id: graphId.startsWith('graph:') ? graphId : `graph:${graphId}`,
|
|
254
|
+
revision: typeof flat.version === 'string' ? flat.version : '1.0.0',
|
|
255
|
+
name: graphId,
|
|
256
|
+
graph: {
|
|
257
|
+
nodes: nodes,
|
|
258
|
+
edges,
|
|
259
|
+
inputs: taskNodes.map((node) => ({
|
|
260
|
+
id: `graph-input:${node.id}`,
|
|
261
|
+
name: 'Input Record',
|
|
262
|
+
type: 'builtin:object',
|
|
263
|
+
target: { nodeId: node.id, portId: 'in:record' },
|
|
264
|
+
contract: { semanticKind: 'record', required: true, schema: { type: 'object' } },
|
|
265
|
+
})),
|
|
266
|
+
outputs: finalizer
|
|
267
|
+
? [
|
|
268
|
+
{
|
|
269
|
+
id: 'graph-output:final',
|
|
270
|
+
name: 'Final Output',
|
|
271
|
+
type: 'builtin:object',
|
|
272
|
+
source: { nodeId: finalizer.id, portId: 'out:final' },
|
|
273
|
+
contract: { semanticKind: 'final-output', required: true, schema: { type: 'object' } },
|
|
274
|
+
},
|
|
275
|
+
]
|
|
276
|
+
: [],
|
|
277
|
+
metadata,
|
|
278
|
+
},
|
|
279
|
+
types: [],
|
|
280
|
+
};
|
|
281
|
+
}
|
package/dist/testkit/index.d.ts
CHANGED
|
@@ -3,4 +3,7 @@ export { DepGraphEngineFactory } from './depGraphEngineFactory.js';
|
|
|
3
3
|
export { RealTasksClient } from './RealTasksClient.js';
|
|
4
4
|
export { createTestExellixGraphRuntime } from './testModelAliasRuntime.js';
|
|
5
5
|
export { buildExecuteGraphInput } from './buildExecuteGraphInput.js';
|
|
6
|
+
export { buildAiTaskAuthoringGraph, buildLocalSkillAuthoringGraph, buildGraphResponseMappingAuthoringGraph, withAuthoringGraphModelConfig, } from './authoringGraphFixtures.js';
|
|
7
|
+
export { flatTestGraphToAuthoringDocument, isAuthoringGraphDocument } from './flatGraphToAuthoring.js';
|
|
8
|
+
export { runTaskMainModelSelection, runTaskMainModelSlot, expectMainSkillModelKey, } from './runTaskNodePlanAssertions.js';
|
|
6
9
|
export { tryLoadExellixAiTasksRuntimeSubtree, loadExellixGraphRuntimeObjects, } from './exellixRuntimeObjects.js';
|
package/dist/testkit/index.js
CHANGED
|
@@ -3,4 +3,7 @@ export { DepGraphEngineFactory } from './depGraphEngineFactory.js';
|
|
|
3
3
|
export { RealTasksClient } from './RealTasksClient.js';
|
|
4
4
|
export { createTestExellixGraphRuntime } from './testModelAliasRuntime.js';
|
|
5
5
|
export { buildExecuteGraphInput } from './buildExecuteGraphInput.js';
|
|
6
|
+
export { buildAiTaskAuthoringGraph, buildLocalSkillAuthoringGraph, buildGraphResponseMappingAuthoringGraph, withAuthoringGraphModelConfig, } from './authoringGraphFixtures.js';
|
|
7
|
+
export { flatTestGraphToAuthoringDocument, isAuthoringGraphDocument } from './flatGraphToAuthoring.js';
|
|
8
|
+
export { runTaskMainModelSelection, runTaskMainModelSlot, expectMainSkillModelKey, } from './runTaskNodePlanAssertions.js';
|
|
6
9
|
export { tryLoadExellixAiTasksRuntimeSubtree, loadExellixGraphRuntimeObjects, } from './exellixRuntimeObjects.js';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Test helpers for ai-tasks ≥ 9 nodePlan wire shape. */
|
|
2
|
+
type ExecutionUnitLike = Record<string, unknown> & {
|
|
3
|
+
unitKind?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function runTaskMainModelSelection(req: {
|
|
6
|
+
nodePlan?: {
|
|
7
|
+
executionUnits?: ExecutionUnitLike[];
|
|
8
|
+
};
|
|
9
|
+
}): unknown;
|
|
10
|
+
export declare function runTaskMainModelSlot(req: {
|
|
11
|
+
nodePlan?: {
|
|
12
|
+
executionUnits?: ExecutionUnitLike[];
|
|
13
|
+
};
|
|
14
|
+
}): unknown;
|
|
15
|
+
export declare function runTaskModelSelectionTriplet(req: {
|
|
16
|
+
nodePlan?: {
|
|
17
|
+
executionUnits?: ExecutionUnitLike[];
|
|
18
|
+
};
|
|
19
|
+
}): {
|
|
20
|
+
preActionModel: string | undefined;
|
|
21
|
+
skillModel: string | undefined;
|
|
22
|
+
postActionModel: string | undefined;
|
|
23
|
+
} | undefined;
|
|
24
|
+
/** Assert helper: compiled plan exposes profileChoice on MAIN unit (skillModel slot). */
|
|
25
|
+
export declare function expectMainSkillModelKey(req: {
|
|
26
|
+
nodePlan?: {
|
|
27
|
+
executionUnits?: ExecutionUnitLike[];
|
|
28
|
+
};
|
|
29
|
+
}, key: string): {
|
|
30
|
+
modelSelection: unknown;
|
|
31
|
+
modelSlot: unknown;
|
|
32
|
+
key: string | undefined;
|
|
33
|
+
};
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Test helpers for ai-tasks ≥ 9 nodePlan wire shape. */
|
|
2
|
+
function mainSkillUnit(nodePlan) {
|
|
3
|
+
return nodePlan?.executionUnits?.find((u) => u.unitKind === 'mainSkill');
|
|
4
|
+
}
|
|
5
|
+
export function runTaskMainModelSelection(req) {
|
|
6
|
+
return mainSkillUnit(req.nodePlan)?.modelSelection;
|
|
7
|
+
}
|
|
8
|
+
export function runTaskMainModelSlot(req) {
|
|
9
|
+
return mainSkillUnit(req.nodePlan)?.modelSlot;
|
|
10
|
+
}
|
|
11
|
+
export function runTaskModelSelectionTriplet(req) {
|
|
12
|
+
const main = mainSkillUnit(req.nodePlan);
|
|
13
|
+
const selection = main?.modelSelection;
|
|
14
|
+
if (!selection || selection.kind !== 'profileChoice' || typeof selection.key !== 'string') {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const slot = typeof main?.modelSlot === 'string' ? main.modelSlot : 'skillModel';
|
|
18
|
+
return {
|
|
19
|
+
preActionModel: slot === 'preActionModel' ? selection.key : undefined,
|
|
20
|
+
skillModel: slot === 'skillModel' ? selection.key : undefined,
|
|
21
|
+
postActionModel: slot === 'postActionModel' ? selection.key : undefined,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Assert helper: compiled plan exposes profileChoice on MAIN unit (skillModel slot). */
|
|
25
|
+
export function expectMainSkillModelKey(req, key) {
|
|
26
|
+
const main = mainSkillUnit(req.nodePlan);
|
|
27
|
+
return {
|
|
28
|
+
modelSelection: main?.modelSelection,
|
|
29
|
+
modelSlot: main?.modelSlot,
|
|
30
|
+
key: main?.modelSelection?.key === key ? key : undefined,
|
|
31
|
+
};
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exellix/graph-engine",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Graph executor SDK",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -52,17 +52,19 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@exellix/ai-tasks": "^
|
|
55
|
+
"@exellix/ai-tasks": "^9.0.0",
|
|
56
56
|
"@x12i/activix": "8.5.0",
|
|
57
57
|
"@x12i/catalox": "5.1.3",
|
|
58
58
|
"@x12i/env": "4.0.1",
|
|
59
59
|
"@x12i/funcx": "4.4.4",
|
|
60
60
|
"@x12i/graphenix": "2.5.0",
|
|
61
|
-
"@x12i/graphenix-
|
|
62
|
-
"@x12i/graphenix-
|
|
61
|
+
"@x12i/graphenix-authoring-format": "^1.1.0",
|
|
62
|
+
"@x12i/graphenix-executable-contracts": "^1.1.0",
|
|
63
|
+
"@x12i/graphenix-executable-format": "^2.1.2",
|
|
64
|
+
"@x12i/graphenix-execute-envelope": "^1.1.0",
|
|
63
65
|
"@x12i/graphenix-format": "2.0.0",
|
|
64
|
-
"@x12i/graphenix-plan-
|
|
65
|
-
"@x12i/graphenix-plan-
|
|
66
|
+
"@x12i/graphenix-plan-compiler": "^1.1.0",
|
|
67
|
+
"@x12i/graphenix-plan-format": "^1.1.0",
|
|
66
68
|
"@x12i/graphenix-trace-format": "^1.0.0",
|
|
67
69
|
"@x12i/logxer": "^4.6.0",
|
|
68
70
|
"@x12i/memorix-descriptors": "1.6.0",
|
|
@@ -73,7 +75,6 @@
|
|
|
73
75
|
},
|
|
74
76
|
"devDependencies": {
|
|
75
77
|
"@types/node": "25.9.1",
|
|
76
|
-
"@x12i/graphenix-authoring-format": "^1.0.1",
|
|
77
78
|
"tsx": "4.22.3",
|
|
78
79
|
"typescript": "6.0.3"
|
|
79
80
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { CompileExecutablePlanV2Options, ExecutableGraphPlanV2 } from '@x12i/graphenix-executable-contracts';
|
|
2
|
-
import type { Graph, GraphModelObject } from '../types/refs.js';
|
|
3
|
-
import type { GraphRuntimeObject } from '../runtime/ExellixGraphRuntime.js';
|
|
4
|
-
export type CompileExellixExecutablePlanOptions = CompileExecutablePlanV2Options;
|
|
5
|
-
/**
|
|
6
|
-
* Host/test helper: exellix graph model + runtime → validated v2 executable plan.
|
|
7
|
-
*/
|
|
8
|
-
export declare function compileExellixExecutablePlan(model: Graph | GraphModelObject, runtime: GraphRuntimeObject, options?: CompileExellixExecutablePlanOptions): ExecutableGraphPlanV2;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { compileExecutablePlanV2 } from '@x12i/graphenix-plan-compiler';
|
|
2
|
-
import { validateExecutablePlan } from '@x12i/graphenix-plan-format';
|
|
3
|
-
import { migrateExellixGraphModelToAuthoring } from './migrateExellixGraphModelToAuthoring.js';
|
|
4
|
-
import { patchFinalizerPlansOnExecutablePlan } from './patchFinalizerPlans.js';
|
|
5
|
-
/**
|
|
6
|
-
* Host/test helper: exellix graph model + runtime → validated v2 executable plan.
|
|
7
|
-
*/
|
|
8
|
-
export function compileExellixExecutablePlan(model, runtime, options) {
|
|
9
|
-
const authoring = migrateExellixGraphModelToAuthoring(model);
|
|
10
|
-
const compiled = compileExecutablePlanV2(authoring, runtime, options);
|
|
11
|
-
const plan = patchFinalizerPlansOnExecutablePlan(compiled, runtime);
|
|
12
|
-
const validation = validateExecutablePlan(plan);
|
|
13
|
-
if (!validation.valid) {
|
|
14
|
-
const summary = validation.errors.map((e) => `${e.path}: ${e.message}`).join('; ');
|
|
15
|
-
throw new Error(`compileExellixExecutablePlan: invalid plan: ${summary}`);
|
|
16
|
-
}
|
|
17
|
-
return plan;
|
|
18
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type AuthoringGraphDocument } from '@x12i/graphenix-executable-contracts';
|
|
2
|
-
import type { Graph, GraphModelObject } from '../types/refs.js';
|
|
3
|
-
/**
|
|
4
|
-
* Converts exellix {@link GraphModelObject} to graphenix {@link AuthoringGraphDocument} for plan compilation.
|
|
5
|
-
*/
|
|
6
|
-
export declare function migrateExellixGraphModelToAuthoring(model: Graph | GraphModelObject): AuthoringGraphDocument;
|