ai-workflow-logic 0.1.9 → 0.2.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/package.json +6 -5
- package/src/agent-definition-selection.ts +766 -0
- package/src/agent-invocation.ts +2 -2
- package/src/agent-resources.ts +134 -29
- package/src/agent-state.ts +5 -5
- package/src/checkpoint-store.ts +3 -1
- package/src/filesystem.ts +22 -2
- package/src/index.ts +15 -0
- package/src/resource-resolution.ts +121 -0
- package/src/run-checkpoint.ts +225 -3
- package/src/run-freeze.ts +30 -15
package/src/run-checkpoint.ts
CHANGED
|
@@ -755,7 +755,10 @@ function normalizeAIDataRunGraph(value: unknown, runId: string, location: string
|
|
|
755
755
|
'id', 'tag', 'nodeType', 'generation', 'status', 'declarationIndex', 'inputs',
|
|
756
756
|
'outputs', 'config', 'dependsOn', 'dependents', 'reusePolicy',
|
|
757
757
|
],
|
|
758
|
-
[
|
|
758
|
+
[
|
|
759
|
+
'subflow', 'childInvocation', 'childFreezeReceipt', 'childTerminalReceipt',
|
|
760
|
+
'semanticFingerprint', 'result', 'invalidatedBy',
|
|
761
|
+
],
|
|
759
762
|
nodeLocation,
|
|
760
763
|
);
|
|
761
764
|
const storedId = canonicalIdentity(dataField(node, 'id', `${nodeLocation}.id`), `${nodeLocation}.id`);
|
|
@@ -778,6 +781,46 @@ function normalizeAIDataRunGraph(value: unknown, runId: string, location: string
|
|
|
778
781
|
normalizeAIDataInputs(dataField(node, 'inputs', `${nodeLocation}.inputs`), `${nodeLocation}.inputs`);
|
|
779
782
|
uniqueIdentityArray(dataField(node, 'outputs', `${nodeLocation}.outputs`), `${nodeLocation}.outputs`);
|
|
780
783
|
const config = plainRecord(dataField(node, 'config', `${nodeLocation}.config`), `${nodeLocation}.config`);
|
|
784
|
+
const tag = String(dataField(node, 'tag', `${nodeLocation}.tag`));
|
|
785
|
+
const hasSubflow = Object.prototype.hasOwnProperty.call(node, 'subflow');
|
|
786
|
+
if (tag === 'SubFlowNode' && !hasSubflow) {
|
|
787
|
+
invalid('AI_DATA_SUBFLOW_BINDING_MISSING', `${nodeLocation}.subflow`, 'SubFlowNode requires an exact durable child binding.');
|
|
788
|
+
}
|
|
789
|
+
if (tag !== 'SubFlowNode' && hasSubflow) {
|
|
790
|
+
invalid('AI_DATA_SUBFLOW_BINDING_INVALID', `${nodeLocation}.subflow`, 'Only SubFlowNode may carry a child binding.');
|
|
791
|
+
}
|
|
792
|
+
if (hasSubflow) normalizeAIDataSubflowBinding(dataField(node, 'subflow', `${nodeLocation}.subflow`), `${nodeLocation}.subflow`);
|
|
793
|
+
const hasChildInvocation = Object.prototype.hasOwnProperty.call(node, 'childInvocation');
|
|
794
|
+
const hasChildFreeze = Object.prototype.hasOwnProperty.call(node, 'childFreezeReceipt');
|
|
795
|
+
const hasChildTerminal = Object.prototype.hasOwnProperty.call(node, 'childTerminalReceipt');
|
|
796
|
+
if ((hasChildInvocation || hasChildFreeze || hasChildTerminal) && tag !== 'SubFlowNode') {
|
|
797
|
+
invalid('AI_DATA_CHILD_INVOCATION_NODE_INVALID', nodeLocation, 'Only SubFlowNode may carry child invocation facts.');
|
|
798
|
+
}
|
|
799
|
+
if ((hasChildFreeze || hasChildTerminal) && !hasChildInvocation) {
|
|
800
|
+
invalid('AI_DATA_CHILD_INVOCATION_IDENTITY_MISSING', nodeLocation, 'Child receipts require a reserved invocation identity.');
|
|
801
|
+
}
|
|
802
|
+
if (hasChildInvocation) {
|
|
803
|
+
const identity = normalizeAIDataChildInvocationIdentity(
|
|
804
|
+
dataField(node, 'childInvocation', `${nodeLocation}.childInvocation`),
|
|
805
|
+
graphRunId,
|
|
806
|
+
nodeId,
|
|
807
|
+
generation,
|
|
808
|
+
dataField(node, 'subflow', `${nodeLocation}.subflow`),
|
|
809
|
+
`${nodeLocation}.childInvocation`,
|
|
810
|
+
);
|
|
811
|
+
if (hasChildFreeze) normalizeAIDataChildFreezeReceipt(
|
|
812
|
+
dataField(node, 'childFreezeReceipt', `${nodeLocation}.childFreezeReceipt`),
|
|
813
|
+
identity,
|
|
814
|
+
`${nodeLocation}.childFreezeReceipt`,
|
|
815
|
+
);
|
|
816
|
+
if (hasChildTerminal) normalizeAIDataChildTerminalReceipt(
|
|
817
|
+
dataField(node, 'childTerminalReceipt', `${nodeLocation}.childTerminalReceipt`),
|
|
818
|
+
identity,
|
|
819
|
+
node,
|
|
820
|
+
String(status),
|
|
821
|
+
`${nodeLocation}.childTerminalReceipt`,
|
|
822
|
+
);
|
|
823
|
+
}
|
|
781
824
|
const dependsOn = uniqueIdentityArray(dataField(node, 'dependsOn', `${nodeLocation}.dependsOn`), `${nodeLocation}.dependsOn`);
|
|
782
825
|
const dependents = uniqueIdentityArray(dataField(node, 'dependents', `${nodeLocation}.dependents`), `${nodeLocation}.dependents`);
|
|
783
826
|
normalizeReusePolicy(
|
|
@@ -811,6 +854,17 @@ function normalizeAIDataRunGraph(value: unknown, runId: string, location: string
|
|
|
811
854
|
`${nodeLocation}.result`,
|
|
812
855
|
);
|
|
813
856
|
normalizeAIDataResultOutput(resultValue, node, String(status), bindingDefinition, `${nodeLocation}.result`);
|
|
857
|
+
if (hasChildTerminal) {
|
|
858
|
+
const childReceipt = plainRecord(
|
|
859
|
+
dataField(node, 'childTerminalReceipt', `${nodeLocation}.childTerminalReceipt`),
|
|
860
|
+
`${nodeLocation}.childTerminalReceipt`,
|
|
861
|
+
);
|
|
862
|
+
if (String(status) === 'Succeeded'
|
|
863
|
+
&& JSON.stringify(dataField(childReceipt, 'output', `${nodeLocation}.childTerminalReceipt.output`))
|
|
864
|
+
!== JSON.stringify(dataField(plainRecord(resultValue, `${nodeLocation}.result`), 'output', `${nodeLocation}.result.output`))) {
|
|
865
|
+
invalid('AI_DATA_CHILD_PARENT_OUTPUT_MISMATCH', `${nodeLocation}.result.output`, 'Parent result must equal the accepted child output.');
|
|
866
|
+
}
|
|
867
|
+
}
|
|
814
868
|
}
|
|
815
869
|
const invalidationFacts: string[] = [];
|
|
816
870
|
if (Object.prototype.hasOwnProperty.call(node, 'invalidatedBy')) {
|
|
@@ -988,12 +1042,176 @@ function normalizeInitialAIDataNodeProjection(
|
|
|
988
1042
|
? dataField(definitionNode, 'config', `${location}.bindingNode.config`)
|
|
989
1043
|
: {},
|
|
990
1044
|
dependsOn: eagerDefinitionDependencies(definition, definitionNode, nodeId, location),
|
|
1045
|
+
...(dataField(definitionNode, 'tag', `${location}.bindingNode.tag`) === 'SubFlowNode'
|
|
1046
|
+
? {
|
|
1047
|
+
subflow: {
|
|
1048
|
+
kind: 'declared',
|
|
1049
|
+
flowRef: dataField(definitionNode, 'flow', `${location}.bindingNode.flow`),
|
|
1050
|
+
},
|
|
1051
|
+
}
|
|
1052
|
+
: {}),
|
|
991
1053
|
};
|
|
992
1054
|
for (const field of ['tag', 'declarationIndex', 'inputs', 'outputs', 'config', 'dependsOn'] as const) {
|
|
993
1055
|
if (JSON.stringify(dataField(node, field, `${location}.${field}`)) !== JSON.stringify(projected[field])) {
|
|
994
1056
|
invalid('AI_DATA_NODE_PROJECTION_MISMATCH', `${location}.${field}`, `Initial run node ${field} differs from its binding projection.`);
|
|
995
1057
|
}
|
|
996
1058
|
}
|
|
1059
|
+
if (Object.prototype.hasOwnProperty.call(projected, 'subflow')
|
|
1060
|
+
&& JSON.stringify(dataField(node, 'subflow', `${location}.subflow`)) !== JSON.stringify(projected.subflow)) {
|
|
1061
|
+
invalid('AI_DATA_NODE_PROJECTION_MISMATCH', `${location}.subflow`, 'Initial run node subflow differs from its binding projection.');
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
function normalizeAIDataSubflowBinding(value: unknown, location: string): void {
|
|
1066
|
+
const binding = plainRecord(value, location);
|
|
1067
|
+
const kind = dataField(binding, 'kind', `${location}.kind`);
|
|
1068
|
+
if (kind === 'declared') {
|
|
1069
|
+
exactRecord(value, ['kind', 'flowRef'], [], location);
|
|
1070
|
+
} else if (kind === 'autonomous') {
|
|
1071
|
+
const autonomous = exactRecord(
|
|
1072
|
+
value,
|
|
1073
|
+
['kind', 'schemaVersion', 'capabilityId', 'catalogDigest', 'definitionRef', 'flowRef', 'contractDigest'],
|
|
1074
|
+
[],
|
|
1075
|
+
location,
|
|
1076
|
+
);
|
|
1077
|
+
if (dataField(autonomous, 'schemaVersion', `${location}.schemaVersion`) !== 'depa.ai-data-subflow-binding/v1') {
|
|
1078
|
+
invalid('AI_DATA_SUBFLOW_BINDING_VERSION_INVALID', `${location}.schemaVersion`, 'Unsupported autonomous child binding version.');
|
|
1079
|
+
}
|
|
1080
|
+
const definitionRef = canonicalIdentity(dataField(autonomous, 'definitionRef', `${location}.definitionRef`), `${location}.definitionRef`);
|
|
1081
|
+
if (!definitionRef.startsWith('resource://')) {
|
|
1082
|
+
invalid('AI_DATA_SUBFLOW_DEFINITION_REF_INVALID', `${location}.definitionRef`, 'Child definition must use resource:// identity.');
|
|
1083
|
+
}
|
|
1084
|
+
for (const field of ['capabilityId', 'catalogDigest', 'contractDigest'] as const) {
|
|
1085
|
+
canonicalIdentity(dataField(autonomous, field, `${location}.${field}`), `${location}.${field}`);
|
|
1086
|
+
}
|
|
1087
|
+
} else {
|
|
1088
|
+
invalid('AI_DATA_SUBFLOW_BINDING_KIND_INVALID', `${location}.kind`, 'Child binding kind must be declared or autonomous.');
|
|
1089
|
+
}
|
|
1090
|
+
const flowRef = canonicalIdentity(dataField(binding, 'flowRef', `${location}.flowRef`), `${location}.flowRef`);
|
|
1091
|
+
if (!flowRef.startsWith('eager-data-flow://')) {
|
|
1092
|
+
invalid('AI_DATA_SUBFLOW_FLOW_REF_INVALID', `${location}.flowRef`, 'Child flow must use eager-data-flow:// identity.');
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
interface NormalizedAIDataChildInvocationIdentity {
|
|
1097
|
+
readonly invocationKey: string;
|
|
1098
|
+
readonly childInstanceId: string;
|
|
1099
|
+
readonly childRunId: string;
|
|
1100
|
+
readonly definitionRef: string;
|
|
1101
|
+
readonly flowRef: string;
|
|
1102
|
+
readonly contractDigest: string;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
function normalizeAIDataChildInvocationIdentity(
|
|
1106
|
+
value: unknown,
|
|
1107
|
+
parentRunId: string,
|
|
1108
|
+
parentNodeId: string,
|
|
1109
|
+
parentGeneration: number,
|
|
1110
|
+
subflowValue: unknown,
|
|
1111
|
+
location: string,
|
|
1112
|
+
): NormalizedAIDataChildInvocationIdentity {
|
|
1113
|
+
const identity = exactRecord(value, [
|
|
1114
|
+
'schemaVersion', 'invocationKey', 'parentInstanceId', 'parentRunId', 'parentNodeId', 'parentGeneration',
|
|
1115
|
+
'childInstanceId', 'childRunId', 'subflow',
|
|
1116
|
+
], [], location);
|
|
1117
|
+
if (dataField(identity, 'schemaVersion', `${location}.schemaVersion`) !== 'depa.ai-data-child-invocation/v1') {
|
|
1118
|
+
invalid('AI_DATA_CHILD_INVOCATION_SCHEMA_INVALID', `${location}.schemaVersion`, 'Unsupported child invocation schema.');
|
|
1119
|
+
}
|
|
1120
|
+
canonicalIdentity(dataField(identity, 'parentInstanceId', `${location}.parentInstanceId`), `${location}.parentInstanceId`);
|
|
1121
|
+
if (canonicalIdentity(dataField(identity, 'parentRunId', `${location}.parentRunId`), `${location}.parentRunId`) !== parentRunId
|
|
1122
|
+
|| canonicalIdentity(dataField(identity, 'parentNodeId', `${location}.parentNodeId`), `${location}.parentNodeId`) !== parentNodeId
|
|
1123
|
+
|| nonNegativeSafeInteger(dataField(identity, 'parentGeneration', `${location}.parentGeneration`), `${location}.parentGeneration`) !== parentGeneration) {
|
|
1124
|
+
invalid('AI_DATA_CHILD_INVOCATION_PARENT_MISMATCH', location, 'Child invocation identity must bind the owning parent node generation.');
|
|
1125
|
+
}
|
|
1126
|
+
const subflow = dataField(identity, 'subflow', `${location}.subflow`);
|
|
1127
|
+
normalizeAIDataSubflowBinding(subflow, `${location}.subflow`);
|
|
1128
|
+
if (JSON.stringify(subflow) !== JSON.stringify(subflowValue)) {
|
|
1129
|
+
invalid('AI_DATA_CHILD_INVOCATION_SUBFLOW_MISMATCH', `${location}.subflow`, 'Child invocation must bind the exact node subflow.');
|
|
1130
|
+
}
|
|
1131
|
+
const normalizedSubflow = plainRecord(subflow, `${location}.subflow`);
|
|
1132
|
+
if (dataField(normalizedSubflow, 'kind', `${location}.subflow.kind`) !== 'autonomous') {
|
|
1133
|
+
invalid('AI_DATA_CHILD_INVOCATION_SUBFLOW_INVALID', `${location}.subflow`, 'Durable child invocation requires an autonomous subflow binding.');
|
|
1134
|
+
}
|
|
1135
|
+
return {
|
|
1136
|
+
invocationKey: canonicalIdentity(dataField(identity, 'invocationKey', `${location}.invocationKey`), `${location}.invocationKey`),
|
|
1137
|
+
childInstanceId: canonicalIdentity(dataField(identity, 'childInstanceId', `${location}.childInstanceId`), `${location}.childInstanceId`),
|
|
1138
|
+
childRunId: canonicalIdentity(dataField(identity, 'childRunId', `${location}.childRunId`), `${location}.childRunId`),
|
|
1139
|
+
definitionRef: canonicalIdentity(dataField(normalizedSubflow, 'definitionRef', `${location}.subflow.definitionRef`), `${location}.subflow.definitionRef`),
|
|
1140
|
+
flowRef: canonicalIdentity(dataField(normalizedSubflow, 'flowRef', `${location}.subflow.flowRef`), `${location}.subflow.flowRef`),
|
|
1141
|
+
contractDigest: canonicalIdentity(dataField(normalizedSubflow, 'contractDigest', `${location}.subflow.contractDigest`), `${location}.subflow.contractDigest`),
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
function assertAIDataChildReceiptIdentity(
|
|
1146
|
+
value: Record<string, unknown>,
|
|
1147
|
+
identity: NormalizedAIDataChildInvocationIdentity,
|
|
1148
|
+
location: string,
|
|
1149
|
+
): void {
|
|
1150
|
+
for (const [field, expected] of Object.entries(identity)) {
|
|
1151
|
+
if (field === 'definitionRef' || field === 'flowRef' || field === 'contractDigest'
|
|
1152
|
+
|| field === 'invocationKey' || field === 'childInstanceId' || field === 'childRunId') {
|
|
1153
|
+
if (canonicalIdentity(dataField(value, field, `${location}.${field}`), `${location}.${field}`) !== expected) {
|
|
1154
|
+
invalid('AI_DATA_CHILD_RECEIPT_IDENTITY_MISMATCH', `${location}.${field}`, 'Child receipt does not match the reserved invocation.');
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
function normalizeAIDataChildFreezeReceipt(
|
|
1161
|
+
value: unknown,
|
|
1162
|
+
identity: NormalizedAIDataChildInvocationIdentity,
|
|
1163
|
+
location: string,
|
|
1164
|
+
): void {
|
|
1165
|
+
const receipt = exactRecord(value, [
|
|
1166
|
+
'schemaVersion', 'invocationKey', 'childInstanceId', 'childRunId', 'definitionRef', 'flowRef',
|
|
1167
|
+
'contractDigest', 'definitionRevision', 'definitionDigest',
|
|
1168
|
+
], [], location);
|
|
1169
|
+
if (dataField(receipt, 'schemaVersion', `${location}.schemaVersion`) !== 'depa.ai-data-child-invocation/v1') {
|
|
1170
|
+
invalid('AI_DATA_CHILD_FREEZE_SCHEMA_INVALID', `${location}.schemaVersion`, 'Unsupported child freeze schema.');
|
|
1171
|
+
}
|
|
1172
|
+
assertAIDataChildReceiptIdentity(receipt, identity, location);
|
|
1173
|
+
canonicalIdentity(dataField(receipt, 'definitionRevision', `${location}.definitionRevision`), `${location}.definitionRevision`);
|
|
1174
|
+
canonicalIdentity(dataField(receipt, 'definitionDigest', `${location}.definitionDigest`), `${location}.definitionDigest`);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
function normalizeAIDataChildTerminalReceipt(
|
|
1178
|
+
value: unknown,
|
|
1179
|
+
identity: NormalizedAIDataChildInvocationIdentity,
|
|
1180
|
+
node: Record<string, unknown>,
|
|
1181
|
+
nodeStatus: string,
|
|
1182
|
+
location: string,
|
|
1183
|
+
): void {
|
|
1184
|
+
const base = plainRecord(value, location);
|
|
1185
|
+
const terminalStatus = dataField(base, 'status', `${location}.status`);
|
|
1186
|
+
const receipt = exactRecord(value, [
|
|
1187
|
+
'schemaVersion', 'invocationKey', 'childInstanceId', 'childRunId', 'definitionRef', 'flowRef',
|
|
1188
|
+
'contractDigest', 'status', 'receiptDigest',
|
|
1189
|
+
...(terminalStatus === 'Succeeded' ? ['output'] : ['failureCode', 'failureMessage']),
|
|
1190
|
+
], [], location);
|
|
1191
|
+
if (dataField(receipt, 'schemaVersion', `${location}.schemaVersion`) !== 'depa.ai-data-child-invocation/v1') {
|
|
1192
|
+
invalid('AI_DATA_CHILD_TERMINAL_SCHEMA_INVALID', `${location}.schemaVersion`, 'Unsupported child terminal schema.');
|
|
1193
|
+
}
|
|
1194
|
+
if (terminalStatus !== 'Succeeded' && terminalStatus !== 'Failed') {
|
|
1195
|
+
invalid('AI_DATA_CHILD_TERMINAL_STATUS_INVALID', `${location}.status`, 'Child terminal receipt must be Succeeded or Failed.');
|
|
1196
|
+
}
|
|
1197
|
+
if (terminalStatus !== nodeStatus) {
|
|
1198
|
+
invalid('AI_DATA_CHILD_TERMINAL_PARENT_STATUS_MISMATCH', `${location}.status`, 'Child terminal status must equal its parent node status.');
|
|
1199
|
+
}
|
|
1200
|
+
assertAIDataChildReceiptIdentity(receipt, identity, location);
|
|
1201
|
+
canonicalIdentity(dataField(receipt, 'receiptDigest', `${location}.receiptDigest`), `${location}.receiptDigest`);
|
|
1202
|
+
if (terminalStatus === 'Succeeded') {
|
|
1203
|
+
const output = plainRecord(dataField(receipt, 'output', `${location}.output`), `${location}.output`);
|
|
1204
|
+
const expected = [...identityArray(
|
|
1205
|
+
dataField(node, 'outputs', `${location}.nodeOutputs`),
|
|
1206
|
+
`${location}.nodeOutputs`,
|
|
1207
|
+
)].sort(compareCodeUnits);
|
|
1208
|
+
if (JSON.stringify(stringDataKeys(output, `${location}.output`).sort(compareCodeUnits)) !== JSON.stringify(expected)) {
|
|
1209
|
+
invalid('AI_DATA_CHILD_TERMINAL_OUTPUT_MISMATCH', `${location}.output`, 'Child output keys must equal the parent SubFlowNode ports.');
|
|
1210
|
+
}
|
|
1211
|
+
} else {
|
|
1212
|
+
canonicalIdentity(dataField(receipt, 'failureCode', `${location}.failureCode`), `${location}.failureCode`);
|
|
1213
|
+
canonicalIdentity(dataField(receipt, 'failureMessage', `${location}.failureMessage`), `${location}.failureMessage`);
|
|
1214
|
+
}
|
|
997
1215
|
}
|
|
998
1216
|
|
|
999
1217
|
function eagerDefinitionDependencies(
|
|
@@ -1321,7 +1539,7 @@ function normalizeAIDataPatchNodeSpec(value: unknown, location: string): string
|
|
|
1321
1539
|
const spec = exactRecord(
|
|
1322
1540
|
value,
|
|
1323
1541
|
['id'],
|
|
1324
|
-
['tag', 'nodeType', 'declarationIndex', 'inputs', 'outputs', 'config', 'dependsOn', 'reusePolicy'],
|
|
1542
|
+
['tag', 'nodeType', 'declarationIndex', 'inputs', 'outputs', 'config', 'subflow', 'dependsOn', 'reusePolicy'],
|
|
1325
1543
|
location,
|
|
1326
1544
|
);
|
|
1327
1545
|
const nodeId = canonicalIdentity(dataField(spec, 'id', `${location}.id`), `${location}.id`);
|
|
@@ -1333,7 +1551,7 @@ function normalizeAIDataPatchNodeChanges(value: unknown, location: string): void
|
|
|
1333
1551
|
const changes = exactRecord(
|
|
1334
1552
|
value,
|
|
1335
1553
|
[],
|
|
1336
|
-
['tag', 'nodeType', 'inputs', 'outputs', 'config', 'dependsOn', 'reusePolicy'],
|
|
1554
|
+
['tag', 'nodeType', 'inputs', 'outputs', 'config', 'subflow', 'dependsOn', 'reusePolicy'],
|
|
1337
1555
|
location,
|
|
1338
1556
|
);
|
|
1339
1557
|
normalizeAIDataPatchNodeFields(changes, location);
|
|
@@ -1349,6 +1567,10 @@ function normalizeAIDataPatchNodeFields(record: Record<string, unknown>, locatio
|
|
|
1349
1567
|
if (Object.prototype.hasOwnProperty.call(record, field)) uniqueIdentityArray(dataField(record, field, `${location}.${field}`), `${location}.${field}`);
|
|
1350
1568
|
}
|
|
1351
1569
|
if (Object.prototype.hasOwnProperty.call(record, 'config')) plainRecord(dataField(record, 'config', `${location}.config`), `${location}.config`);
|
|
1570
|
+
if (Object.prototype.hasOwnProperty.call(record, 'subflow')) {
|
|
1571
|
+
const value = dataField(record, 'subflow', `${location}.subflow`);
|
|
1572
|
+
if (value !== null) normalizeAIDataSubflowBinding(value, `${location}.subflow`);
|
|
1573
|
+
}
|
|
1352
1574
|
if (Object.prototype.hasOwnProperty.call(record, 'reusePolicy')) {
|
|
1353
1575
|
const reuse = exactRecord(dataField(record, 'reusePolicy', `${location}.reusePolicy`), ['policy', 'source', 'nodeType'], [], `${location}.reusePolicy`);
|
|
1354
1576
|
canonicalIdentity(dataField(reuse, 'nodeType', `${location}.reusePolicy.nodeType`), `${location}.reusePolicy.nodeType`);
|
package/src/run-freeze.ts
CHANGED
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
buildResourceDependencySnapshot,
|
|
19
19
|
composeLayeredResourceRegistry,
|
|
20
20
|
loadResourceTree,
|
|
21
|
-
resolveEffectiveResourceContentIdentities,
|
|
22
21
|
sha256Digest,
|
|
23
22
|
type EffectiveResourceRegistry,
|
|
24
23
|
type ResourceContentIdentity,
|
|
@@ -26,6 +25,10 @@ import {
|
|
|
26
25
|
} from 'halfcode-compiler.xnl/resource-core';
|
|
27
26
|
import { projectAIWorkflowAgentResources } from './agent-resources.js';
|
|
28
27
|
import { sourceRegistryForAIWorkflowAgentResourceProjection } from './agent-resource-brand.js';
|
|
28
|
+
import {
|
|
29
|
+
createResolvedAIWorkflowContentIdentityIndex,
|
|
30
|
+
resolveAIWorkflowResourceTree,
|
|
31
|
+
} from './resource-resolution.js';
|
|
29
32
|
|
|
30
33
|
export interface FreezeAIWorkflowRunResourcesInput {
|
|
31
34
|
readonly registry: EffectiveResourceRegistry;
|
|
@@ -39,14 +42,15 @@ export async function freezeAIWorkflowRunResourcesFromDirectory(
|
|
|
39
42
|
rootDir: string,
|
|
40
43
|
task: AIWorkflowAgentTaskRef,
|
|
41
44
|
): Promise<AIWorkflowRunResourceFreezeReceipt> {
|
|
42
|
-
const
|
|
45
|
+
const authoredTree = await loadResourceTree({ rootDir });
|
|
46
|
+
const tree = resolveAIWorkflowResourceTree(authoredTree);
|
|
43
47
|
const layers = [{ id: 'workspace', tree }] as const;
|
|
44
48
|
const registry = composeLayeredResourceRegistry({ layers });
|
|
45
49
|
return freezeAIWorkflowRunResources({
|
|
46
50
|
registry,
|
|
47
51
|
projection: projectAIWorkflowAgentResources(registry),
|
|
48
52
|
task,
|
|
49
|
-
contentIdentities:
|
|
53
|
+
contentIdentities: createResolvedAIWorkflowContentIdentityIndex(tree),
|
|
50
54
|
});
|
|
51
55
|
}
|
|
52
56
|
|
|
@@ -72,13 +76,14 @@ export async function freezeAIWorkflowHolonTaskTargetFromDirectory(
|
|
|
72
76
|
rootDir: string,
|
|
73
77
|
target: HolonTaskTarget,
|
|
74
78
|
): Promise<AIWorkflowHolonTaskTargetFreezeReceipt> {
|
|
75
|
-
const
|
|
79
|
+
const authoredTree = await loadResourceTree({ rootDir });
|
|
80
|
+
const tree = resolveAIWorkflowResourceTree(authoredTree);
|
|
76
81
|
const layers = [{ id: 'workspace', tree }] as const;
|
|
77
82
|
const registry = composeLayeredResourceRegistry({ layers });
|
|
78
83
|
return freezeAIWorkflowHolonTaskTarget({
|
|
79
84
|
registry,
|
|
80
85
|
target,
|
|
81
|
-
contentIdentities:
|
|
86
|
+
contentIdentities: createResolvedAIWorkflowContentIdentityIndex(tree),
|
|
82
87
|
});
|
|
83
88
|
}
|
|
84
89
|
|
|
@@ -329,16 +334,26 @@ function semanticResourceFingerprint(
|
|
|
329
334
|
},
|
|
330
335
|
agent: {
|
|
331
336
|
resourceId: agent.resource.resourceId,
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
337
|
+
messagePrefix: agent.messagePrefix.map((item) => item.type === 'message'
|
|
338
|
+
? {
|
|
339
|
+
type: item.type,
|
|
340
|
+
id: item.id,
|
|
341
|
+
role: item.role,
|
|
342
|
+
prompt: [item.prompt.kind, item.prompt.resource.resourceId],
|
|
343
|
+
schema: item.schema ? {
|
|
344
|
+
kind: item.schema.kind,
|
|
345
|
+
resourceId: item.schema.resource.resourceId,
|
|
346
|
+
value: item.schema.schema,
|
|
347
|
+
} : null,
|
|
348
|
+
}
|
|
349
|
+
: {
|
|
350
|
+
type: item.type,
|
|
351
|
+
id: item.id,
|
|
352
|
+
source: [item.source.kind, item.source.resource.resourceId],
|
|
353
|
+
}),
|
|
354
|
+
contextPipeline: agent.contextPipeline
|
|
355
|
+
? [agent.contextPipeline.kind, agent.contextPipeline.resource.resourceId]
|
|
356
|
+
: null,
|
|
342
357
|
inputSchema: agent.inputSchema ? {
|
|
343
358
|
kind: agent.inputSchema.kind,
|
|
344
359
|
resourceId: agent.inputSchema.resource.resourceId,
|