@toolproof-core/lib 1.0.42 → 1.0.44
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/lookups/lookups.d.ts +0 -2
- package/dist/lookups/lookups.js +0 -2
- package/dist/utils/stepExpansion.d.ts +6 -0
- package/dist/utils/stepExpansion.js +32 -0
- package/dist/utils/stepParallelization.js +3 -23
- package/dist/utils/strategyExtraction.js +2 -24
- package/dist/utils/toolFilters.d.ts +36 -0
- package/dist/utils/toolFilters.js +107 -0
- package/package.json +5 -1
- package/src/lookups/lookups.ts +0 -2
- package/src/utils/stepExpansion.ts +63 -0
- package/src/utils/stepParallelization.ts +3 -29
- package/src/utils/strategyExtraction.ts +2 -26
- package/src/utils/toolFilters.ts +139 -0
- package/tsconfig.tsbuildinfo +1 -1
package/dist/lookups/lookups.js
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MutableStep, MutableToolStep, MutableToolStepKey } from './mutableStrategyOverlay.js';
|
|
2
|
+
export type StepExpansionOrder = {
|
|
3
|
+
branchCaseOrder?: 'when-what' | 'what-when';
|
|
4
|
+
loopCaseOrder?: 'what-when' | 'when-what';
|
|
5
|
+
};
|
|
6
|
+
export declare function extractToolStepsFromStep<TKey extends string = MutableToolStepKey, TStep extends MutableStep<TKey> = MutableStep<TKey>>(step: TStep, order?: StepExpansionOrder): MutableToolStep<TKey>[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CONSTANTS } from '../lookups/lookups.js';
|
|
2
|
+
export function extractToolStepsFromStep(step, order = {}) {
|
|
3
|
+
const { branchCaseOrder = 'when-what', loopCaseOrder = 'what-when', } = order;
|
|
4
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.tool) {
|
|
5
|
+
return [step];
|
|
6
|
+
}
|
|
7
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.branch) {
|
|
8
|
+
const branch = step;
|
|
9
|
+
const cases = branch.cases ?? [];
|
|
10
|
+
return cases.flatMap((stepCase) => {
|
|
11
|
+
if (branchCaseOrder === 'what-when') {
|
|
12
|
+
return [stepCase.what, stepCase.when];
|
|
13
|
+
}
|
|
14
|
+
return [stepCase.when, stepCase.what];
|
|
15
|
+
}).filter(Boolean);
|
|
16
|
+
}
|
|
17
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.while) {
|
|
18
|
+
const loop = step;
|
|
19
|
+
if (loopCaseOrder === 'when-what') {
|
|
20
|
+
return [loop.case.when, loop.case.what].filter(Boolean);
|
|
21
|
+
}
|
|
22
|
+
return [loop.case.what, loop.case.when].filter(Boolean);
|
|
23
|
+
}
|
|
24
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.for) {
|
|
25
|
+
const loop = step;
|
|
26
|
+
if (loopCaseOrder === 'when-what') {
|
|
27
|
+
return [loop.case.when, loop.case.what].filter(Boolean);
|
|
28
|
+
}
|
|
29
|
+
return [loop.case.what, loop.case.when].filter(Boolean);
|
|
30
|
+
}
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { extractToolStepsFromStep } from './stepExpansion.js';
|
|
2
2
|
export function getIndependentThreads(steps, strategyState) {
|
|
3
3
|
const getOwnerLabel = (ownerIndex) => {
|
|
4
4
|
const step = steps[ownerIndex];
|
|
@@ -17,28 +17,8 @@ export function getIndependentThreads(steps, strategyState) {
|
|
|
17
17
|
toolStepByKey.set(toolStep.toolStepKey, toolStep);
|
|
18
18
|
};
|
|
19
19
|
steps.forEach((step, ownerIndex) => {
|
|
20
|
-
|
|
21
|
-
addToolStep(
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
if (step.stepKind === CONSTANTS.Enums.StepKind.for) {
|
|
25
|
-
const loop = step;
|
|
26
|
-
addToolStep(loop.case?.what, ownerIndex);
|
|
27
|
-
addToolStep(loop.case?.when, ownerIndex);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
if (step.stepKind === CONSTANTS.Enums.StepKind.while) {
|
|
31
|
-
const loop = step;
|
|
32
|
-
addToolStep(loop.case?.what, ownerIndex);
|
|
33
|
-
addToolStep(loop.case?.when, ownerIndex);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (step.stepKind === CONSTANTS.Enums.StepKind.branch) {
|
|
37
|
-
const branch = step;
|
|
38
|
-
for (const stepCase of branch.cases) {
|
|
39
|
-
addToolStep(stepCase?.what, ownerIndex);
|
|
40
|
-
addToolStep(stepCase?.when, ownerIndex);
|
|
41
|
-
}
|
|
20
|
+
for (const toolStep of extractToolStepsFromStep(step, { branchCaseOrder: 'what-when' })) {
|
|
21
|
+
addToolStep(toolStep, ownerIndex);
|
|
42
22
|
}
|
|
43
23
|
});
|
|
44
24
|
const ownerAdj = new Map();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CONSTANTS } from '../lookups/lookups.js';
|
|
2
|
+
import { extractToolStepsFromStep } from './stepExpansion.js';
|
|
2
3
|
export function getInputRoleSpecEntriesFromTool(tool) {
|
|
3
4
|
return Object.entries(tool.roleSpec.inputRoleValueByName);
|
|
4
5
|
}
|
|
@@ -20,32 +21,9 @@ export function extractResourceTypeHandleFromRoleValue(roleValue) {
|
|
|
20
21
|
}
|
|
21
22
|
export function extractToolStepsFromStrategy(strategy) {
|
|
22
23
|
const toolSteps = [];
|
|
23
|
-
const visitStep = (step) => {
|
|
24
|
-
switch (step.stepKind) {
|
|
25
|
-
case 'tool': {
|
|
26
|
-
toolSteps.push(step);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
case 'branch': {
|
|
30
|
-
for (const conditional of step.cases) {
|
|
31
|
-
toolSteps.push(conditional.when, conditional.what);
|
|
32
|
-
}
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
case 'while':
|
|
36
|
-
case 'for': {
|
|
37
|
-
toolSteps.push(step.case.when, step.case.what);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
default: {
|
|
41
|
-
const _exhaustive = step;
|
|
42
|
-
return _exhaustive;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
24
|
for (const threadSteps of strategy.stepsByThreadIndex) {
|
|
47
25
|
for (const step of threadSteps) {
|
|
48
|
-
|
|
26
|
+
toolSteps.push(...extractToolStepsFromStep(step, { loopCaseOrder: 'when-what' }));
|
|
49
27
|
}
|
|
50
28
|
}
|
|
51
29
|
return toolSteps;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Tool, ToolHandle } from '@toolproof-core/genesis';
|
|
2
|
+
export declare function isInstantiationTool(tool: Tool): boolean;
|
|
3
|
+
export declare function isScalarRoleValueOnlyTool(tool: Tool): boolean;
|
|
4
|
+
export declare function isResourceTypeHandleBackedRoleValueOnlyTool(tool: Tool): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Returns Tools that can be used as LoopStep whatTools.
|
|
7
|
+
*
|
|
8
|
+
* A Tool is "loop-step-eligible" if:
|
|
9
|
+
* - it has exactly one input role
|
|
10
|
+
* - it has exactly one output role
|
|
11
|
+
* - the input and output roles share the same type
|
|
12
|
+
*/
|
|
13
|
+
export declare function getLoopStepWhatSlotEligibleToolHandles(toolMap: Map<ToolHandle, Tool>): ToolHandle[];
|
|
14
|
+
/**
|
|
15
|
+
* Returns Tools that can be used as BranchStep whatTools.
|
|
16
|
+
*
|
|
17
|
+
* A Tool is "branch-step-eligible" if:
|
|
18
|
+
* - it has exactly one output role
|
|
19
|
+
* - there's also a cross-case requirement that the whatTool's output role types must be the same (this is enforced dynamically at buildtime)
|
|
20
|
+
*/
|
|
21
|
+
export declare function getBranchStepWhatSlotEligibleToolHandles(toolMap: Map<ToolHandle, Tool>): ToolHandle[];
|
|
22
|
+
/**
|
|
23
|
+
* Returns Tools that can be used as MacroStep whenTools.
|
|
24
|
+
*
|
|
25
|
+
* A Tool is "when-slot-eligible" if:
|
|
26
|
+
* - it has exactly one output role and that output role is of type `TYPE-Boolean`
|
|
27
|
+
* - all input role types are available in strategyState at the point of execution (this is enforced dynamically at buildtime)
|
|
28
|
+
*/
|
|
29
|
+
export declare function getMacroStepWhenSlotEligibleToolHandles(toolMap: Map<ToolHandle, Tool>): ToolHandle[];
|
|
30
|
+
type ToolFilters = {
|
|
31
|
+
instantiationOnly?: boolean;
|
|
32
|
+
scalarRoleValueOnly?: boolean;
|
|
33
|
+
resourceTypeHandleBackedRoleValueOnly?: boolean;
|
|
34
|
+
};
|
|
35
|
+
export declare function getFilteredToolMap(toolMap: Map<ToolHandle, Tool>, filters?: ToolFilters): Map<ToolHandle, Tool>;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { CONSTANTS } from '../lookups/lookups.js';
|
|
2
|
+
import { extractResourceTypeHandleFromRoleValue } from './strategyExtraction.js';
|
|
3
|
+
export function isInstantiationTool(tool) {
|
|
4
|
+
return tool.isTemplate !== true;
|
|
5
|
+
}
|
|
6
|
+
function isScalarRoleValue(roleValue) {
|
|
7
|
+
return roleValue.containerKind === 'scalar';
|
|
8
|
+
}
|
|
9
|
+
export function isScalarRoleValueOnlyTool(tool) {
|
|
10
|
+
const inputRoleValues = Object.values(tool.roleSpec.inputRoleValueByName);
|
|
11
|
+
const outputRoleValues = Object.values(tool.roleSpec.outputRoleValueByName);
|
|
12
|
+
return [...inputRoleValues, ...outputRoleValues].every(isScalarRoleValue);
|
|
13
|
+
}
|
|
14
|
+
export function isResourceTypeHandleBackedRoleValueOnlyTool(tool) {
|
|
15
|
+
const roleValues = [
|
|
16
|
+
...Object.values(tool.roleSpec.inputRoleValueByName),
|
|
17
|
+
...Object.values(tool.roleSpec.outputRoleValueByName),
|
|
18
|
+
];
|
|
19
|
+
return roleValues.every((roleValue) => extractResourceTypeHandleFromRoleValue(roleValue) !== null);
|
|
20
|
+
}
|
|
21
|
+
// ATTENTION: the slot-eligibility functions below can currently handle only scalar, resourceTypeHandle-backed role values. Callers must ensure that the provided toolMaps are pre-filtered accordingly.
|
|
22
|
+
/**
|
|
23
|
+
* Returns Tools that can be used as LoopStep whatTools.
|
|
24
|
+
*
|
|
25
|
+
* A Tool is "loop-step-eligible" if:
|
|
26
|
+
* - it has exactly one input role
|
|
27
|
+
* - it has exactly one output role
|
|
28
|
+
* - the input and output roles share the same type
|
|
29
|
+
*/
|
|
30
|
+
export function getLoopStepWhatSlotEligibleToolHandles(toolMap) {
|
|
31
|
+
const candidates = [];
|
|
32
|
+
for (const tool of toolMap.values()) {
|
|
33
|
+
const inputEntries = Object.entries(tool.roleSpec.inputRoleValueByName);
|
|
34
|
+
if (inputEntries.length !== 1)
|
|
35
|
+
continue;
|
|
36
|
+
const outputEntries = Object.entries(tool.roleSpec.outputRoleValueByName);
|
|
37
|
+
if (outputEntries.length !== 1)
|
|
38
|
+
continue;
|
|
39
|
+
const firstInputEntry = inputEntries[0];
|
|
40
|
+
if (!firstInputEntry)
|
|
41
|
+
continue;
|
|
42
|
+
const firstOutputEntry = outputEntries[0];
|
|
43
|
+
if (!firstOutputEntry)
|
|
44
|
+
continue;
|
|
45
|
+
const inputRole = firstInputEntry[1];
|
|
46
|
+
const outputRole = firstOutputEntry[1];
|
|
47
|
+
const inputType = extractResourceTypeHandleFromRoleValue(inputRole);
|
|
48
|
+
const outputType = extractResourceTypeHandleFromRoleValue(outputRole);
|
|
49
|
+
if (inputType !== outputType)
|
|
50
|
+
continue; // ATTENTION: relies on pre-filtering to resourceTypeHandle-backed role values for correctness
|
|
51
|
+
candidates.push(tool.handle);
|
|
52
|
+
}
|
|
53
|
+
return candidates;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns Tools that can be used as BranchStep whatTools.
|
|
57
|
+
*
|
|
58
|
+
* A Tool is "branch-step-eligible" if:
|
|
59
|
+
* - it has exactly one output role
|
|
60
|
+
* - there's also a cross-case requirement that the whatTool's output role types must be the same (this is enforced dynamically at buildtime)
|
|
61
|
+
*/
|
|
62
|
+
export function getBranchStepWhatSlotEligibleToolHandles(toolMap) {
|
|
63
|
+
const candidates = [];
|
|
64
|
+
for (const tool of toolMap.values()) {
|
|
65
|
+
const outputEntries = Object.entries(tool.roleSpec.outputRoleValueByName);
|
|
66
|
+
if (outputEntries.length !== 1)
|
|
67
|
+
continue;
|
|
68
|
+
candidates.push(tool.handle);
|
|
69
|
+
}
|
|
70
|
+
return candidates;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns Tools that can be used as MacroStep whenTools.
|
|
74
|
+
*
|
|
75
|
+
* A Tool is "when-slot-eligible" if:
|
|
76
|
+
* - it has exactly one output role and that output role is of type `TYPE-Boolean`
|
|
77
|
+
* - all input role types are available in strategyState at the point of execution (this is enforced dynamically at buildtime)
|
|
78
|
+
*/
|
|
79
|
+
export function getMacroStepWhenSlotEligibleToolHandles(toolMap) {
|
|
80
|
+
const candidates = [];
|
|
81
|
+
for (const tool of toolMap.values()) {
|
|
82
|
+
const outputEntries = Object.entries(tool.roleSpec.outputRoleValueByName);
|
|
83
|
+
if (outputEntries.length !== 1)
|
|
84
|
+
continue;
|
|
85
|
+
const firstOutputEntry = outputEntries[0];
|
|
86
|
+
if (!firstOutputEntry)
|
|
87
|
+
continue;
|
|
88
|
+
const outputRoleValue = firstOutputEntry[1];
|
|
89
|
+
const outputType = extractResourceTypeHandleFromRoleValue(outputRoleValue);
|
|
90
|
+
if (outputType !== CONSTANTS.Handles.ResourceTypes.TYPE_Boolean)
|
|
91
|
+
continue;
|
|
92
|
+
candidates.push(tool.handle);
|
|
93
|
+
}
|
|
94
|
+
return candidates;
|
|
95
|
+
}
|
|
96
|
+
export function getFilteredToolMap(toolMap, filters = {
|
|
97
|
+
instantiationOnly: true,
|
|
98
|
+
scalarRoleValueOnly: true,
|
|
99
|
+
resourceTypeHandleBackedRoleValueOnly: true,
|
|
100
|
+
}) {
|
|
101
|
+
const filteredEntries = Array.from(toolMap.entries()).filter(([, tool]) => {
|
|
102
|
+
return ((!filters.instantiationOnly || isInstantiationTool(tool))
|
|
103
|
+
&& (!filters.scalarRoleValueOnly || isScalarRoleValueOnlyTool(tool))
|
|
104
|
+
&& (!filters.resourceTypeHandleBackedRoleValueOnly || isResourceTypeHandleBackedRoleValueOnlyTool(tool)));
|
|
105
|
+
});
|
|
106
|
+
return new Map(filteredEntries);
|
|
107
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toolproof-core/lib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.44",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [],
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"types": "./dist/utils/stepCreation.d.ts",
|
|
40
40
|
"import": "./dist/utils/stepCreation.js"
|
|
41
41
|
},
|
|
42
|
+
"./step-expansion": {
|
|
43
|
+
"types": "./dist/utils/stepExpansion.d.ts",
|
|
44
|
+
"import": "./dist/utils/stepExpansion.js"
|
|
45
|
+
},
|
|
42
46
|
"./tool-step-paths": {
|
|
43
47
|
"types": "./dist/utils/toolStepPaths.d.ts",
|
|
44
48
|
"import": "./dist/utils/toolStepPaths.js"
|
package/src/lookups/lookups.ts
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CONSTANTS } from '../lookups/lookups.js';
|
|
2
|
+
import type {
|
|
3
|
+
MutableBranchStep,
|
|
4
|
+
MutableForStep,
|
|
5
|
+
MutableStep,
|
|
6
|
+
MutableToolStep,
|
|
7
|
+
MutableToolStepKey,
|
|
8
|
+
MutableWhileStep,
|
|
9
|
+
} from './mutableStrategyOverlay.js';
|
|
10
|
+
|
|
11
|
+
export type StepExpansionOrder = {
|
|
12
|
+
branchCaseOrder?: 'when-what' | 'what-when';
|
|
13
|
+
loopCaseOrder?: 'what-when' | 'when-what';
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function extractToolStepsFromStep<
|
|
17
|
+
TKey extends string = MutableToolStepKey,
|
|
18
|
+
TStep extends MutableStep<TKey> = MutableStep<TKey>,
|
|
19
|
+
>(
|
|
20
|
+
step: TStep,
|
|
21
|
+
order: StepExpansionOrder = {},
|
|
22
|
+
): MutableToolStep<TKey>[] {
|
|
23
|
+
const {
|
|
24
|
+
branchCaseOrder = 'when-what',
|
|
25
|
+
loopCaseOrder = 'what-when',
|
|
26
|
+
} = order;
|
|
27
|
+
|
|
28
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.tool) {
|
|
29
|
+
return [step as MutableToolStep<TKey>];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.branch) {
|
|
33
|
+
const branch = step as MutableBranchStep<TKey>;
|
|
34
|
+
const cases = branch.cases ?? [];
|
|
35
|
+
return cases.flatMap((stepCase) => {
|
|
36
|
+
if (branchCaseOrder === 'what-when') {
|
|
37
|
+
return [stepCase.what, stepCase.when];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return [stepCase.when, stepCase.what];
|
|
41
|
+
}).filter(Boolean) as MutableToolStep<TKey>[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.while) {
|
|
45
|
+
const loop = step as MutableWhileStep<TKey>;
|
|
46
|
+
if (loopCaseOrder === 'when-what') {
|
|
47
|
+
return [loop.case.when, loop.case.what].filter(Boolean) as MutableToolStep<TKey>[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return [loop.case.what, loop.case.when].filter(Boolean) as MutableToolStep<TKey>[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (step.stepKind === CONSTANTS.Enums.StepKind.for) {
|
|
54
|
+
const loop = step as MutableForStep<TKey>;
|
|
55
|
+
if (loopCaseOrder === 'when-what') {
|
|
56
|
+
return [loop.case.when, loop.case.what].filter(Boolean) as MutableToolStep<TKey>[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return [loop.case.what, loop.case.when].filter(Boolean) as MutableToolStep<TKey>[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return [] as MutableToolStep<TKey>[];
|
|
63
|
+
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
MutableBranchStep,
|
|
3
|
-
MutableForStep,
|
|
4
2
|
MutableStep,
|
|
5
3
|
MutableStrategyState,
|
|
6
4
|
MutableToolStep,
|
|
7
5
|
MutableToolStepKey,
|
|
8
|
-
MutableWhileStep,
|
|
9
6
|
} from './mutableStrategyOverlay.js';
|
|
10
|
-
import {
|
|
7
|
+
import { extractToolStepsFromStep } from './stepExpansion.js';
|
|
11
8
|
|
|
12
9
|
export function getIndependentThreads<
|
|
13
10
|
TKey extends string = MutableToolStepKey,
|
|
@@ -44,31 +41,8 @@ export function getIndependentThreads<
|
|
|
44
41
|
};
|
|
45
42
|
|
|
46
43
|
steps.forEach((step, ownerIndex) => {
|
|
47
|
-
|
|
48
|
-
addToolStep(
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (step.stepKind === CONSTANTS.Enums.StepKind.for) {
|
|
53
|
-
const loop = step as MutableForStep<TKey>;
|
|
54
|
-
addToolStep(loop.case?.what, ownerIndex);
|
|
55
|
-
addToolStep(loop.case?.when, ownerIndex);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (step.stepKind === CONSTANTS.Enums.StepKind.while) {
|
|
60
|
-
const loop = step as MutableWhileStep<TKey>;
|
|
61
|
-
addToolStep(loop.case?.what, ownerIndex);
|
|
62
|
-
addToolStep(loop.case?.when, ownerIndex);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (step.stepKind === CONSTANTS.Enums.StepKind.branch) {
|
|
67
|
-
const branch = step as MutableBranchStep<TKey>;
|
|
68
|
-
for (const stepCase of branch.cases) {
|
|
69
|
-
addToolStep(stepCase?.what, ownerIndex);
|
|
70
|
-
addToolStep(stepCase?.when, ownerIndex);
|
|
71
|
-
}
|
|
44
|
+
for (const toolStep of extractToolStepsFromStep<TKey, TStep>(step, { branchCaseOrder: 'what-when' })) {
|
|
45
|
+
addToolStep(toolStep, ownerIndex);
|
|
72
46
|
}
|
|
73
47
|
});
|
|
74
48
|
|
|
@@ -8,10 +8,10 @@ import type {
|
|
|
8
8
|
} from '@toolproof-core/genesis';
|
|
9
9
|
import type {
|
|
10
10
|
MutableStrategy,
|
|
11
|
-
MutableStep,
|
|
12
11
|
MutableToolStep
|
|
13
12
|
} from './mutableStrategyOverlay.js';
|
|
14
13
|
import { CONSTANTS } from '../lookups/lookups.js';
|
|
14
|
+
import { extractToolStepsFromStep } from './stepExpansion.js';
|
|
15
15
|
|
|
16
16
|
export type RoleSpecEntry = [RoleName, RoleValue];
|
|
17
17
|
|
|
@@ -55,33 +55,9 @@ export function extractResourceTypeHandleFromRoleValue(
|
|
|
55
55
|
export function extractToolStepsFromStrategy(strategy: MutableStrategy): MutableToolStep[] {
|
|
56
56
|
const toolSteps: MutableToolStep[] = [];
|
|
57
57
|
|
|
58
|
-
const visitStep = (step: MutableStep) => {
|
|
59
|
-
switch (step.stepKind) {
|
|
60
|
-
case 'tool': {
|
|
61
|
-
toolSteps.push(step);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
case 'branch': {
|
|
65
|
-
for (const conditional of step.cases) {
|
|
66
|
-
toolSteps.push(conditional.when, conditional.what);
|
|
67
|
-
}
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
case 'while':
|
|
71
|
-
case 'for': {
|
|
72
|
-
toolSteps.push(step.case.when, step.case.what);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
default: {
|
|
76
|
-
const _exhaustive: never = step;
|
|
77
|
-
return _exhaustive;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
58
|
for (const threadSteps of strategy.stepsByThreadIndex) {
|
|
83
59
|
for (const step of threadSteps) {
|
|
84
|
-
|
|
60
|
+
toolSteps.push(...extractToolStepsFromStep(step, { loopCaseOrder: 'when-what' }));
|
|
85
61
|
}
|
|
86
62
|
}
|
|
87
63
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { RoleValue, Tool, ToolHandle } from '@toolproof-core/genesis';
|
|
2
|
+
import { CONSTANTS } from '../lookups/lookups.js';
|
|
3
|
+
import { extractResourceTypeHandleFromRoleValue } from './strategyExtraction.js';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export function isInstantiationTool(tool: Tool): boolean {
|
|
7
|
+
return tool.isTemplate !== true;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function isScalarRoleValue(roleValue: RoleValue): boolean {
|
|
11
|
+
return roleValue.containerKind === 'scalar';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isScalarRoleValueOnlyTool(tool: Tool): boolean {
|
|
15
|
+
const inputRoleValues = Object.values(tool.roleSpec.inputRoleValueByName);
|
|
16
|
+
const outputRoleValues = Object.values(tool.roleSpec.outputRoleValueByName);
|
|
17
|
+
|
|
18
|
+
return [...inputRoleValues, ...outputRoleValues].every(isScalarRoleValue);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isResourceTypeHandleBackedRoleValueOnlyTool(tool: Tool): boolean {
|
|
22
|
+
const roleValues = [
|
|
23
|
+
...Object.values(tool.roleSpec.inputRoleValueByName),
|
|
24
|
+
...Object.values(tool.roleSpec.outputRoleValueByName),
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
return roleValues.every(
|
|
28
|
+
(roleValue) => extractResourceTypeHandleFromRoleValue(roleValue) !== null
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ATTENTION: the slot-eligibility functions below can currently handle only scalar, resourceTypeHandle-backed role values. Callers must ensure that the provided toolMaps are pre-filtered accordingly.
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns Tools that can be used as LoopStep whatTools.
|
|
36
|
+
*
|
|
37
|
+
* A Tool is "loop-step-eligible" if:
|
|
38
|
+
* - it has exactly one input role
|
|
39
|
+
* - it has exactly one output role
|
|
40
|
+
* - the input and output roles share the same type
|
|
41
|
+
*/
|
|
42
|
+
export function getLoopStepWhatSlotEligibleToolHandles(toolMap: Map<ToolHandle, Tool>): ToolHandle[] {
|
|
43
|
+
const candidates: ToolHandle[] = [];
|
|
44
|
+
|
|
45
|
+
for (const tool of toolMap.values()) {
|
|
46
|
+
|
|
47
|
+
const inputEntries = Object.entries(tool.roleSpec.inputRoleValueByName);
|
|
48
|
+
if (inputEntries.length !== 1) continue;
|
|
49
|
+
|
|
50
|
+
const outputEntries = Object.entries(tool.roleSpec.outputRoleValueByName);
|
|
51
|
+
if (outputEntries.length !== 1) continue;
|
|
52
|
+
|
|
53
|
+
const firstInputEntry = inputEntries[0];
|
|
54
|
+
if (!firstInputEntry) continue;
|
|
55
|
+
|
|
56
|
+
const firstOutputEntry = outputEntries[0];
|
|
57
|
+
if (!firstOutputEntry) continue;
|
|
58
|
+
|
|
59
|
+
const inputRole = firstInputEntry[1];
|
|
60
|
+
const outputRole = firstOutputEntry[1];
|
|
61
|
+
|
|
62
|
+
const inputType = extractResourceTypeHandleFromRoleValue(inputRole);
|
|
63
|
+
const outputType = extractResourceTypeHandleFromRoleValue(outputRole);
|
|
64
|
+
|
|
65
|
+
if (inputType !== outputType) continue; // ATTENTION: relies on pre-filtering to resourceTypeHandle-backed role values for correctness
|
|
66
|
+
|
|
67
|
+
candidates.push(tool.handle);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return candidates;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Returns Tools that can be used as BranchStep whatTools.
|
|
75
|
+
*
|
|
76
|
+
* A Tool is "branch-step-eligible" if:
|
|
77
|
+
* - it has exactly one output role
|
|
78
|
+
* - there's also a cross-case requirement that the whatTool's output role types must be the same (this is enforced dynamically at buildtime)
|
|
79
|
+
*/
|
|
80
|
+
export function getBranchStepWhatSlotEligibleToolHandles(toolMap: Map<ToolHandle, Tool>): ToolHandle[] {
|
|
81
|
+
const candidates: ToolHandle[] = [];
|
|
82
|
+
|
|
83
|
+
for (const tool of toolMap.values()) {
|
|
84
|
+
const outputEntries = Object.entries(tool.roleSpec.outputRoleValueByName);
|
|
85
|
+
if (outputEntries.length !== 1) continue;
|
|
86
|
+
candidates.push(tool.handle);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return candidates;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Returns Tools that can be used as MacroStep whenTools.
|
|
94
|
+
*
|
|
95
|
+
* A Tool is "when-slot-eligible" if:
|
|
96
|
+
* - it has exactly one output role and that output role is of type `TYPE-Boolean`
|
|
97
|
+
* - all input role types are available in strategyState at the point of execution (this is enforced dynamically at buildtime)
|
|
98
|
+
*/
|
|
99
|
+
export function getMacroStepWhenSlotEligibleToolHandles(toolMap: Map<ToolHandle, Tool>): ToolHandle[] {
|
|
100
|
+
const candidates: ToolHandle[] = [];
|
|
101
|
+
|
|
102
|
+
for (const tool of toolMap.values()) {
|
|
103
|
+
const outputEntries = Object.entries(tool.roleSpec.outputRoleValueByName);
|
|
104
|
+
if (outputEntries.length !== 1) continue;
|
|
105
|
+
const firstOutputEntry = outputEntries[0];
|
|
106
|
+
if (!firstOutputEntry) continue;
|
|
107
|
+
const outputRoleValue = firstOutputEntry[1];
|
|
108
|
+
const outputType = extractResourceTypeHandleFromRoleValue(outputRoleValue);
|
|
109
|
+
if (outputType !== CONSTANTS.Handles.ResourceTypes.TYPE_Boolean) continue;
|
|
110
|
+
candidates.push(tool.handle);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return candidates;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
type ToolFilters = {
|
|
117
|
+
instantiationOnly?: boolean;
|
|
118
|
+
scalarRoleValueOnly?: boolean;
|
|
119
|
+
resourceTypeHandleBackedRoleValueOnly?: boolean;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export function getFilteredToolMap(
|
|
123
|
+
toolMap: Map<ToolHandle, Tool>,
|
|
124
|
+
filters: ToolFilters = {
|
|
125
|
+
instantiationOnly: true,
|
|
126
|
+
scalarRoleValueOnly: true,
|
|
127
|
+
resourceTypeHandleBackedRoleValueOnly: true,
|
|
128
|
+
},
|
|
129
|
+
): Map<ToolHandle, Tool> {
|
|
130
|
+
const filteredEntries = Array.from(toolMap.entries()).filter(([, tool]) => {
|
|
131
|
+
return (
|
|
132
|
+
(!filters.instantiationOnly || isInstantiationTool(tool))
|
|
133
|
+
&& (!filters.scalarRoleValueOnly || isScalarRoleValueOnlyTool(tool))
|
|
134
|
+
&& (!filters.resourceTypeHandleBackedRoleValueOnly || isResourceTypeHandleBackedRoleValueOnlyTool(tool))
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return new Map(filteredEntries);
|
|
139
|
+
}
|