@exellix/graph-engine 8.6.0 → 9.0.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 +21 -0
- package/README.md +2 -2
- package/dist/src/compile/compileExellixExecutablePlan.d.ts +4 -1
- package/dist/src/compile/compileExellixExecutablePlan.js +18 -0
- package/dist/src/contract/graphRunContract.d.ts +37 -0
- package/dist/src/contract/graphRunContract.js +127 -0
- package/dist/src/contract/persistencyDefaults.d.ts +2 -0
- package/dist/src/contract/persistencyDefaults.js +2 -0
- package/dist/src/index.d.ts +11 -2
- package/dist/src/index.js +8 -1
- package/dist/src/inspection/graphInspection.js +4 -0
- package/dist/src/inspection/types.d.ts +5 -0
- package/dist/src/integrations/activixExellixShared.js +2 -2
- package/dist/src/plan/embeddedGraphToExellixGraph.js +25 -8
- package/dist/src/runtime/ExellixGraphRuntime.d.ts +2 -2
- package/dist/src/runtime/ExellixGraphRuntime.js +52 -19
- package/dist/src/runtime/coerceStringArray.d.ts +5 -0
- package/dist/src/runtime/coerceStringArray.js +34 -0
- package/dist/src/runtime/executionMatrixHost.d.ts +2 -2
- package/dist/src/runtime/executionMatrixHost.js +2 -2
- package/dist/src/runtime/graphEngineLogMeta.js +2 -2
- package/dist/src/runtime/graphEngineLogxer.js +2 -2
- package/dist/src/runtime/graphResponseMapping.d.ts +11 -0
- package/dist/src/runtime/graphResponseMapping.js +61 -8
- package/dist/src/runtime/runtimeObjects.d.ts +5 -5
- package/dist/src/runtime/runtimeObjects.js +5 -5
- package/dist/src/runtime/validateCanonicalGraphDocument.js +26 -1
- package/dist/src/types/aiTaskProfile.d.ts +2 -2
- package/dist/src/types/aiTaskProfile.js +1 -1
- package/dist/src/types/refs.d.ts +13 -8
- package/dist/src/validation/authoringGraphResponse.d.ts +21 -0
- package/dist/src/validation/authoringGraphResponse.js +88 -0
- package/dist/src/validation/validateGraphResponseWiring.d.ts +26 -0
- package/dist/src/validation/validateGraphResponseWiring.js +233 -0
- package/dist/testkit/authoringGraphFixtures.js +4 -1
- package/dist/testkit/buildExecuteGraphInput.js +3 -1
- package/dist/testkit/flatGraphToAuthoring.js +5 -5
- package/docs/handoff/graphs-studio-graphenix-2.7.3.md +13 -13
- package/package.json +17 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 9.0.0 — Response contract & finalOutput (FR-GE / CR-GE pack)
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- **Single canonical response:** Executable mapping reads **`graph.response` only** (authoring: `graph.response`; flat model: root `response`). `metadata.graphResponse` is rejected as executable truth (`GRAPH_RESPONSE_LEGACY_SOURCE`).
|
|
8
|
+
- **`validateGraphResponseWiring`** runs on compile by default (`strictResponseValidation !== false`): path writers, flat map targets, legacy paths/shapes, empty shape + finalizer.
|
|
9
|
+
- **`GRAPH_RESPONSE_INCOMPLETE`** when non-empty `graph.response.shape` resolves empty on a completed run.
|
|
10
|
+
- **Legacy removed:** `inference.conceptSketch.*` execution paths, `subnetAnalysis` / top-level `taskSections` shape keys, `metadata.responsePreset.id === 'subnetAnalysis'`, task `outputMapping`.
|
|
11
|
+
- **`resolveGraphRunContract`** reads **`graph.response.persistency` only** (no `metadata.graphResponse.persistency` fallback).
|
|
12
|
+
- **`ExecuteGraphResult.execution`** is always present on graph runs.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **`coerce: 'stringArray'`** on response selectors; **`coerceStringArray`**, **`resolveGraphResponse`**, **`assessGraphResponseCompleteness`** exports.
|
|
17
|
+
- **`migrateLegacyGraphResponseToAuthoring`** (import-only).
|
|
18
|
+
- **`inspectGraph`**: `response.source === 'graph.response'`.
|
|
19
|
+
|
|
20
|
+
### Downstream
|
|
21
|
+
|
|
22
|
+
- **graphs-playground:** remove `normalizeQaAnswersArrayFinalOutput`, `normalizeTaskSectionsFinalOutput`, `coerceResponsePresetTaggedGraph`, `buildTaskSectionsFinalOutputFromAnswers`; add `coerce: 'stringArray'` in studio preset builders at save time.
|
|
23
|
+
|
|
3
24
|
## 8.6.0 — Graphenix 2.7.3 (no-legacy web + narrix pipeline)
|
|
4
25
|
|
|
5
26
|
### Breaking
|
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ npm install @exellix/graph-engine
|
|
|
55
55
|
|
|
56
56
|
**Upstream tasks SDK:** This package depends on **`@exellix/ai-tasks` ^8.6.8** and **`@x12i/funcx` 4.4.4** (see **`package.json`**). Graph-engine emits **`RunTaskRequest`** shapes that match the ai-tasks **8.x** closed schema (mandatory **`executionStrategies`**, three-slot **`modelConfig`**, **`xynthesized`**, optional **`smartInput`**, no legacy root mirrors). Pin compatible versions in your app lockfile. Optional CI improvement: fail or warn when the resolved ai-tasks major/minor drifts outside an allowlist (not enforced in-repo today).
|
|
57
57
|
|
|
58
|
-
### Execution matrix hosts (`@
|
|
58
|
+
### Execution matrix hosts (`@x12i/exellix-runtime`) — documentation only for the engine
|
|
59
59
|
|
|
60
60
|
Matrix **claim**, **rows**, and **retry policy** live outside this package. If your host wires **matrix → graph run**, see [.docs/execution-matrix-handoff.md](.docs/execution-matrix-handoff.md) for how **you** should inject `runtime.executeGraph`, compile **`GraphModelObject` → plan**, resolve **`metadata.graphEntry` per model**, seed **`runtime.executionMemory`**, and pass **`runtime.jobId`**. Helpers such as **`buildMatrixJobForGraphRun`** align **`id`** and **`job.jobId`** on the `job` object so you can call **`runtime.executeGraph({ plan, runtime: { jobId: job.jobId, job, … } })`**. Those exports are **optional helpers for callers**; they do **not** expand graph-engine’s role beyond **executing the single run** when invoked.
|
|
61
61
|
|
|
@@ -329,7 +329,7 @@ When **`taskConfiguration.aiTaskProfile.inputSynthesis`** is enabled, graph-engi
|
|
|
329
329
|
|
|
330
330
|
1. **Engine PRE/POST strategy utilities (ai-tasks only):** `taskConfiguration.aiTaskProfile.preStrategyKey` / `postStrategyKey` → extra **`runTask`** calls via **`@exellix/ai-tasks`** before/after MAIN; outputs stored at **`execution.xynthesis.pre`** / **`execution.xynthesis.post`** (historical slot names).
|
|
331
331
|
2. **`executionPipeline` inside ai-tasks:** e.g. PRE **`synthesized-context`** + MAIN direct — still **one** outbound MAIN `runTask` handled inside `@exellix/ai-tasks`.
|
|
332
|
-
3. **Narrix web scope inside ai-tasks:** when **`taskConfiguration.aiTaskProfile.webScoping.enabled`** is true, graph-engine forwards a `narrix` payload with `enableWebScope` / `webScopeQuestions`. The actual web fetch + skip rules run **inside `@exellix/ai-tasks`** (`@
|
|
332
|
+
3. **Narrix web scope inside ai-tasks:** when **`taskConfiguration.aiTaskProfile.webScoping.enabled`** is true, graph-engine forwards a `narrix` payload with `enableWebScope` / `webScopeQuestions`. The actual web fetch + skip rules run **inside `@exellix/ai-tasks`** (`@x12i/narrix-web-scoper`); graph-engine has **no local web phase** in 5.x.
|
|
333
333
|
|
|
334
334
|
`synthesize` finalizers are a fourth outbound task-call shape: the finalizer is still a graph model node, but its terminal utility `runTask` uses the same run identity, diagnostics, `llmCall`, and resolved model config as the rest of the graph run.
|
|
335
335
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { AuthoringGraphDocument, CompileExecutablePlanV2Options, ExecutableGraphPlanV2 } from '@x12i/graphenix-executable-contracts';
|
|
2
2
|
import type { GraphRuntimeObject } from '../runtime/ExellixGraphRuntime.js';
|
|
3
|
-
export type CompileExellixExecutablePlanOptions = CompileExecutablePlanV2Options
|
|
3
|
+
export type CompileExellixExecutablePlanOptions = CompileExecutablePlanV2Options & {
|
|
4
|
+
/** When true (default in 9.x), reject unsatisfiable graph.response wiring before returning a plan. */
|
|
5
|
+
strictResponseValidation?: boolean;
|
|
6
|
+
};
|
|
4
7
|
/**
|
|
5
8
|
* Host/test helper: canonical {@link AuthoringGraphDocument} + runtime → validated v2 executable plan.
|
|
6
9
|
* No legacy migration — graphs must already be Graphenix 2.x authoring shape.
|
|
@@ -3,6 +3,12 @@ import { compileExecutablePlanV2 } from '@x12i/graphenix-plan-compiler';
|
|
|
3
3
|
import { validateExecutablePlanV2 } from '@x12i/graphenix-plan-format';
|
|
4
4
|
import { resolveGraphEntryFromAuthoringDocument } from './authoringDocumentHelpers.js';
|
|
5
5
|
import { EXELLIX_STRUCTURED_DATA_FILTERS_V1 } from '../types/refs.js';
|
|
6
|
+
import { assertGraphResponseWiringOk, validateGraphResponseWiring, } from '../validation/validateGraphResponseWiring.js';
|
|
7
|
+
import { resolveAuthoringGraphResponse } from '../validation/authoringGraphResponse.js';
|
|
8
|
+
import { assertGraphResponseDefinition } from '../runtime/graphResponseMapping.js';
|
|
9
|
+
function isPlainRecord(v) {
|
|
10
|
+
return v != null && typeof v === 'object' && !Array.isArray(v);
|
|
11
|
+
}
|
|
6
12
|
function patchEntryGatesFromGraphEntryDataFilters(plan, doc) {
|
|
7
13
|
const graphEntry = resolveGraphEntryFromAuthoringDocument(doc);
|
|
8
14
|
const dataFilters = graphEntry?.dataFilters;
|
|
@@ -30,6 +36,14 @@ function patchEntryGatesFromGraphEntryDataFilters(plan, doc) {
|
|
|
30
36
|
* No legacy migration — graphs must already be Graphenix 2.x authoring shape.
|
|
31
37
|
*/
|
|
32
38
|
export function compileExellixExecutablePlan(doc, runtime, options) {
|
|
39
|
+
const strictResponseValidation = options?.strictResponseValidation !== false;
|
|
40
|
+
// Ensure canonical response is present on authoring graph before plan compile (FR-GE-001).
|
|
41
|
+
const resolvedResponse = resolveAuthoringGraphResponse(doc);
|
|
42
|
+
assertGraphResponseDefinition(resolvedResponse);
|
|
43
|
+
const graphRecord = doc.graph;
|
|
44
|
+
if (!isPlainRecord(graphRecord.response)) {
|
|
45
|
+
graphRecord.response = resolvedResponse;
|
|
46
|
+
}
|
|
33
47
|
const authoringValidation = validateAuthoringGraph(doc);
|
|
34
48
|
if (!authoringValidation.valid) {
|
|
35
49
|
const summary = authoringValidation.errors.map((e) => `${e.path}: ${e.message}`).join('; ');
|
|
@@ -41,5 +55,9 @@ export function compileExellixExecutablePlan(doc, runtime, options) {
|
|
|
41
55
|
const summary = planValidation.errors.map((e) => `${e.path}: ${e.message}`).join('; ');
|
|
42
56
|
throw new Error(`compileExellixExecutablePlan: invalid plan: ${summary}`);
|
|
43
57
|
}
|
|
58
|
+
if (strictResponseValidation) {
|
|
59
|
+
const planWiring = validateGraphResponseWiring(plan);
|
|
60
|
+
assertGraphResponseWiringOk(planWiring, { graphId: plan.source.graphId });
|
|
61
|
+
}
|
|
44
62
|
return plan;
|
|
45
63
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type GraphRunPersistencyLink = {
|
|
2
|
+
/** Relation descriptor key (result entity → source entity). */
|
|
3
|
+
relationKey?: string;
|
|
4
|
+
/** Dot-path on the new record where the source recordId/entityId FK is written. */
|
|
5
|
+
fkPath?: string;
|
|
6
|
+
type?: 'oneToOne' | 'oneToMany' | 'manyToOne' | 'manyToMany';
|
|
7
|
+
/** Content type the relation targets on the source (default: source job contentType). */
|
|
8
|
+
targetContentType?: string;
|
|
9
|
+
};
|
|
10
|
+
export type GraphRunPersistency = {
|
|
11
|
+
/** Target object type; default `same-as-input`. */
|
|
12
|
+
entityId: string | 'same-as-input';
|
|
13
|
+
/** Result collection content type; default {@link DEFAULT_GRAPH_RUN_PERSISTENCY_CONTENT_TYPE}. */
|
|
14
|
+
contentType: string;
|
|
15
|
+
/** When true (default), always insert a new result record with a new recordId. */
|
|
16
|
+
newRecord?: boolean;
|
|
17
|
+
/** Cross-object link intent; auto-derived when {@link entityId} differs from the job source. */
|
|
18
|
+
link?: GraphRunPersistencyLink;
|
|
19
|
+
};
|
|
20
|
+
export type GraphRunContract = {
|
|
21
|
+
graphId: string;
|
|
22
|
+
persistency: GraphRunPersistency | null;
|
|
23
|
+
graphVersion?: string;
|
|
24
|
+
};
|
|
25
|
+
/** Parse a work/job/graph persistency object (partial fields allowed). */
|
|
26
|
+
export declare function parseGraphRunPersistency(raw: unknown): GraphRunPersistency | null;
|
|
27
|
+
/** Work/job overrides win over graph defaults; partial overrides merge field-by-field. */
|
|
28
|
+
export declare function mergeGraphRunPersistency(base: GraphRunPersistency | null, override: GraphRunPersistency | null): GraphRunPersistency | null;
|
|
29
|
+
/** Apply a run/work/job persistency override onto a resolved graph contract. */
|
|
30
|
+
export declare function applyGraphRunContractOverride(contract: GraphRunContract, persistencyOverride: unknown): GraphRunContract;
|
|
31
|
+
/** Read graph document version from published graph JSON (`version` or `metadata.version`). */
|
|
32
|
+
export declare function readGraphDocumentVersion(graphDoc: unknown): string | undefined;
|
|
33
|
+
/** Resolve graph-run contract from published graph JSON (GRX-NOTE-001). */
|
|
34
|
+
export declare function resolveGraphRunContract(graphId: string, graphDoc: unknown): GraphRunContract;
|
|
35
|
+
export declare function loadGraphRunContracts(graphIds: string[], graphLoader: {
|
|
36
|
+
loadGraph(graphId: string): Promise<unknown>;
|
|
37
|
+
}): Promise<GraphRunContract[]>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { DEFAULT_GRAPH_RUN_PERSISTENCY_CONTENT_TYPE } from './persistencyDefaults.js';
|
|
2
|
+
const RELATION_TYPES = new Set(['oneToOne', 'oneToMany', 'manyToOne', 'manyToMany']);
|
|
3
|
+
function asRecord(value) {
|
|
4
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
5
|
+
return null;
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
function readLink(raw) {
|
|
9
|
+
const link = asRecord(raw);
|
|
10
|
+
if (!link)
|
|
11
|
+
return undefined;
|
|
12
|
+
const out = {};
|
|
13
|
+
if (typeof link.relationKey === 'string' && link.relationKey.length > 0) {
|
|
14
|
+
out.relationKey = link.relationKey;
|
|
15
|
+
}
|
|
16
|
+
if (typeof link.fkPath === 'string' && link.fkPath.length > 0) {
|
|
17
|
+
out.fkPath = link.fkPath;
|
|
18
|
+
}
|
|
19
|
+
if (typeof link.type === 'string' && RELATION_TYPES.has(link.type)) {
|
|
20
|
+
out.type = link.type;
|
|
21
|
+
}
|
|
22
|
+
if (typeof link.targetContentType === 'string' && link.targetContentType.length > 0) {
|
|
23
|
+
out.targetContentType = link.targetContentType;
|
|
24
|
+
}
|
|
25
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
26
|
+
}
|
|
27
|
+
function normalizePersistency(raw) {
|
|
28
|
+
const entityIdRaw = raw.entityId;
|
|
29
|
+
const entityId = entityIdRaw === 'same-as-input'
|
|
30
|
+
? 'same-as-input'
|
|
31
|
+
: typeof entityIdRaw === 'string' && entityIdRaw.length > 0
|
|
32
|
+
? entityIdRaw
|
|
33
|
+
: 'same-as-input';
|
|
34
|
+
const contentTypeRaw = raw.contentType;
|
|
35
|
+
const contentType = typeof contentTypeRaw === 'string' && contentTypeRaw.length > 0
|
|
36
|
+
? contentTypeRaw
|
|
37
|
+
: DEFAULT_GRAPH_RUN_PERSISTENCY_CONTENT_TYPE;
|
|
38
|
+
const newRecord = raw.newRecord === false ? false : true;
|
|
39
|
+
const link = readLink(raw.link);
|
|
40
|
+
return {
|
|
41
|
+
entityId,
|
|
42
|
+
contentType,
|
|
43
|
+
newRecord,
|
|
44
|
+
...(link ? { link } : {}),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Parse a work/job/graph persistency object (partial fields allowed). */
|
|
48
|
+
export function parseGraphRunPersistency(raw) {
|
|
49
|
+
const rec = asRecord(raw);
|
|
50
|
+
if (!rec)
|
|
51
|
+
return null;
|
|
52
|
+
return normalizePersistency(rec);
|
|
53
|
+
}
|
|
54
|
+
/** Work/job overrides win over graph defaults; partial overrides merge field-by-field. */
|
|
55
|
+
export function mergeGraphRunPersistency(base, override) {
|
|
56
|
+
if (!override)
|
|
57
|
+
return base;
|
|
58
|
+
if (!base)
|
|
59
|
+
return override;
|
|
60
|
+
return {
|
|
61
|
+
entityId: override.entityId,
|
|
62
|
+
contentType: override.contentType,
|
|
63
|
+
newRecord: override.newRecord !== undefined ? override.newRecord : base.newRecord,
|
|
64
|
+
link: override.link ? { ...base.link, ...override.link } : base.link,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function mergeRawPersistency(base, rawOverride) {
|
|
68
|
+
// Explicit null on a run/work/job disables result writeback (simulation).
|
|
69
|
+
if (rawOverride === null)
|
|
70
|
+
return null;
|
|
71
|
+
const overrideRec = asRecord(rawOverride);
|
|
72
|
+
if (!overrideRec)
|
|
73
|
+
return base;
|
|
74
|
+
const merged = {
|
|
75
|
+
...(base
|
|
76
|
+
? {
|
|
77
|
+
entityId: base.entityId,
|
|
78
|
+
contentType: base.contentType,
|
|
79
|
+
...(base.newRecord === false ? { newRecord: false } : {}),
|
|
80
|
+
...(base.link ? { link: { ...base.link } } : {}),
|
|
81
|
+
}
|
|
82
|
+
: {}),
|
|
83
|
+
...overrideRec,
|
|
84
|
+
};
|
|
85
|
+
const overrideLink = asRecord(overrideRec.link);
|
|
86
|
+
if (base?.link && overrideLink) {
|
|
87
|
+
merged.link = { ...base.link, ...overrideLink };
|
|
88
|
+
}
|
|
89
|
+
return normalizePersistency(merged);
|
|
90
|
+
}
|
|
91
|
+
/** Apply a run/work/job persistency override onto a resolved graph contract. */
|
|
92
|
+
export function applyGraphRunContractOverride(contract, persistencyOverride) {
|
|
93
|
+
return {
|
|
94
|
+
...contract,
|
|
95
|
+
persistency: mergeRawPersistency(contract.persistency, persistencyOverride),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function readPersistency(graph) {
|
|
99
|
+
const response = asRecord(graph.response);
|
|
100
|
+
const fromResponse = asRecord(response?.persistency);
|
|
101
|
+
if (fromResponse) {
|
|
102
|
+
return normalizePersistency(fromResponse);
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/** Read graph document version from published graph JSON (`version` or `metadata.version`). */
|
|
107
|
+
export function readGraphDocumentVersion(graphDoc) {
|
|
108
|
+
const graph = asRecord(graphDoc) ?? {};
|
|
109
|
+
const metadata = asRecord(graph.metadata);
|
|
110
|
+
if (typeof graph.version === 'string')
|
|
111
|
+
return graph.version;
|
|
112
|
+
if (typeof metadata?.version === 'string')
|
|
113
|
+
return metadata.version;
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
/** Resolve graph-run contract from published graph JSON (GRX-NOTE-001). */
|
|
117
|
+
export function resolveGraphRunContract(graphId, graphDoc) {
|
|
118
|
+
const graph = asRecord(graphDoc) ?? {};
|
|
119
|
+
return {
|
|
120
|
+
graphId,
|
|
121
|
+
persistency: readPersistency(graph),
|
|
122
|
+
graphVersion: readGraphDocumentVersion(graph),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
export async function loadGraphRunContracts(graphIds, graphLoader) {
|
|
126
|
+
return Promise.all(graphIds.map(async (graphId) => resolveGraphRunContract(graphId, await graphLoader.loadGraph(graphId))));
|
|
127
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type { HostExecuteGraphRunOptions, MainReadinessPolicy, ExecutionStepOpti
|
|
|
16
16
|
export type { AiTaskProfileMetadata, AiTaskProfileInputSynthesis, } from './types/aiTaskProfile.js';
|
|
17
17
|
export { hasWebScopeAuthoring } from './types/aiTaskProfile.js';
|
|
18
18
|
export type { ExecutionStrategyInvocation, ExecutionStrategyPhase, ExecutionStrategyWrapperKey, SmartInputConfig, TaskStrategyItemData, XynthesizedDestinationScope, XynthesizedMemory, XynthesizedOutputConfig, } from './types/aiTasksDerivedTypes.js';
|
|
19
|
-
export type { Graph, GraphModelObject, GraphAiModelConfig, PartialGraphAiModelConfig, GraphModelAliasConfig, GraphRuntimeNodeConfig, TaskNodeRuntimeObject, GraphDocumentMetadata, GraphEntryContract, GraphResponseDefinition, GraphResponseMissingBehavior, GraphResponseSelector, GraphResponseShape, GraphResponseContract, GraphResponseMapping, GraphResponseMappingMissingBehavior, GraphResponseMappingSelector, GraphResponseMappingTarget, GraphExecutionDefaults, GraphExecutionMode, GraphOutputMode, GraphFlowOutline, GraphCoreObjective, GraphNodesResponses, GraphNode, TaskNode, TaskNodeConditions, TaskNodeConditionWhen, TaskNodeJsonCondition, TaskNodeJsConditionFunction, TaskNodeAiCondition, TaskNodeConditionParameters, ModelConfigSelection, ModelConfigCase, TaskNodePureMetadata, TaskNodeExecutionPipelineStep, TaskOutputValidation, FinalizerNode, FinalizerInputBinding, OutputSchema, AggregateFinalizerConfig, BundleFinalizerConfig, SelectFinalizerConfig, SynthesizeFinalizerConfig, UtilityExecutionPolicy, Job, CatalogPlanningKind, CatalogRequestStatus, CatalogBinding, ScopedQuestionCatalogRequestEntry, DiscoveryDefinitionCatalogRequestEntry, DiscoveryDefinitionCatalogRequest, DiscoveryDefinitionPlanningFields, CatalogRequestEntry, StructuredDataFiltersV1, ConditionsDataFilters, } from './types/refs.js';
|
|
19
|
+
export type { Graph, GraphModelObject, GraphAiModelConfig, PartialGraphAiModelConfig, GraphModelAliasConfig, GraphRuntimeNodeConfig, TaskNodeRuntimeObject, GraphDocumentMetadata, GraphEntryContract, GraphResponseDefinition, GraphResponseMissingBehavior, GraphResponseSelector, GraphResponseCoercion, GraphResponseShape, GraphResponseContract, GraphResponseMapping, GraphResponseMappingMissingBehavior, GraphResponseMappingSelector, GraphResponseMappingTarget, GraphExecutionDefaults, GraphExecutionMode, GraphOutputMode, GraphFlowOutline, GraphCoreObjective, GraphNodesResponses, GraphNode, TaskNode, TaskNodeConditions, TaskNodeConditionWhen, TaskNodeJsonCondition, TaskNodeJsConditionFunction, TaskNodeAiCondition, TaskNodeConditionParameters, ModelConfigSelection, ModelConfigCase, TaskNodePureMetadata, TaskNodeExecutionPipelineStep, TaskOutputValidation, FinalizerNode, FinalizerInputBinding, OutputSchema, AggregateFinalizerConfig, BundleFinalizerConfig, SelectFinalizerConfig, SynthesizeFinalizerConfig, UtilityExecutionPolicy, Job, CatalogPlanningKind, CatalogRequestStatus, CatalogBinding, ScopedQuestionCatalogRequestEntry, DiscoveryDefinitionCatalogRequestEntry, DiscoveryDefinitionCatalogRequest, DiscoveryDefinitionPlanningFields, CatalogRequestEntry, StructuredDataFiltersV1, ConditionsDataFilters, } from './types/refs.js';
|
|
20
20
|
export { mergeGraphDocumentModel, EXELLIX_GRAPH_MODEL_VARIABLE_KEY, EXELLIX_STRUCTURED_DATA_FILTERS_V1, } from './types/refs.js';
|
|
21
21
|
export type { TaskNodeTaskConfiguration, TaskNodeScopedDataReaderPackSlot, } from './types/taskNodeConfiguration.js';
|
|
22
22
|
export { getTaskConfiguration } from './types/taskNodeConfiguration.js';
|
|
@@ -79,7 +79,7 @@ export type { BuildTaskNodeRunTaskRequestArgs, BuildTaskNodeRunTaskRequestResult
|
|
|
79
79
|
/** Re-exported from `@exellix/ai-tasks` — preflight validation without `runTask`. */
|
|
80
80
|
export { validateRunTaskConfig, validateRunTaskInvoke, analyzeExpectedRunTaskInput, checkExpectedInputAgainstRequest, collectSmartInputValidationIssues, buildRunTaskValidationContext, validateParsedOutput, listTokens, analyzeTemplateResolution, renderSmartInput, extractTokenNamesFromStrings, getSkillTokens, getSkillContent, } from '@exellix/ai-tasks';
|
|
81
81
|
export type { RunTaskValidationIssue, RunTaskValidationResult, RunTaskInvokeValidationResult, ExpectedRunTaskInputPath, AnalyzeExpectedRunTaskInputResult, ValidateRunTaskInvokeParams, RunTaskTemplateResolver, OutputValidationResult, } from '@exellix/ai-tasks';
|
|
82
|
-
export { buildExellixGraphRuntimeObjects, setRuntimeObjectsLastJobId, summarizeRuntimeObjectsForPlayground,
|
|
82
|
+
export { buildExellixGraphRuntimeObjects, setRuntimeObjectsLastJobId, summarizeRuntimeObjectsForPlayground, X12I_GRAPH_RUNTIME_PACKAGE_NAME, X12I_AI_TASKS_PACKAGE_NAME, } from './runtime/runtimeObjects.js';
|
|
83
83
|
export type { ActivixQueryableClient, LogxerQueryableClient, LogxerLogLine, PackageRuntimeObjects, RuntimeObjects, BuildExellixGraphRuntimeObjectsInput, RuntimeObjectsObservabilitySummary, } from './runtime/runtimeObjects.js';
|
|
84
84
|
export type { GetJobLogsInput, GetJobLogsResult, QueryableLogLine } from '@x12i/logxer';
|
|
85
85
|
export { assertCanonicalGraphDocument, assertCanonicalTaskNode, getCanonicalGraphDocumentViolations, CANONICAL_GRAPH_TOP_LEVEL_KEYS, } from './runtime/validateCanonicalGraphDocument.js';
|
|
@@ -95,6 +95,13 @@ export type { ExecutableGraphPlanV2, NodeExecutionPlan, ExecutionUnitPlanV2, } f
|
|
|
95
95
|
export type { AuthoringGraphDocument } from '@x12i/graphenix-executable-contracts';
|
|
96
96
|
export { compileExellixExecutablePlan } from './compile/compileExellixExecutablePlan.js';
|
|
97
97
|
export type { CompileExellixExecutablePlanOptions } from './compile/compileExellixExecutablePlan.js';
|
|
98
|
+
export { applyGraphResponseDefinition, resolveGraphResponse, assessGraphResponseCompleteness, GRAPH_RESPONSE_INCOMPLETE, } from './runtime/graphResponseMapping.js';
|
|
99
|
+
export type { GraphResponseMappingContext, GraphResponseMappingError } from './runtime/graphResponseMapping.js';
|
|
100
|
+
export { coerceStringArray } from './runtime/coerceStringArray.js';
|
|
101
|
+
export { validateGraphResponseWiring, assertGraphResponseWiringOk, RESPONSE_PATH_NO_WRITER, TASK_MAP_TARGET_INVALID, TASK_MAP_SOURCE_INVALID, RESPONSE_LEGACY_SHAPE_KEY, EXECUTION_MAPPING_LEGACY_PATH, RESPONSE_EMPTY_SHAPE, RESPONSE_LEGACY_PRESET_ID, RESPONSE_COERCE_STRING_ARRAY_ON_SCALAR, } from './validation/validateGraphResponseWiring.js';
|
|
102
|
+
export type { GraphResponseWiringIssue, GraphResponseWiringValidation, } from './validation/validateGraphResponseWiring.js';
|
|
103
|
+
export { detectAuthoringResponseSourceIssues, resolveAuthoringGraphResponse, migrateLegacyGraphResponseToAuthoring, GRAPH_RESPONSE_LEGACY_SOURCE, GRAPH_RESPONSE_DUAL_SOURCE, } from './validation/authoringGraphResponse.js';
|
|
104
|
+
export type { AuthoringResponseSourceIssue } from './validation/authoringGraphResponse.js';
|
|
98
105
|
export { buildGraphExecutionRequestFromStudioExecute as buildAuthoringStudioGraphExecutionRequest } from '@x12i/graphenix-execute-envelope';
|
|
99
106
|
export type { RunTaskRequest, RunTaskResponse, TasksClientLike, GraphLoader as RuntimeGraphLoader, ExecuteGraphInput, GraphExecutionRequest, GraphRuntimeObject, GraphKnowledgeResolver, GraphKnowledgeResolverContext, ExecuteGraphResult, ExellixGraphRuntimeOptions, } from './runtime/ExellixGraphRuntime.js';
|
|
100
107
|
export type { PlanStatus, GraphPlan, GraphEngine, GraphEngineFactory, } from './runtime/GraphEngine.js';
|
|
@@ -120,5 +127,7 @@ export type { CreatePlaygroundReporterOptions, PlaygroundDebugArtifact, Playgrou
|
|
|
120
127
|
export { getNodeScopingQuestion, getNodeMemoryShape, getNodeNarrixDiscovery, fetchNodeScopingData, inspectNode, resolveNodeSkillKey, getGraphNodes, getGraphCatalogs, inspectGraph, collectPredicatePaths, executionMemoryPathTail, executionMemoryTailsMatch, getNodeExecutionMemoryWriteTails, getNodeControlDependencies, getNodeSideEffects, inspectFinalizer, inspectNodeContract, inspectGraphContracts, EXELLIX_VIRTUAL_GRAPH_ENTRY_NODE_ID, EXELLIX_VIRTUAL_GRAPH_RESPONSE_NODE_ID, EXELLIX_VIRTUAL_BOUNDARY_NODE_METADATA_KEY, EXELLIX_VIRTUAL_BOUNDARY_EDGE_FLAG_KEY, getVirtualGraphEntryLayer, getVirtualGraphResponseLayer, materializeVirtualBoundaryDiagram, stripMaterializedVirtualBoundaryDiagram, validateCatalogPlanning, isCatalogBinding, isCatalogRequestEntry, inspectGraphModelSelection, } from './inspection/index.js';
|
|
121
128
|
export type { GraphModelSelectionInspection, NodeModelSelection, ModelSelectionSource, NodeScopingQuestion, NodeScopeSource, NodeScopeTarget, NodeScopingData, NodeMemoryShape, MemoryPath, NodeNarrixDiscovery, NodeInspection, GraphInspection, NodeIOEdge, GraphCatalogs, CatalogBindingSummary, CatalogPlanningValidationIssue, GraphVirtualIO, GraphVirtualIONode, GraphVirtualIOEdge, GraphVirtualIONodeRole, VirtualGraphEntryLayer, VirtualGraphResponseLayer, MaterializeVirtualBoundaryDiagramOptions, MaterializedVirtualBoundaryDiagram, MaterializedVirtualBoundaryDiagramMeta, InspectNodeContractOptions, LocalSkillKey, NodeExecutionType, FactProvenance, ProvenancedSection, NodeInputBindingEntry, ScopedDataDependency, NodeInputContract, ExecutionMemoryWriteSpec, NodeOutputContract, NodeSideEffects, ControlBranchEntry, NodeControlContract, NodeValidationContract, FinalizerContractInspection, NodeContractInspection, GraphContractsInspection, } from './inspection/index.js';
|
|
122
129
|
export type { NarrixPreProcessorConfig, NarrixModeKey, NarrixRunInput, NarrixScope, ResolvedNarrixWirePayload, LocalTaskHandler, LocalTaskContext, } from './types/narrix.js';
|
|
130
|
+
export { resolveGraphRunContract, loadGraphRunContracts, readGraphDocumentVersion, parseGraphRunPersistency, mergeGraphRunPersistency, applyGraphRunContractOverride, type GraphRunContract, type GraphRunPersistency, type GraphRunPersistencyLink, } from './contract/graphRunContract.js';
|
|
131
|
+
export { DEFAULT_GRAPH_RUN_PERSISTENCY_CONTENT_TYPE } from './contract/persistencyDefaults.js';
|
|
123
132
|
export { shutdownMemorixRuntime } from './runtime/localSkills/memorixRuntime.js';
|
|
124
133
|
export type { ScopedDataReaderConfig, ScopedDataReaderOutput, ScopedDataReaderPackOutput, ScopedAnswerAssemblerConfig, ScopedAnswerAssemblerOutput, ScopedAnswerWriterConfig, ScopedAnswerWriterOutput, } from './runtime/localSkills/index.js';
|
package/dist/src/index.js
CHANGED
|
@@ -60,7 +60,7 @@ export { runTaskResponseSucceeded } from './runtime/runTaskResponse.js';
|
|
|
60
60
|
export { buildTaskNodeRunTaskRequest, validateTaskNodeRunTaskConfig, validateTaskNodeRunTaskInvoke, } from './runtime/taskNodeRunTaskPreflight.js';
|
|
61
61
|
/** Re-exported from `@exellix/ai-tasks` — preflight validation without `runTask`. */
|
|
62
62
|
export { validateRunTaskConfig, validateRunTaskInvoke, analyzeExpectedRunTaskInput, checkExpectedInputAgainstRequest, collectSmartInputValidationIssues, buildRunTaskValidationContext, validateParsedOutput, listTokens, analyzeTemplateResolution, renderSmartInput, extractTokenNamesFromStrings, getSkillTokens, getSkillContent, } from '@exellix/ai-tasks';
|
|
63
|
-
export { buildExellixGraphRuntimeObjects, setRuntimeObjectsLastJobId, summarizeRuntimeObjectsForPlayground,
|
|
63
|
+
export { buildExellixGraphRuntimeObjects, setRuntimeObjectsLastJobId, summarizeRuntimeObjectsForPlayground, X12I_GRAPH_RUNTIME_PACKAGE_NAME, X12I_AI_TASKS_PACKAGE_NAME, } from './runtime/runtimeObjects.js';
|
|
64
64
|
export { assertCanonicalGraphDocument, assertCanonicalTaskNode, getCanonicalGraphDocumentViolations, CANONICAL_GRAPH_TOP_LEVEL_KEYS, } from './runtime/validateCanonicalGraphDocument.js';
|
|
65
65
|
export { assertCanonicalGraphRuntimeObject } from './runtime/validateCanonicalGraphRuntime.js';
|
|
66
66
|
export { GRAPH_ENTRY_STUDIO_ONLY_KEYS, GRAPH_METADATA_STUDIO_ONLY_KEYS, stripGraphModelStudioFields, primaryRuntimeInputFromStudioDocument, getGraphEntryStudioOnlyKeyViolations, getGraphMetadataStudioOnlyKeyViolations, } from './runtime/graphModelStudioSeparation.js';
|
|
@@ -69,6 +69,10 @@ export { computeGraphDocumentContentSha256, stableStringifyGraphDocument, } from
|
|
|
69
69
|
// New runtime with injection seam
|
|
70
70
|
export { createExellixGraphRuntime } from './runtime/ExellixGraphRuntime.js';
|
|
71
71
|
export { compileExellixExecutablePlan } from './compile/compileExellixExecutablePlan.js';
|
|
72
|
+
export { applyGraphResponseDefinition, resolveGraphResponse, assessGraphResponseCompleteness, GRAPH_RESPONSE_INCOMPLETE, } from './runtime/graphResponseMapping.js';
|
|
73
|
+
export { coerceStringArray } from './runtime/coerceStringArray.js';
|
|
74
|
+
export { validateGraphResponseWiring, assertGraphResponseWiringOk, RESPONSE_PATH_NO_WRITER, TASK_MAP_TARGET_INVALID, TASK_MAP_SOURCE_INVALID, RESPONSE_LEGACY_SHAPE_KEY, EXECUTION_MAPPING_LEGACY_PATH, RESPONSE_EMPTY_SHAPE, RESPONSE_LEGACY_PRESET_ID, RESPONSE_COERCE_STRING_ARRAY_ON_SCALAR, } from './validation/validateGraphResponseWiring.js';
|
|
75
|
+
export { detectAuthoringResponseSourceIssues, resolveAuthoringGraphResponse, migrateLegacyGraphResponseToAuthoring, GRAPH_RESPONSE_LEGACY_SOURCE, GRAPH_RESPONSE_DUAL_SOURCE, } from './validation/authoringGraphResponse.js';
|
|
72
76
|
export { buildGraphExecutionRequestFromStudioExecute as buildAuthoringStudioGraphExecutionRequest } from '@x12i/graphenix-execute-envelope';
|
|
73
77
|
// Testkit (in-memory loader, dep engine, recording client — sample NARRIX tasks: `@exellix/graph-engine/testkit`)
|
|
74
78
|
export { InMemoryGraphLoader, DepGraphEngineFactory } from '../testkit/index.js';
|
|
@@ -88,5 +92,8 @@ export { composeEventEmitters } from './runtime/events.js';
|
|
|
88
92
|
export { createPlaygroundReporter } from './playground/index.js';
|
|
89
93
|
// Graph Inspection API
|
|
90
94
|
export { getNodeScopingQuestion, getNodeMemoryShape, getNodeNarrixDiscovery, fetchNodeScopingData, inspectNode, resolveNodeSkillKey, getGraphNodes, getGraphCatalogs, inspectGraph, collectPredicatePaths, executionMemoryPathTail, executionMemoryTailsMatch, getNodeExecutionMemoryWriteTails, getNodeControlDependencies, getNodeSideEffects, inspectFinalizer, inspectNodeContract, inspectGraphContracts, EXELLIX_VIRTUAL_GRAPH_ENTRY_NODE_ID, EXELLIX_VIRTUAL_GRAPH_RESPONSE_NODE_ID, EXELLIX_VIRTUAL_BOUNDARY_NODE_METADATA_KEY, EXELLIX_VIRTUAL_BOUNDARY_EDGE_FLAG_KEY, getVirtualGraphEntryLayer, getVirtualGraphResponseLayer, materializeVirtualBoundaryDiagram, stripMaterializedVirtualBoundaryDiagram, validateCatalogPlanning, isCatalogBinding, isCatalogRequestEntry, inspectGraphModelSelection, } from './inspection/index.js';
|
|
95
|
+
// Graph-run contract (GRX-NOTE-001) — persistency intent from published graph JSON
|
|
96
|
+
export { resolveGraphRunContract, loadGraphRunContracts, readGraphDocumentVersion, parseGraphRunPersistency, mergeGraphRunPersistency, applyGraphRunContractOverride, } from './contract/graphRunContract.js';
|
|
97
|
+
export { DEFAULT_GRAPH_RUN_PERSISTENCY_CONTENT_TYPE } from './contract/persistencyDefaults.js';
|
|
91
98
|
export { shutdownMemorixRuntime } from './runtime/localSkills/memorixRuntime.js';
|
|
92
99
|
// Web context rendering — consume execution.webContext → markdown for prompts (Layer 04)
|
|
@@ -264,6 +264,11 @@ export type GraphInspection = {
|
|
|
264
264
|
* Graph `metadata` (same shape as `variables.__graphModel` during execution).
|
|
265
265
|
*/
|
|
266
266
|
graphDocumentModel: GraphDocumentMetadata;
|
|
267
|
+
/** Executable response definition source — always `graph.response` in 9.x. */
|
|
268
|
+
response: {
|
|
269
|
+
source: 'graph.response';
|
|
270
|
+
definition: import('../types/refs.js').GraphResponseDefinition;
|
|
271
|
+
};
|
|
267
272
|
/**
|
|
268
273
|
* Virtual Layer 01 / 08 nodes and edges for visualization; not part of executable `nodes` / `edges`.
|
|
269
274
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { X12I_GRAPH_RUNTIME_PACKAGE_NAME } from '../runtime/runtimeObjects.js';
|
|
2
2
|
/** Recommended Mongo indexes for exellix-graph Activix streams (see `@x12i/activix` README). */
|
|
3
3
|
export const ACTIVIX_EXELLIX_RUN_CONTEXT_INDEXES = [
|
|
4
4
|
{ keys: { 'runContext.jobId': 1 } },
|
|
@@ -55,5 +55,5 @@ export function buildNodeActivixRunContext(args) {
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
export function activixExellixCollectionRegistryOwner() {
|
|
58
|
-
return { package:
|
|
58
|
+
return { package: X12I_GRAPH_RUNTIME_PACKAGE_NAME };
|
|
59
59
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getFinalizerNodeConfig, getTaskNodeConfig, isExecutableFinalizerNode, isExecutableTaskNode, } from '@x12i/graphenix-executable-contracts';
|
|
2
|
+
import { GRAPH_RESPONSE_LEGACY_SOURCE } from '../validation/authoringGraphResponse.js';
|
|
2
3
|
function isPlainRecord(v) {
|
|
3
4
|
return v != null && typeof v === 'object' && !Array.isArray(v);
|
|
4
5
|
}
|
|
@@ -82,24 +83,40 @@ function edgesFromPlan(plan) {
|
|
|
82
83
|
});
|
|
83
84
|
}
|
|
84
85
|
function responseFromEmbedded(doc, plan) {
|
|
85
|
-
const
|
|
86
|
-
|
|
86
|
+
const graphRecord = doc.graph;
|
|
87
|
+
const graphLevel = graphRecord.response;
|
|
88
|
+
if (isPlainRecord(graphLevel) && 'shape' in graphLevel) {
|
|
87
89
|
const out = {
|
|
88
|
-
shape: isPlainRecord(
|
|
90
|
+
shape: isPlainRecord(graphLevel.shape) || Array.isArray(graphLevel.shape)
|
|
91
|
+
? structuredClone(graphLevel.shape)
|
|
92
|
+
: graphLevel.shape ?? {},
|
|
89
93
|
};
|
|
90
|
-
if (
|
|
91
|
-
out.missing =
|
|
92
|
-
}
|
|
93
|
-
if (metaResponse.version !== undefined) {
|
|
94
|
-
out.version = metaResponse.version;
|
|
94
|
+
if (graphLevel.missing !== undefined) {
|
|
95
|
+
out.missing = graphLevel.missing;
|
|
95
96
|
}
|
|
96
97
|
return out;
|
|
97
98
|
}
|
|
99
|
+
const metaResponse = doc.graph.metadata?.graphResponse;
|
|
100
|
+
if (isPlainRecord(metaResponse) && hasExecutableMetadataResponse(metaResponse)) {
|
|
101
|
+
const err = new Error('Executable response mapping exists only under metadata.graphResponse. Move shape to graph.response — studio metadata is UI-only and is not read at compile or execute.');
|
|
102
|
+
err.code = GRAPH_RESPONSE_LEGACY_SOURCE;
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
98
105
|
if (isPlainRecord(plan.contracts?.response?.finalOutputSchema)) {
|
|
99
106
|
return { shape: { type: 'literal', value: {} } };
|
|
100
107
|
}
|
|
101
108
|
return { shape: {} };
|
|
102
109
|
}
|
|
110
|
+
function hasExecutableMetadataResponse(metaResponse) {
|
|
111
|
+
const shape = metaResponse.shape;
|
|
112
|
+
if (shape === undefined)
|
|
113
|
+
return false;
|
|
114
|
+
if (isPlainRecord(shape))
|
|
115
|
+
return Object.keys(shape).length > 0;
|
|
116
|
+
if (Array.isArray(shape))
|
|
117
|
+
return shape.length > 0;
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
103
120
|
/** Materialize exellix {@link Graph} from plan embedded normalized authoring graph. */
|
|
104
121
|
export function embeddedGraphToExellixGraph(plan) {
|
|
105
122
|
if (plan.normalizedGraph.mode !== 'embedded') {
|
|
@@ -100,8 +100,8 @@ export interface ExecuteGraphResult {
|
|
|
100
100
|
nodeId?: string;
|
|
101
101
|
error: any;
|
|
102
102
|
}>;
|
|
103
|
-
/** Final execution object (includes `_trace.nodes` for per-node timing). */
|
|
104
|
-
execution
|
|
103
|
+
/** Final execution object (includes `_trace.nodes` for per-node timing). Always present on graph runs (FR-GE-005). */
|
|
104
|
+
execution: Record<string, unknown>;
|
|
105
105
|
/** Final graph-engine-owned output memory accumulated from finalizer `outputMapping` writes. */
|
|
106
106
|
outputsMemory?: unknown;
|
|
107
107
|
runLog?: RunLogEntry[];
|
|
@@ -19,7 +19,7 @@ import { assertFinalizerRequiredReadsResolvable, validateGraphFinalizer, } from
|
|
|
19
19
|
import { executeDeterministicFinalizer, executeSynthesizeFinalizer } from "./finalizers/executeFinalizer.js";
|
|
20
20
|
import { createFinalizerError } from "./finalizers/errors.js";
|
|
21
21
|
import { assertCanonicalGraphRuntimeObject } from "./validateCanonicalGraphRuntime.js";
|
|
22
|
-
import { applyGraphResponseDefinition } from "./graphResponseMapping.js";
|
|
22
|
+
import { applyGraphResponseDefinition, assessGraphResponseCompleteness, GRAPH_RESPONSE_INCOMPLETE } from "./graphResponseMapping.js";
|
|
23
23
|
import { buildAiTasksObservabilityRecord } from "./aiTasksObservability.js";
|
|
24
24
|
import { buildRunTaskIdentityEnvelope, shouldForwardRunTaskTraceMode, } from "./runTaskAugments.js";
|
|
25
25
|
import { buildRunLog, extractLogxerCorrelationFromMetadata, extractTaskRunLogFromMetadata, resolveRunLogLimits, } from "./buildRunLog.js";
|
|
@@ -1172,7 +1172,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1172
1172
|
logxerCorrelationId: logxerCorrelationIdLast,
|
|
1173
1173
|
});
|
|
1174
1174
|
return {
|
|
1175
|
-
execution: currentExecution,
|
|
1175
|
+
execution: (isPlainRecord(currentExecution) ? currentExecution : {}),
|
|
1176
1176
|
outputsMemory: currentOutputsMemory,
|
|
1177
1177
|
...built,
|
|
1178
1178
|
};
|
|
@@ -1256,7 +1256,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1256
1256
|
const executionMemoryForResponse = isPlainRecord(currentExecution)
|
|
1257
1257
|
? structuredClone(currentExecution)
|
|
1258
1258
|
: currentExecution;
|
|
1259
|
-
|
|
1259
|
+
const finalOutput = applyGraphResponseDefinition({
|
|
1260
1260
|
response: graph.response,
|
|
1261
1261
|
context: {
|
|
1262
1262
|
graph,
|
|
@@ -1268,6 +1268,38 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1268
1268
|
stepsResponses,
|
|
1269
1269
|
},
|
|
1270
1270
|
});
|
|
1271
|
+
const completeness = assessGraphResponseCompleteness(graph.response, finalOutput);
|
|
1272
|
+
if (completeness.incomplete) {
|
|
1273
|
+
return {
|
|
1274
|
+
responseErrors: [
|
|
1275
|
+
{
|
|
1276
|
+
code: completeness.code ?? GRAPH_RESPONSE_INCOMPLETE,
|
|
1277
|
+
message: completeness.message ?? 'graph.response resolved empty.',
|
|
1278
|
+
},
|
|
1279
|
+
],
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
return finalOutput !== undefined ? { finalOutput } : {};
|
|
1283
|
+
}
|
|
1284
|
+
function resolveGraphRunFinalOutput(baseErrors = errors) {
|
|
1285
|
+
const resolved = buildFinalOutputFromGraphResponse();
|
|
1286
|
+
if (resolved.responseErrors?.length) {
|
|
1287
|
+
return {
|
|
1288
|
+
errors: [
|
|
1289
|
+
...baseErrors,
|
|
1290
|
+
...resolved.responseErrors.map((re) => {
|
|
1291
|
+
const e = new Error(re.message);
|
|
1292
|
+
e.code = re.code;
|
|
1293
|
+
return { error: e };
|
|
1294
|
+
}),
|
|
1295
|
+
],
|
|
1296
|
+
responseFailed: true,
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
return {
|
|
1300
|
+
finalOutput: resolved.finalOutput,
|
|
1301
|
+
errors: baseErrors,
|
|
1302
|
+
};
|
|
1271
1303
|
}
|
|
1272
1304
|
const playgroundReporter = runtime.playgroundReporter ?? opts.playgroundReporter;
|
|
1273
1305
|
if (playgroundReporter) {
|
|
@@ -1314,7 +1346,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1314
1346
|
taskId: graphTaskId,
|
|
1315
1347
|
error: err,
|
|
1316
1348
|
});
|
|
1317
|
-
const
|
|
1349
|
+
const responseResolution = resolveGraphRunFinalOutput([...errors, { error: err }]);
|
|
1318
1350
|
appendExecutionEvent(executionTrace, {
|
|
1319
1351
|
id: `evt:${graphTaskId}:graph.failed`,
|
|
1320
1352
|
ts: new Date().toISOString(),
|
|
@@ -1330,8 +1362,8 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1330
1362
|
outputsByNodeId,
|
|
1331
1363
|
stepsResponses,
|
|
1332
1364
|
engineSnapshot: engine.snapshot(),
|
|
1333
|
-
...(finalOutput !== undefined ? { finalOutput } : {}),
|
|
1334
|
-
errors:
|
|
1365
|
+
...(responseResolution.finalOutput !== undefined ? { finalOutput: responseResolution.finalOutput } : {}),
|
|
1366
|
+
errors: responseResolution.errors,
|
|
1335
1367
|
planAudit,
|
|
1336
1368
|
trace: executionTrace,
|
|
1337
1369
|
...finalizeGraphPayload("failed"),
|
|
@@ -1350,8 +1382,8 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1350
1382
|
while (true) {
|
|
1351
1383
|
const wavePlan = engine.plan();
|
|
1352
1384
|
if (wavePlan.status === "completed") {
|
|
1353
|
-
const
|
|
1354
|
-
const
|
|
1385
|
+
const responseResolution = resolveGraphRunFinalOutput();
|
|
1386
|
+
const graphStatus = errors.length || responseResolution.responseFailed ? "failed" : "completed";
|
|
1355
1387
|
appendExecutionEvent(executionTrace, {
|
|
1356
1388
|
id: `evt:${graphTaskId}:graph.${graphStatus}`,
|
|
1357
1389
|
ts: new Date().toISOString(),
|
|
@@ -1360,6 +1392,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1360
1392
|
message: `Graph execution ${graphStatus}.`,
|
|
1361
1393
|
});
|
|
1362
1394
|
validateExecutionTrace(executionTrace, plan);
|
|
1395
|
+
const resultErrors = responseResolution.errors.length ? responseResolution.errors : undefined;
|
|
1363
1396
|
const result = {
|
|
1364
1397
|
jobId,
|
|
1365
1398
|
taskId: graphTaskId,
|
|
@@ -1368,9 +1401,9 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1368
1401
|
outputsByNodeId,
|
|
1369
1402
|
stepsResponses,
|
|
1370
1403
|
engineSnapshot: engine.snapshot(),
|
|
1371
|
-
...(finalOutput !== undefined ? { finalOutput } : {}),
|
|
1372
|
-
...(
|
|
1373
|
-
errors:
|
|
1404
|
+
...(responseResolution.finalOutput !== undefined ? { finalOutput: responseResolution.finalOutput } : {}),
|
|
1405
|
+
...(graphStatus === "completed" ? { finalizerNodeId, finalizerType: finalizer.finalizerType } : {}),
|
|
1406
|
+
errors: resultErrors,
|
|
1374
1407
|
planAudit,
|
|
1375
1408
|
trace: executionTrace,
|
|
1376
1409
|
...finalizeGraphPayload(graphStatus),
|
|
@@ -1381,14 +1414,14 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1381
1414
|
if (eventEmitter) {
|
|
1382
1415
|
if (graphStatus === "completed") {
|
|
1383
1416
|
eventEmitter.emit(createGraphCompleteEvent(jobId, resolvedGraphId, graphTaskId, {
|
|
1384
|
-
output: finalOutput,
|
|
1417
|
+
output: responseResolution.finalOutput,
|
|
1385
1418
|
nodesExecuted: Object.keys(outputsByNodeId).length,
|
|
1386
1419
|
finalMemory: { jobMemory: currentJobMemory, taskMemory: currentTaskMemory, execution: currentExecution, outputsMemory: currentOutputsMemory },
|
|
1387
1420
|
...(jobCorrelation ?? {}),
|
|
1388
1421
|
}));
|
|
1389
1422
|
}
|
|
1390
1423
|
else {
|
|
1391
|
-
eventEmitter.emit(createGraphFailEvent(jobId, resolvedGraphId, graphTaskId, errors[0]?.error, {
|
|
1424
|
+
eventEmitter.emit(createGraphFailEvent(jobId, resolvedGraphId, graphTaskId, responseResolution.errors[0]?.error ?? errors[0]?.error, {
|
|
1392
1425
|
finalMemory: { jobMemory: currentJobMemory, taskMemory: currentTaskMemory, execution: currentExecution, outputsMemory: currentOutputsMemory },
|
|
1393
1426
|
...(jobCorrelation ?? {}),
|
|
1394
1427
|
}));
|
|
@@ -1399,7 +1432,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1399
1432
|
if (wavePlan.status !== "continue") {
|
|
1400
1433
|
const err = new Error(`GRAPH_BLOCKED: status=${wavePlan.status}`);
|
|
1401
1434
|
err.code = "GRAPH_BLOCKED";
|
|
1402
|
-
const
|
|
1435
|
+
const responseResolution = resolveGraphRunFinalOutput([...errors, { error: err }]);
|
|
1403
1436
|
const result = {
|
|
1404
1437
|
jobId,
|
|
1405
1438
|
taskId: graphTaskId,
|
|
@@ -1408,8 +1441,8 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1408
1441
|
outputsByNodeId,
|
|
1409
1442
|
stepsResponses,
|
|
1410
1443
|
engineSnapshot: engine.snapshot(),
|
|
1411
|
-
...(finalOutput !== undefined ? { finalOutput } : {}),
|
|
1412
|
-
errors:
|
|
1444
|
+
...(responseResolution.finalOutput !== undefined ? { finalOutput: responseResolution.finalOutput } : {}),
|
|
1445
|
+
errors: responseResolution.errors,
|
|
1413
1446
|
planAudit,
|
|
1414
1447
|
trace: executionTrace,
|
|
1415
1448
|
...finalizeGraphPayload("failed"),
|
|
@@ -1651,7 +1684,7 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1651
1684
|
throw e;
|
|
1652
1685
|
});
|
|
1653
1686
|
if (failFast && errors.length) {
|
|
1654
|
-
const
|
|
1687
|
+
const responseResolution = resolveGraphRunFinalOutput();
|
|
1655
1688
|
const result = {
|
|
1656
1689
|
jobId,
|
|
1657
1690
|
taskId: graphTaskId,
|
|
@@ -1660,8 +1693,8 @@ export function createExellixGraphRuntime(opts) {
|
|
|
1660
1693
|
outputsByNodeId,
|
|
1661
1694
|
stepsResponses,
|
|
1662
1695
|
engineSnapshot: engine.snapshot(),
|
|
1663
|
-
...(finalOutput !== undefined ? { finalOutput } : {}),
|
|
1664
|
-
errors,
|
|
1696
|
+
...(responseResolution.finalOutput !== undefined ? { finalOutput: responseResolution.finalOutput } : {}),
|
|
1697
|
+
errors: responseResolution.errors,
|
|
1665
1698
|
planAudit,
|
|
1666
1699
|
trace: executionTrace,
|
|
1667
1700
|
...finalizeGraphPayload("failed"),
|