@toolproof-core/lib 1.0.24 → 1.0.25
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/dist/artifacts/artifacts.d.ts +21 -21
- package/dist/artifacts/artifacts.js +8 -8
- package/dist/artifacts/artifacts.js.map +1 -1
- package/dist/integrations/firebase/createStep.d.ts +6 -6
- package/dist/integrations/firebase/createStep.d.ts.map +1 -1
- package/dist/integrations/firebase/createStep.js +18 -18
- package/dist/integrations/firebase/createStep.js.map +1 -1
- package/dist/integrations/firebase/firebaseAdminHelpers.js +3 -3
- package/dist/integrations/firebase/firebaseAdminHelpers.js.map +1 -1
- package/dist/utils/bindInputRoleToResource.js +11 -11
- package/dist/utils/bindInputRoleToResource.js.map +1 -1
- package/dist/utils/creation/stepCreation.d.ts +16 -16
- package/dist/utils/creation/stepCreation.d.ts.map +1 -1
- package/dist/utils/creation/stepCreation.js +16 -16
- package/dist/utils/creation/stepCreation.js.map +1 -1
- package/dist/utils/extractData.d.ts +5 -5
- package/dist/utils/extractData.d.ts.map +1 -1
- package/dist/utils/extractData.js +28 -28
- package/dist/utils/extractData.js.map +1 -1
- package/dist/utils/parallelizeSteps.js +30 -30
- package/dist/utils/parallelizeSteps.js.map +1 -1
- package/dist/utils/resolveResourceChain.js +2 -2
- package/dist/utils/resolveResourceChain.js.map +1 -1
- package/package.json +2 -2
- package/src/artifacts/artifacts.ts +8 -8
- package/src/integrations/firebase/createStep.ts +25 -25
- package/src/integrations/firebase/firebaseAdminHelpers.ts +3 -3
- package/src/utils/bindInputRoleToResource.ts +11 -11
- package/src/utils/creation/stepCreation.ts +35 -35
- package/src/utils/extractData.ts +34 -34
- package/src/utils/parallelizeSteps.ts +32 -32
- package/src/utils/resolveResourceChain.ts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -4,9 +4,9 @@ import type {
|
|
|
4
4
|
CaseJson,
|
|
5
5
|
ForStepIdentityJson,
|
|
6
6
|
ForStepJson,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
ToolJson,
|
|
8
|
+
ToolStepIdentityJson,
|
|
9
|
+
ToolStepJson,
|
|
10
10
|
ResourceRoleIdentityJson,
|
|
11
11
|
WhileStepIdentityJson,
|
|
12
12
|
WhileStepJson,
|
|
@@ -17,19 +17,19 @@ export type LoopStepBuildIdentities =
|
|
|
17
17
|
| {
|
|
18
18
|
stepKind: typeof CONSTANTS.Enums.StepKind.for;
|
|
19
19
|
stepIdentity: ForStepIdentityJson;
|
|
20
|
-
whatIdentity:
|
|
21
|
-
whenIdentity:
|
|
20
|
+
whatIdentity: ToolStepIdentityJson;
|
|
21
|
+
whenIdentity: ToolStepIdentityJson;
|
|
22
22
|
}
|
|
23
23
|
| {
|
|
24
24
|
stepKind: typeof CONSTANTS.Enums.StepKind.while;
|
|
25
25
|
stepIdentity: WhileStepIdentityJson;
|
|
26
|
-
whatIdentity:
|
|
27
|
-
whenIdentity:
|
|
26
|
+
whatIdentity: ToolStepIdentityJson;
|
|
27
|
+
whenIdentity: ToolStepIdentityJson;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export type BranchCaseBuildIdentities = {
|
|
31
|
-
whatIdentity:
|
|
32
|
-
whenIdentity:
|
|
31
|
+
whatIdentity: ToolStepIdentityJson;
|
|
32
|
+
whenIdentity: ToolStepIdentityJson;
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
function assertNonEmpty<T>(arr: T[], msg: string): asserts arr is [T, ...T[]] {
|
|
@@ -38,32 +38,32 @@ function assertNonEmpty<T>(arr: T[], msg: string): asserts arr is [T, ...T[]] {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function getRoleBindingSpec(
|
|
41
|
+
function getRoleBindingSpec(tool: ToolJson): ToolStepJson['roleBindingSpec'] {
|
|
42
42
|
return {
|
|
43
|
-
inputBindings: Object.keys(
|
|
44
|
-
outputBindings: Object.keys(
|
|
43
|
+
inputBindings: Object.keys(tool.roleSpec.inputRoleValueByIdentity) as ResourceRoleIdentityJson[],
|
|
44
|
+
outputBindings: Object.keys(tool.roleSpec.outputRoleValueByIdentity) as ResourceRoleIdentityJson[],
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export function
|
|
49
|
-
|
|
50
|
-
identity:
|
|
51
|
-
):
|
|
48
|
+
export function buildToolStepFromTool(
|
|
49
|
+
tool: ToolJson,
|
|
50
|
+
identity: ToolStepIdentityJson,
|
|
51
|
+
): ToolStepJson {
|
|
52
52
|
return {
|
|
53
53
|
identity,
|
|
54
|
-
stepKind: CONSTANTS.Enums.StepKind.
|
|
55
|
-
|
|
56
|
-
roleBindingSpec: getRoleBindingSpec(
|
|
54
|
+
stepKind: CONSTANTS.Enums.StepKind.tool,
|
|
55
|
+
toolHandle: tool.identity,
|
|
56
|
+
roleBindingSpec: getRoleBindingSpec(tool),
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
export function
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
export function buildLoopStepFromToolPair(
|
|
61
|
+
whatTool: ToolJson,
|
|
62
|
+
whenTool: ToolJson,
|
|
63
63
|
identities: LoopStepBuildIdentities,
|
|
64
64
|
): ForStepJson | WhileStepJson {
|
|
65
|
-
const what =
|
|
66
|
-
const when =
|
|
65
|
+
const what = buildToolStepFromTool(whatTool, identities.whatIdentity);
|
|
66
|
+
const when = buildToolStepFromTool(whenTool, identities.whenIdentity);
|
|
67
67
|
|
|
68
68
|
if (identities.stepKind === CONSTANTS.Enums.StepKind.for) {
|
|
69
69
|
return {
|
|
@@ -80,28 +80,28 @@ export function buildLoopStepFromJobPair(
|
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
export function
|
|
84
|
-
cases: Array<{
|
|
83
|
+
export function buildBranchStepFromToolPairs(
|
|
84
|
+
cases: Array<{ whatTool: ToolJson; whenTool: ToolJson }>,
|
|
85
85
|
branchIdentity: BranchStepIdentityJson,
|
|
86
86
|
caseIdentities: BranchCaseBuildIdentities[],
|
|
87
87
|
): BranchStepJson {
|
|
88
88
|
if (cases.length !== caseIdentities.length) {
|
|
89
|
-
throw new Error('
|
|
89
|
+
throw new Error('buildBranchStepFromToolPairs requires one identity pair per case');
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
const resolved = cases.map(({
|
|
92
|
+
const resolved = cases.map(({ whatTool, whenTool }, index) => {
|
|
93
93
|
const identities = caseIdentities[index];
|
|
94
94
|
|
|
95
95
|
if (!identities) {
|
|
96
96
|
throw new Error(`Missing case identities for case index ${index}`);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
const what =
|
|
100
|
-
const when =
|
|
99
|
+
const what = buildToolStepFromTool(whatTool, identities.whatIdentity);
|
|
100
|
+
const when = buildToolStepFromTool(whenTool, identities.whenIdentity);
|
|
101
101
|
return { what, when } satisfies CaseJson;
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
assertNonEmpty(resolved, '
|
|
104
|
+
assertNonEmpty(resolved, 'buildBranchStepFromToolPairs requires at least one case');
|
|
105
105
|
|
|
106
106
|
return {
|
|
107
107
|
identity: branchIdentity,
|
|
@@ -114,8 +114,8 @@ export function cloneForStepWithIdentities(
|
|
|
114
114
|
forStep: ForStepJson,
|
|
115
115
|
identities: {
|
|
116
116
|
stepIdentity: ForStepIdentityJson;
|
|
117
|
-
whatIdentity:
|
|
118
|
-
whenIdentity:
|
|
117
|
+
whatIdentity: ToolStepIdentityJson;
|
|
118
|
+
whenIdentity: ToolStepIdentityJson;
|
|
119
119
|
},
|
|
120
120
|
): ForStepJson {
|
|
121
121
|
return {
|
|
@@ -138,8 +138,8 @@ export function cloneWhileStepWithIdentities(
|
|
|
138
138
|
whileStep: WhileStepJson,
|
|
139
139
|
identities: {
|
|
140
140
|
stepIdentity: WhileStepIdentityJson;
|
|
141
|
-
whatIdentity:
|
|
142
|
-
whenIdentity:
|
|
141
|
+
whatIdentity: ToolStepIdentityJson;
|
|
142
|
+
whenIdentity: ToolStepIdentityJson;
|
|
143
143
|
},
|
|
144
144
|
): WhileStepJson {
|
|
145
145
|
return {
|
package/src/utils/extractData.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
RawStrategyJson,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
ToolIdentityJson,
|
|
4
|
+
ToolJson,
|
|
5
|
+
ToolStepIdentityJson,
|
|
6
|
+
ToolStepJson,
|
|
7
7
|
StepJson,
|
|
8
8
|
ResourceRoleIdentityJson,
|
|
9
9
|
ResourceRoleJson,
|
|
@@ -14,44 +14,44 @@ import type {
|
|
|
14
14
|
import { CONSTANTS } from '../artifacts/artifacts.js';
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
export function
|
|
18
|
-
const
|
|
19
|
-
const ids = new Set<
|
|
20
|
-
for (const jStep of
|
|
21
|
-
ids.add(jStep.
|
|
17
|
+
export function extractToolHandlesFromRawStrategy(rawStrategy: RawStrategyJson): ToolIdentityJson[] {
|
|
18
|
+
const toolSteps = extractToolStepsFromRawStrategy(rawStrategy);
|
|
19
|
+
const ids = new Set<ToolIdentityJson>();
|
|
20
|
+
for (const jStep of toolSteps) {
|
|
21
|
+
ids.add(jStep.toolHandle);
|
|
22
22
|
}
|
|
23
23
|
return Array.from(ids);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export function
|
|
27
|
-
const
|
|
28
|
-
const seen = new Set<
|
|
26
|
+
export function extractToolStepsFromRawStrategy(rawStrategy: RawStrategyJson): ToolStepJson[] {
|
|
27
|
+
const toolSteps: ToolStepJson[] = [];
|
|
28
|
+
const seen = new Set<ToolStepIdentityJson>();
|
|
29
29
|
|
|
30
|
-
const
|
|
31
|
-
if (seen.has(
|
|
32
|
-
throw new Error(`Duplicate
|
|
30
|
+
const addToolStep = (toolStep: ToolStepJson) => {
|
|
31
|
+
if (seen.has(toolStep.identity)) {
|
|
32
|
+
throw new Error(`Duplicate tool step identity encountered: ${toolStep.identity}`);
|
|
33
33
|
}
|
|
34
|
-
seen.add(
|
|
35
|
-
|
|
34
|
+
seen.add(toolStep.identity);
|
|
35
|
+
toolSteps.push(toolStep);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
const visitStep = (step: StepJson) => {
|
|
39
39
|
switch (step.stepKind) {
|
|
40
|
-
case CONSTANTS.Enums.StepKind.
|
|
41
|
-
|
|
40
|
+
case CONSTANTS.Enums.StepKind.tool: {
|
|
41
|
+
addToolStep(step);
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
case CONSTANTS.Enums.StepKind.branch: {
|
|
45
45
|
for (const conditional of step.cases) {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
addToolStep(conditional.when);
|
|
47
|
+
addToolStep(conditional.what);
|
|
48
48
|
}
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
case CONSTANTS.Enums.StepKind.while:
|
|
52
52
|
case CONSTANTS.Enums.StepKind.for: {
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
addToolStep(step.case.when);
|
|
54
|
+
addToolStep(step.case.what);
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
57
|
default: {
|
|
@@ -65,25 +65,25 @@ export function extractJobStepsFromRawStrategy(rawStrategy: RawStrategyJson): Jo
|
|
|
65
65
|
visitStep(step);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
return
|
|
68
|
+
return toolSteps;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
export function extractRoleMapFromRawStrategy(rawStrategy: RawStrategyJson,
|
|
72
|
+
export function extractRoleMapFromRawStrategy(rawStrategy: RawStrategyJson, toolMap: Map<ToolIdentityJson, ToolJson>): Map<ResourceRoleIdentityJson, ResourceRoleJson> {
|
|
73
73
|
const roleMap = new Map<ResourceRoleIdentityJson, ResourceRoleJson>();
|
|
74
|
-
const
|
|
74
|
+
const toolHandles = extractToolHandlesFromRawStrategy(rawStrategy);
|
|
75
75
|
|
|
76
|
-
for (const
|
|
77
|
-
const
|
|
78
|
-
if (!
|
|
76
|
+
for (const toolHandle of toolHandles) {
|
|
77
|
+
const tool = toolMap.get(toolHandle);
|
|
78
|
+
if (!tool) continue;
|
|
79
79
|
|
|
80
|
-
for (const [rid, role] of Object.entries(
|
|
80
|
+
for (const [rid, role] of Object.entries(tool.roleSpec.inputRoleValueByIdentity)) {
|
|
81
81
|
roleMap.set(rid as ResourceRoleIdentityJson, {
|
|
82
82
|
identity: rid as ResourceRoleIdentityJson,
|
|
83
83
|
...role,
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
|
-
for (const [rid, role] of Object.entries(
|
|
86
|
+
for (const [rid, role] of Object.entries(tool.roleSpec.outputRoleValueByIdentity)) {
|
|
87
87
|
roleMap.set(rid as ResourceRoleIdentityJson, {
|
|
88
88
|
identity: rid as ResourceRoleIdentityJson,
|
|
89
89
|
...role,
|
|
@@ -94,11 +94,11 @@ export function extractRoleMapFromRawStrategy(rawStrategy: RawStrategyJson, jobM
|
|
|
94
94
|
return roleMap;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
export function extractSingleNonErrorOutputTypeHandle(
|
|
97
|
+
export function extractSingleNonErrorOutputTypeHandle(tool: ToolJson): ResourceTypeIdentityJson | null {
|
|
98
98
|
const errorRoleId = CONSTANTS.Cosmos.ROLE_ErrorOutput;
|
|
99
|
-
const outputEntries = Object.entries(
|
|
99
|
+
const outputEntries = Object.entries(tool.roleSpec.outputRoleValueByIdentity).filter(([roleId]) => roleId !== errorRoleId);
|
|
100
100
|
if (!outputEntries || !outputEntries[0] || outputEntries.length !== 1) {
|
|
101
|
-
throw new Error(`
|
|
101
|
+
throw new Error(`Tool ${tool.identity} must have exactly one non-error output role to be branchable/loopable`);
|
|
102
102
|
} // ATTENTION_PUREIFY
|
|
103
103
|
const outputRole = outputEntries[0][1];
|
|
104
104
|
return outputRole.resourceTypeHandle;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
BranchStepJson,
|
|
3
3
|
ForStepJson,
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
ToolStepIdentityJson,
|
|
5
|
+
ToolStepJson,
|
|
6
6
|
ResourceRoleIdentityJson,
|
|
7
7
|
StepJson,
|
|
8
8
|
StrategyStateJson,
|
|
@@ -19,53 +19,53 @@ export function getIndependentThreads(steps: StepJson[], strategyState: Strategy
|
|
|
19
19
|
return `steps[${ownerIndex}] stepKind=${(step as any)?.stepKind ?? 'unknown'}`;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
// Map each
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
22
|
+
// Map each toolStep.identity (including macro-nested tool steps) to owning top-level step index.
|
|
23
|
+
const toolStepIdToOwner = new Map<ToolStepIdentityJson, OwnerIndex>();
|
|
24
|
+
const ownerToToolStepIds = new Map<OwnerIndex, ToolStepIdentityJson[]>();
|
|
25
|
+
const toolStepById = new Map<ToolStepIdentityJson, ToolStepJson>();
|
|
26
26
|
|
|
27
|
-
const
|
|
28
|
-
if (!
|
|
27
|
+
const addToolStep = (toolStep: ToolStepJson | undefined, ownerIndex: OwnerIndex) => {
|
|
28
|
+
if (!toolStep?.identity) return;
|
|
29
29
|
|
|
30
|
-
const existingOwner =
|
|
30
|
+
const existingOwner = toolStepIdToOwner.get(toolStep.identity);
|
|
31
31
|
if (existingOwner !== undefined) {
|
|
32
32
|
throw new Error(
|
|
33
|
-
`Duplicate
|
|
33
|
+
`Duplicate toolStep.identity '${toolStep.identity}' found in ${getOwnerLabel(ownerIndex)} and ${getOwnerLabel(existingOwner)}`
|
|
34
34
|
);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const bucket =
|
|
40
|
-
bucket.push(
|
|
41
|
-
|
|
37
|
+
toolStepIdToOwner.set(toolStep.identity, ownerIndex);
|
|
38
|
+
toolStepById.set(toolStep.identity, toolStep);
|
|
39
|
+
const bucket = ownerToToolStepIds.get(ownerIndex) ?? [];
|
|
40
|
+
bucket.push(toolStep.identity);
|
|
41
|
+
ownerToToolStepIds.set(ownerIndex, bucket);
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
steps.forEach((step, ownerIndex) => {
|
|
45
|
-
if (step.stepKind === CONSTANTS.Enums.StepKind.
|
|
46
|
-
|
|
45
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.tool) {
|
|
46
|
+
addToolStep(step as ToolStepJson, ownerIndex);
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
if (step.stepKind === CONSTANTS.Enums.StepKind.for) {
|
|
51
51
|
const loop = step as ForStepJson;
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
addToolStep(loop.case?.what, ownerIndex);
|
|
53
|
+
addToolStep(loop.case?.when, ownerIndex);
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (step.stepKind === CONSTANTS.Enums.StepKind.while) {
|
|
58
58
|
const loop = step as WhileStepJson;
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
addToolStep(loop.case?.what, ownerIndex);
|
|
60
|
+
addToolStep(loop.case?.when, ownerIndex);
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
if (step.stepKind === CONSTANTS.Enums.StepKind.branch) {
|
|
65
65
|
const branch = step as BranchStepJson;
|
|
66
66
|
for (const caseItem of branch.cases ?? []) {
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
addToolStep(caseItem?.what, ownerIndex);
|
|
68
|
+
addToolStep(caseItem?.when, ownerIndex);
|
|
69
69
|
}
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
@@ -86,28 +86,28 @@ export function getIndependentThreads(steps: StepJson[], strategyState: Strategy
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// Discover dependencies from strategyState.
|
|
89
|
-
for (const [
|
|
89
|
+
for (const [toolStepId, ownerIndex] of toolStepIdToOwner) {
|
|
90
90
|
ensureOwner(ownerIndex);
|
|
91
91
|
|
|
92
|
-
const
|
|
93
|
-
const inputBindings =
|
|
94
|
-
const bucket = strategyState?.[
|
|
92
|
+
const toolStep = toolStepById.get(toolStepId);
|
|
93
|
+
const inputBindings = toolStep?.roleBindingSpec?.inputBindings ?? [];
|
|
94
|
+
const bucket = strategyState?.[toolStepId] ?? ({} as any);
|
|
95
95
|
|
|
96
96
|
for (const inputRoleHandle of inputBindings) {
|
|
97
97
|
const entry = bucket?.[inputRoleHandle as ResourceRoleIdentityJson] as any;
|
|
98
98
|
if (!entry || entry.resourceShellKind !== 'internalInputPotential') continue;
|
|
99
99
|
|
|
100
|
-
const
|
|
101
|
-
if (!
|
|
100
|
+
const creatorToolStepHandle = entry?.creationContext?.toolStepHandle as ToolStepIdentityJson | undefined;
|
|
101
|
+
if (!creatorToolStepHandle) {
|
|
102
102
|
throw new Error(
|
|
103
|
-
`Unresolvable internalInputPotential in
|
|
103
|
+
`Unresolvable internalInputPotential in toolStep '${toolStepId}' (${getOwnerLabel(ownerIndex)}): missing creationContext.toolStepHandle for role '${inputRoleHandle}'`
|
|
104
104
|
);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
const producerOwner =
|
|
107
|
+
const producerOwner = toolStepIdToOwner.get(creatorToolStepHandle);
|
|
108
108
|
if (producerOwner === undefined) {
|
|
109
109
|
throw new Error(
|
|
110
|
-
`Unresolvable internalInputPotential in
|
|
110
|
+
`Unresolvable internalInputPotential in toolStep '${toolStepId}' (${getOwnerLabel(ownerIndex)}): creator toolStepHandle '${creatorToolStepHandle}' not found in strategy steps`
|
|
111
111
|
);
|
|
112
112
|
}
|
|
113
113
|
|
|
@@ -27,13 +27,13 @@ export function resolveResourceChain(
|
|
|
27
27
|
|
|
28
28
|
for (let depth = 0; depth <= maxDepth; depth++) {
|
|
29
29
|
path.push(current);
|
|
30
|
-
const visitKey = `${current.
|
|
30
|
+
const visitKey = `${current.toolStepHandle}::${current.resourceRoleHandle}`;
|
|
31
31
|
if (visited.has(visitKey)) {
|
|
32
32
|
return { status: 'unresolved', reason: 'cycle', path };
|
|
33
33
|
}
|
|
34
34
|
visited.add(visitKey);
|
|
35
35
|
|
|
36
|
-
const bucket = strategyState[current.
|
|
36
|
+
const bucket = strategyState[current.toolStepHandle];
|
|
37
37
|
if (!bucket) return { status: 'unresolved', reason: 'not-found', path };
|
|
38
38
|
const entry = bucket[current.resourceRoleHandle] as (
|
|
39
39
|
| ResourceJson
|