@toolproof-core/lib 1.0.34 → 1.0.37
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/integrations/firebase/firebaseAdminHelpers.d.ts +3 -10
- package/dist/integrations/firebase/firebaseAdminHelpers.js +43 -148
- package/dist/integrations/firebase/firebaseAdminInit.d.ts +0 -1
- package/dist/integrations/firebase/firebaseAdminInit.js +0 -1
- package/dist/lookups/lookups.d.ts +214 -0
- package/dist/lookups/lookups.js +33 -0
- package/dist/types/types.d.ts +15 -15
- package/dist/types/types.js +2 -3
- package/dist/utils/cosmosDataExtraction.d.ts +5 -0
- package/dist/utils/cosmosDataExtraction.js +15 -0
- package/dist/utils/identifierGeneration.d.ts +2 -0
- package/dist/utils/identifierGeneration.js +5 -0
- package/dist/utils/mutableStrategyOverlay.d.ts +55 -0
- package/dist/utils/mutableStrategyOverlay.js +115 -0
- package/dist/utils/resourceCreation.d.ts +11 -0
- package/dist/utils/resourceCreation.js +32 -0
- package/dist/utils/stepCreation.d.ts +9 -0
- package/dist/utils/stepCreation.js +79 -0
- package/dist/utils/stepParallelization.d.ts +2 -0
- package/dist/utils/{parallelizeSteps.js → stepParallelization.js} +40 -55
- package/dist/utils/strategyAssembly.d.ts +3 -0
- package/dist/utils/strategyAssembly.js +6 -0
- package/dist/utils/strategyCanonicalization.d.ts +4 -0
- package/dist/utils/strategyCanonicalization.js +215 -0
- package/dist/utils/strategyExtraction.d.ts +17 -0
- package/dist/utils/strategyExtraction.js +88 -0
- package/dist/utils/strategyStateResolution.d.ts +17 -0
- package/dist/utils/strategyStateResolution.js +27 -0
- package/dist/utils/strategyThreading.d.ts +2 -0
- package/dist/utils/strategyThreading.js +10 -0
- package/dist/utils/toolStepPaths.d.ts +2 -0
- package/dist/utils/toolStepPaths.js +21 -0
- package/package.json +43 -23
- package/src/integrations/firebase/firebaseAdminHelpers.ts +57 -180
- package/src/lookups/lookups.ts +35 -0
- package/src/types/types.ts +16 -13
- package/src/utils/cosmosDataExtraction.ts +25 -0
- package/src/utils/identifierGeneration.ts +12 -0
- package/src/utils/mutableStrategyOverlay.ts +286 -0
- package/src/utils/resourceCreation.ts +87 -0
- package/src/utils/stepCreation.ts +114 -0
- package/src/utils/stepParallelization.ts +181 -0
- package/src/utils/strategyAssembly.ts +14 -0
- package/src/utils/strategyCanonicalization.ts +294 -0
- package/src/utils/strategyExtraction.ts +150 -0
- package/src/utils/strategyStateResolution.ts +57 -0
- package/src/utils/strategyThreading.ts +27 -0
- package/src/utils/toolStepPaths.ts +34 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/artifacts/artifacts.d.ts +0 -175
- package/dist/artifacts/artifacts.d.ts.map +0 -1
- package/dist/artifacts/artifacts.js +0 -48
- package/dist/artifacts/artifacts.js.map +0 -1
- package/dist/integrations/firebase/createStep.d.ts +0 -11
- package/dist/integrations/firebase/createStep.d.ts.map +0 -1
- package/dist/integrations/firebase/createStep.js +0 -43
- package/dist/integrations/firebase/createStep.js.map +0 -1
- package/dist/integrations/firebase/createThreadedStrategy.d.ts +0 -3
- package/dist/integrations/firebase/createThreadedStrategy.d.ts.map +0 -1
- package/dist/integrations/firebase/createThreadedStrategy.js +0 -9
- package/dist/integrations/firebase/createThreadedStrategy.js.map +0 -1
- package/dist/integrations/firebase/firebaseAdminHelpers.d.ts.map +0 -1
- package/dist/integrations/firebase/firebaseAdminHelpers.js.map +0 -1
- package/dist/integrations/firebase/firebaseAdminInit.d.ts.map +0 -1
- package/dist/integrations/firebase/firebaseAdminInit.js.map +0 -1
- package/dist/types/types.d.ts.map +0 -1
- package/dist/types/types.js.map +0 -1
- package/dist/utils/bindInputRoleToResource.d.ts +0 -6
- package/dist/utils/bindInputRoleToResource.d.ts.map +0 -1
- package/dist/utils/bindInputRoleToResource.js +0 -25
- package/dist/utils/bindInputRoleToResource.js.map +0 -1
- package/dist/utils/creation/resourceCreation.d.ts +0 -21
- package/dist/utils/creation/resourceCreation.d.ts.map +0 -1
- package/dist/utils/creation/resourceCreation.js +0 -66
- package/dist/utils/creation/resourceCreation.js.map +0 -1
- package/dist/utils/creation/stepCreation.d.ts +0 -51
- package/dist/utils/creation/stepCreation.d.ts.map +0 -1
- package/dist/utils/creation/stepCreation.js +0 -90
- package/dist/utils/creation/stepCreation.js.map +0 -1
- package/dist/utils/creation/threadedStrategyCreation.d.ts +0 -19
- package/dist/utils/creation/threadedStrategyCreation.d.ts.map +0 -1
- package/dist/utils/creation/threadedStrategyCreation.js +0 -17
- package/dist/utils/creation/threadedStrategyCreation.js.map +0 -1
- package/dist/utils/extractData.d.ts +0 -13
- package/dist/utils/extractData.d.ts.map +0 -1
- package/dist/utils/extractData.js +0 -74
- package/dist/utils/extractData.js.map +0 -1
- package/dist/utils/parallelizeSteps.d.ts +0 -4
- package/dist/utils/parallelizeSteps.d.ts.map +0 -1
- package/dist/utils/parallelizeSteps.js.map +0 -1
- package/dist/utils/resolveResourceChain.d.ts +0 -19
- package/dist/utils/resolveResourceChain.d.ts.map +0 -1
- package/dist/utils/resolveResourceChain.js +0 -31
- package/dist/utils/resolveResourceChain.js.map +0 -1
- package/dist/utils/roleSpec.d.ts +0 -17
- package/dist/utils/roleSpec.d.ts.map +0 -1
- package/dist/utils/roleSpec.js +0 -58
- package/dist/utils/roleSpec.js.map +0 -1
- package/dist/utils/strategyState.d.ts +0 -8
- package/dist/utils/strategyState.d.ts.map +0 -1
- package/dist/utils/strategyState.js +0 -29
- package/dist/utils/strategyState.js.map +0 -1
- package/src/artifacts/artifacts.ts +0 -49
- package/src/integrations/firebase/createStep.ts +0 -71
- package/src/integrations/firebase/createThreadedStrategy.ts +0 -19
- package/src/utils/bindInputRoleToResource.ts +0 -54
- package/src/utils/creation/resourceCreation.ts +0 -121
- package/src/utils/creation/stepCreation.ts +0 -165
- package/src/utils/creation/threadedStrategyCreation.ts +0 -42
- package/src/utils/extractData.ts +0 -129
- package/src/utils/parallelizeSteps.ts +0 -187
- package/src/utils/resolveResourceChain.ts +0 -52
- package/src/utils/roleSpec.ts +0 -84
- package/src/utils/strategyState.ts +0 -57
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { CONSTANTS } from '../lookups/lookups.js';
|
|
2
|
+
export function getInputRoleSpecEntriesFromTool(tool) {
|
|
3
|
+
return Object.entries(tool.roleSpec.inputRoleValueByName);
|
|
4
|
+
}
|
|
5
|
+
export function getOutputRoleSpecEntriesFromTool(tool) {
|
|
6
|
+
return Object.entries(tool.roleSpec.outputRoleValueByName);
|
|
7
|
+
}
|
|
8
|
+
export function getInputRoleNamesFromTool(tool) {
|
|
9
|
+
return getInputRoleSpecEntriesFromTool(tool).map(([roleName]) => roleName);
|
|
10
|
+
}
|
|
11
|
+
export function getOutputRoleNamesFromTool(tool) {
|
|
12
|
+
return getOutputRoleSpecEntriesFromTool(tool).map(([roleName]) => roleName);
|
|
13
|
+
}
|
|
14
|
+
export function extractResourceTypeHandleFromRoleValue(roleValue) {
|
|
15
|
+
const typeRef = roleValue.typeRef;
|
|
16
|
+
if ('resourceTypeHandle' in typeRef) {
|
|
17
|
+
return typeRef.resourceTypeHandle;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
export function extractToolStepsFromStrategy(strategy) {
|
|
22
|
+
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
|
+
for (const threadSteps of strategy.stepsByThreadIndex) {
|
|
47
|
+
for (const step of threadSteps) {
|
|
48
|
+
visitStep(step);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return toolSteps;
|
|
52
|
+
}
|
|
53
|
+
export function extractToolsFromStrategy(strategy, toolMap) {
|
|
54
|
+
const toolSteps = extractToolStepsFromStrategy(strategy);
|
|
55
|
+
const toolHandles = new Set();
|
|
56
|
+
const tools = [];
|
|
57
|
+
for (const toolStep of toolSteps) {
|
|
58
|
+
toolHandles.add(toolStep.toolHandle);
|
|
59
|
+
}
|
|
60
|
+
for (const toolHandle of toolHandles) {
|
|
61
|
+
const tool = toolMap.get(toolHandle);
|
|
62
|
+
if (!tool) {
|
|
63
|
+
throw new Error(`Tool with handle '${toolHandle}' not found in toolMap.`);
|
|
64
|
+
}
|
|
65
|
+
tools.push(tool);
|
|
66
|
+
}
|
|
67
|
+
return tools;
|
|
68
|
+
}
|
|
69
|
+
function extractRoleSpecByDirectionFromTool(tool) {
|
|
70
|
+
return {
|
|
71
|
+
inputRoleValueByName: new Map(getInputRoleSpecEntriesFromTool(tool)),
|
|
72
|
+
outputRoleValueByName: new Map(getOutputRoleSpecEntriesFromTool(tool)),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function extractRoleSpecByDirectionByToolHandleFromStrategy(strategy, toolMap) {
|
|
76
|
+
const roleSpecByDirectionByToolHandle = new Map();
|
|
77
|
+
for (const tool of extractToolsFromStrategy(strategy, toolMap)) {
|
|
78
|
+
roleSpecByDirectionByToolHandle.set(tool.handle, extractRoleSpecByDirectionFromTool(tool));
|
|
79
|
+
}
|
|
80
|
+
return roleSpecByDirectionByToolHandle;
|
|
81
|
+
}
|
|
82
|
+
export function extractSingleBranchableOutputResourceTypeHandle(tool) {
|
|
83
|
+
const outputRoleSpecEntries = getOutputRoleSpecEntriesFromTool(tool).filter(([roleName]) => roleName !== CONSTANTS.Cosmos.ErrorOutputRoleName);
|
|
84
|
+
if (!outputRoleSpecEntries[0] || outputRoleSpecEntries.length !== 1) {
|
|
85
|
+
throw new Error(`Tool ${tool.handle} must have exactly one branchable output resource type to be branchable/loopable`);
|
|
86
|
+
}
|
|
87
|
+
return extractResourceTypeHandleFromRoleValue(outputRoleSpecEntries[0][1]);
|
|
88
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MutableInputResource, MutableExternalInputPotential, MutableStrategyState, MutableToolStepKey, MutableToolStepRoleAddress } from './mutableStrategyOverlay.js';
|
|
2
|
+
export type ResolveResult<TKey extends string = MutableToolStepKey> = {
|
|
3
|
+
status: 'inputResource';
|
|
4
|
+
entry: MutableInputResource;
|
|
5
|
+
path: MutableToolStepRoleAddress<TKey>[];
|
|
6
|
+
} | {
|
|
7
|
+
status: 'externalInputPotential';
|
|
8
|
+
entry: MutableExternalInputPotential;
|
|
9
|
+
path: MutableToolStepRoleAddress<TKey>[];
|
|
10
|
+
} | {
|
|
11
|
+
status: 'unresolved';
|
|
12
|
+
reason: 'not-found' | 'cycle' | 'depth-exceeded';
|
|
13
|
+
path: MutableToolStepRoleAddress<TKey>[];
|
|
14
|
+
};
|
|
15
|
+
export declare function resolveStrategyStateChain<TKey extends string, TStrategyState extends MutableStrategyState<TKey>>(strategyState: TStrategyState, start: MutableToolStepRoleAddress<TKey>, opts?: {
|
|
16
|
+
maxDepth?: number;
|
|
17
|
+
}): ResolveResult<TKey>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getStrategyStateInputEntry } from './mutableStrategyOverlay.js';
|
|
2
|
+
export function resolveStrategyStateChain(strategyState, start, opts) {
|
|
3
|
+
const maxDepth = opts?.maxDepth ?? 50;
|
|
4
|
+
const visited = new Set();
|
|
5
|
+
const path = [];
|
|
6
|
+
let current = start;
|
|
7
|
+
for (let depth = 0; depth <= maxDepth; depth++) {
|
|
8
|
+
path.push(current);
|
|
9
|
+
const visitKey = `${current.toolStepKey}::${current.roleName}`;
|
|
10
|
+
if (visited.has(visitKey)) {
|
|
11
|
+
return { status: 'unresolved', reason: 'cycle', path };
|
|
12
|
+
}
|
|
13
|
+
visited.add(visitKey);
|
|
14
|
+
const entry = getStrategyStateInputEntry(strategyState, current);
|
|
15
|
+
if (!entry) {
|
|
16
|
+
return { status: 'unresolved', reason: 'not-found', path };
|
|
17
|
+
}
|
|
18
|
+
if (entry.strategyStateInputKind === 'inputResource') {
|
|
19
|
+
return { status: 'inputResource', entry, path };
|
|
20
|
+
}
|
|
21
|
+
if (entry.strategyStateInputKind === 'externalInputPotential') {
|
|
22
|
+
return { status: 'externalInputPotential', entry, path };
|
|
23
|
+
}
|
|
24
|
+
current = entry.toolStepRoleAddress;
|
|
25
|
+
}
|
|
26
|
+
return { status: 'unresolved', reason: 'depth-exceeded', path };
|
|
27
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { MutableStrategy, MutableStep, MutableStrategyState, MutableToolStepKey } from './mutableStrategyOverlay.js';
|
|
2
|
+
export declare function toExecutionMutableStrategy<TKey extends string = MutableToolStepKey, TStep extends MutableStep<TKey> = MutableStep<TKey>, TState extends MutableStrategyState<TKey> = MutableStrategyState<TKey>>(mutableStrategy: MutableStrategy<TKey, TStep, TState>): MutableStrategy<TKey, TStep, TState>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getIndependentThreads } from './stepParallelization.js';
|
|
2
|
+
import { getAuthoringSteps as getAuthoringThreadSteps } from './mutableStrategyOverlay.js';
|
|
3
|
+
export function toExecutionMutableStrategy(mutableStrategy) {
|
|
4
|
+
const authoringSteps = getAuthoringThreadSteps(mutableStrategy);
|
|
5
|
+
const stepsByThreadIndex = getIndependentThreads(authoringSteps, mutableStrategy.strategyState);
|
|
6
|
+
return {
|
|
7
|
+
...mutableStrategy,
|
|
8
|
+
stepsByThreadIndex: stepsByThreadIndex,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function getToolStepPathSuffix(spec) {
|
|
2
|
+
if (spec.toolStepPathSlot === 'self') {
|
|
3
|
+
return '/self';
|
|
4
|
+
}
|
|
5
|
+
if (spec.toolStepPathSlot === 'cases/when' || spec.toolStepPathSlot === 'cases/what') {
|
|
6
|
+
if (typeof spec.caseIndex !== 'number') {
|
|
7
|
+
throw new Error('Expected caseIndex for branch tool-step path construction');
|
|
8
|
+
}
|
|
9
|
+
return `/cases/${spec.caseIndex}/${spec.toolStepPathSlot === 'cases/when' ? 'when' : 'what'}`;
|
|
10
|
+
}
|
|
11
|
+
if (spec.toolStepPathSlot === 'case/when') {
|
|
12
|
+
return '/case/when';
|
|
13
|
+
}
|
|
14
|
+
if (spec.toolStepPathSlot === 'case/what') {
|
|
15
|
+
return '/case/what';
|
|
16
|
+
}
|
|
17
|
+
throw new Error(`Unsupported tool-step path slot '${String(spec.toolStepPathSlot)}'`);
|
|
18
|
+
}
|
|
19
|
+
export function toToolStepPath(spec) {
|
|
20
|
+
return `/threads/${spec.threadIndex}/steps/${spec.stepIndex}${getToolStepPathSuffix(spec)}`;
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,43 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toolproof-core/lib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.37",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [],
|
|
7
7
|
"author": "",
|
|
8
8
|
"license": "ISC",
|
|
9
9
|
"exports": {
|
|
10
|
-
"./
|
|
11
|
-
"types": "./dist/
|
|
12
|
-
"import": "./dist/
|
|
10
|
+
"./lookups": {
|
|
11
|
+
"types": "./dist/lookups/lookups.d.ts",
|
|
12
|
+
"import": "./dist/lookups/lookups.js"
|
|
13
13
|
},
|
|
14
14
|
"./types": {
|
|
15
15
|
"types": "./dist/types/types.d.ts",
|
|
16
16
|
"import": "./dist/types/types.js"
|
|
17
17
|
},
|
|
18
|
-
"./
|
|
19
|
-
"types": "./dist/utils/
|
|
20
|
-
"import": "./dist/utils/
|
|
18
|
+
"./identifier-generation": {
|
|
19
|
+
"types": "./dist/utils/identifierGeneration.d.ts",
|
|
20
|
+
"import": "./dist/utils/identifierGeneration.js"
|
|
21
21
|
},
|
|
22
|
-
"./
|
|
23
|
-
"types": "./dist/utils/
|
|
24
|
-
"import": "./dist/utils/
|
|
22
|
+
"./strategy-assembly": {
|
|
23
|
+
"types": "./dist/utils/strategyAssembly.d.ts",
|
|
24
|
+
"import": "./dist/utils/strategyAssembly.js"
|
|
25
25
|
},
|
|
26
|
-
"./
|
|
27
|
-
"types": "./dist/
|
|
28
|
-
"import": "./dist/
|
|
26
|
+
"./cosmos-data-extraction": {
|
|
27
|
+
"types": "./dist/utils/cosmosDataExtraction.d.ts",
|
|
28
|
+
"import": "./dist/utils/cosmosDataExtraction.js"
|
|
29
29
|
},
|
|
30
|
-
"./
|
|
31
|
-
"types": "./dist/
|
|
32
|
-
"import": "./dist/
|
|
30
|
+
"./strategy-extraction": {
|
|
31
|
+
"types": "./dist/utils/strategyExtraction.d.ts",
|
|
32
|
+
"import": "./dist/utils/strategyExtraction.js"
|
|
33
33
|
},
|
|
34
|
-
"./
|
|
35
|
-
"types": "./dist/utils/
|
|
36
|
-
"import": "./dist/utils/
|
|
34
|
+
"./resource-creation": {
|
|
35
|
+
"types": "./dist/utils/resourceCreation.d.ts",
|
|
36
|
+
"import": "./dist/utils/resourceCreation.js"
|
|
37
37
|
},
|
|
38
|
-
"./
|
|
39
|
-
"types": "./dist/utils/
|
|
40
|
-
"import": "./dist/utils/
|
|
38
|
+
"./step-creation": {
|
|
39
|
+
"types": "./dist/utils/stepCreation.d.ts",
|
|
40
|
+
"import": "./dist/utils/stepCreation.js"
|
|
41
|
+
},
|
|
42
|
+
"./tool-step-paths": {
|
|
43
|
+
"types": "./dist/utils/toolStepPaths.d.ts",
|
|
44
|
+
"import": "./dist/utils/toolStepPaths.js"
|
|
45
|
+
},
|
|
46
|
+
"./strategy-state-resolution": {
|
|
47
|
+
"types": "./dist/utils/strategyStateResolution.d.ts",
|
|
48
|
+
"import": "./dist/utils/strategyStateResolution.js"
|
|
49
|
+
},
|
|
50
|
+
"./mutable-strategy-overlay": {
|
|
51
|
+
"types": "./dist/utils/mutableStrategyOverlay.d.ts",
|
|
52
|
+
"import": "./dist/utils/mutableStrategyOverlay.js"
|
|
53
|
+
},
|
|
54
|
+
"./strategy-threading": {
|
|
55
|
+
"types": "./dist/utils/strategyThreading.d.ts",
|
|
56
|
+
"import": "./dist/utils/strategyThreading.js"
|
|
57
|
+
},
|
|
58
|
+
"./strategy-canonicalization": {
|
|
59
|
+
"types": "./dist/utils/strategyCanonicalization.d.ts",
|
|
60
|
+
"import": "./dist/utils/strategyCanonicalization.js"
|
|
41
61
|
},
|
|
42
62
|
"./firebase-admin-init": {
|
|
43
63
|
"types": "./dist/integrations/firebase/firebaseAdminInit.d.ts",
|
|
@@ -52,7 +72,7 @@
|
|
|
52
72
|
"@types/node": "^22.0.0"
|
|
53
73
|
},
|
|
54
74
|
"dependencies": {
|
|
55
|
-
"@toolproof-core/
|
|
75
|
+
"@toolproof-core/genesis": "^1.0.58",
|
|
56
76
|
"firebase-admin": "^13.7.0"
|
|
57
77
|
},
|
|
58
78
|
"scripts": {
|
|
@@ -1,203 +1,80 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
CreationContext,
|
|
3
2
|
Resource,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from '@toolproof-core/
|
|
3
|
+
ResourcePointer,
|
|
4
|
+
ResourceTypeHandle,
|
|
5
|
+
TimestampedResource,
|
|
6
|
+
} from '@toolproof-core/genesis';
|
|
8
7
|
import type {
|
|
9
|
-
IdName,
|
|
10
|
-
IdStringByIdName,
|
|
11
8
|
ResourcesByType,
|
|
12
9
|
} from '../../types/types.js';
|
|
13
|
-
import { CONSTANTS
|
|
10
|
+
import { CONSTANTS } from '../../lookups/lookups.js';
|
|
14
11
|
import { dbAdmin, storageAdmin } from './firebaseAdminInit.js';
|
|
15
12
|
|
|
16
|
-
type StepIdStringByStepKind<K extends StepKind> = string & { readonly __stepKind?: K };
|
|
17
|
-
|
|
18
|
-
function capitalizeFirst(value: string): string {
|
|
19
|
-
if (!value) {
|
|
20
|
-
return value;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function getNewId<K extends IdName>(idName: K): IdStringByIdName<K> {
|
|
27
|
-
const prefix = MAPPINGS.IdNameToIdPrefix[idName];
|
|
28
|
-
const docRef = dbAdmin
|
|
29
|
-
.collection(CONSTANTS.Persistence.Collections.resources)
|
|
30
|
-
.doc(idName)
|
|
31
|
-
.collection(CONSTANTS.Persistence.Collections.members)
|
|
32
|
-
.doc();
|
|
33
|
-
|
|
34
|
-
return (prefix + docRef.id) as IdStringByIdName<K>;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function getNewStepId<K extends StepKind>(stepKind: K): StepIdStringByStepKind<K> {
|
|
38
|
-
const idName = `${capitalizeFirst(stepKind)}StepId` as IdName;
|
|
39
|
-
|
|
40
|
-
if (!(idName in MAPPINGS.IdNameToIdPrefix)) {
|
|
41
|
-
throw new Error(`No IdNameToIdPrefix entry for derived step id name: ${idName}`);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return getNewId(idName) as StepIdStringByStepKind<K>;
|
|
45
|
-
}
|
|
46
13
|
|
|
47
14
|
export async function listResources(
|
|
48
|
-
|
|
15
|
+
resourceTypeHandles: ResourceTypeHandle[],
|
|
49
16
|
): Promise<ResourcesByType> {
|
|
50
|
-
const
|
|
51
|
-
const
|
|
17
|
+
const resourcesBucket = storageAdmin.bucket(CONSTANTS.Persistence.Buckets.tp_resources);
|
|
18
|
+
const strategiesBucket = storageAdmin.bucket(CONSTANTS.Persistence.Buckets.tp_strategies);
|
|
19
|
+
|
|
20
|
+
async function fetchTimestampedMetadataUnder(
|
|
21
|
+
resourceTypeHandle: ResourceTypeHandle,
|
|
22
|
+
): Promise<ResourcePointer[]> {
|
|
23
|
+
const snapshot = await dbAdmin
|
|
24
|
+
.collection(CONSTANTS.Persistence.Collections.resources)
|
|
25
|
+
.doc(resourceTypeHandle)
|
|
26
|
+
.collection(CONSTANTS.Persistence.Collections.members)
|
|
27
|
+
.get();
|
|
28
|
+
|
|
29
|
+
return snapshot.docs.map((doc) => {
|
|
30
|
+
const data = doc.data() as Partial<TimestampedResource>;
|
|
31
|
+
if (
|
|
32
|
+
typeof data.id !== 'string' ||
|
|
33
|
+
typeof data.resourceTypeHandle !== 'string' ||
|
|
34
|
+
!data.provenance ||
|
|
35
|
+
typeof data.provenance !== 'object' ||
|
|
36
|
+
typeof data.provenance.provenanceKind !== 'string'
|
|
37
|
+
) {
|
|
38
|
+
throw new Error(`Invalid TimestampedResource document for ${resourceTypeHandle}/${doc.id}`);
|
|
39
|
+
}
|
|
52
40
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
: bucketResources;
|
|
59
|
-
const prefix = `${resourceTypeId}/`;
|
|
60
|
-
const [found] = await bucket.getFiles({ prefix });
|
|
61
|
-
const files = found.filter((file) => {
|
|
62
|
-
const name = file.name || '';
|
|
63
|
-
return !!name && !name.endsWith('/');
|
|
41
|
+
return {
|
|
42
|
+
id: data.id,
|
|
43
|
+
resourceTypeHandle: data.resourceTypeHandle,
|
|
44
|
+
provenance: data.provenance,
|
|
45
|
+
} as ResourcePointer;
|
|
64
46
|
});
|
|
47
|
+
}
|
|
65
48
|
|
|
66
|
-
|
|
67
|
-
|
|
49
|
+
async function fetchProjection(
|
|
50
|
+
resourceTypeHandle: ResourceTypeHandle,
|
|
51
|
+
resourceId: ResourcePointer['id'],
|
|
52
|
+
): Promise<unknown> {
|
|
53
|
+
const bucket = resourceTypeHandle === CONSTANTS.Handles.ResourceTypes.TYPE_Strategy
|
|
54
|
+
? strategiesBucket
|
|
55
|
+
: resourcesBucket;
|
|
56
|
+
const file = bucket.file(`${resourceTypeHandle}/${resourceId}`);
|
|
57
|
+
const [exists] = await file.exists();
|
|
58
|
+
if (!exists) {
|
|
59
|
+
throw new Error(`Missing projection blob for ${resourceTypeHandle}/${resourceId}`);
|
|
68
60
|
}
|
|
69
61
|
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
const [buf] = await file.download();
|
|
73
|
-
const meta = file.metadata || (await file.getMetadata())[0];
|
|
74
|
-
const data = JSON.parse(buf.toString('utf8')) as unknown;
|
|
75
|
-
return { data, meta, name: file.name };
|
|
76
|
-
} catch {
|
|
77
|
-
return null as unknown as { data: unknown; meta: any; name: string };
|
|
78
|
-
}
|
|
79
|
-
}));
|
|
80
|
-
|
|
81
|
-
return items.filter(Boolean) as Array<{ data: unknown; meta: any; name: string }>;
|
|
62
|
+
const [buf] = await file.download();
|
|
63
|
+
return JSON.parse(buf.toString('utf8')) as unknown;
|
|
82
64
|
}
|
|
83
65
|
|
|
84
66
|
const entries = await Promise.all(
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
const items: Resource[] =
|
|
88
|
-
const
|
|
89
|
-
const root: any = {};
|
|
90
|
-
|
|
91
|
-
for (const [key, valueRaw] of Object.entries(flat)) {
|
|
92
|
-
if (typeof valueRaw !== 'string') {
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const valueString = valueRaw.trim();
|
|
97
|
-
let value: any = valueString;
|
|
98
|
-
|
|
99
|
-
if ((valueString.startsWith('{') && valueString.endsWith('}')) || (valueString.startsWith('[') && valueString.endsWith(']'))) {
|
|
100
|
-
try {
|
|
101
|
-
value = JSON.parse(valueString);
|
|
102
|
-
} catch {
|
|
103
|
-
value = valueString;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const segments = key.split('.');
|
|
108
|
-
let cursor = root;
|
|
109
|
-
|
|
110
|
-
for (const [index, segment] of segments.entries()) {
|
|
111
|
-
const arrIdxMatch = segment.match(/^(.*)\[(\d+)\]$/);
|
|
112
|
-
|
|
113
|
-
if (arrIdxMatch) {
|
|
114
|
-
const base = arrIdxMatch[1];
|
|
115
|
-
const idxStr = arrIdxMatch[2];
|
|
116
|
-
|
|
117
|
-
if (base === undefined || idxStr === undefined) {
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const idx = parseInt(idxStr, 10);
|
|
122
|
-
|
|
123
|
-
if (!cursor[base] || !Array.isArray(cursor[base])) {
|
|
124
|
-
cursor[base] = [];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
while (cursor[base].length <= idx) {
|
|
128
|
-
cursor[base].push(undefined);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (index === segments.length - 1) {
|
|
132
|
-
cursor[base][idx] = value;
|
|
133
|
-
} else {
|
|
134
|
-
if (!cursor[base][idx]) {
|
|
135
|
-
cursor[base][idx] = {};
|
|
136
|
-
}
|
|
137
|
-
cursor = cursor[base][idx];
|
|
138
|
-
}
|
|
139
|
-
} else {
|
|
140
|
-
if (index === segments.length - 1) {
|
|
141
|
-
cursor[segment] = value;
|
|
142
|
-
} else {
|
|
143
|
-
if (!cursor[segment] || typeof cursor[segment] !== 'object') {
|
|
144
|
-
cursor[segment] = {};
|
|
145
|
-
}
|
|
146
|
-
cursor = cursor[segment];
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const id = root.id;
|
|
153
|
-
const provenance = root.provenance as ResourceProvenance | undefined;
|
|
154
|
-
const versionRaw = root.version;
|
|
155
|
-
const version = typeof versionRaw === 'number'
|
|
156
|
-
? versionRaw
|
|
157
|
-
: parseInt(String(versionRaw ?? ''), 10);
|
|
158
|
-
const resourcePath = root.path;
|
|
159
|
-
const timestamp = root.timestamp;
|
|
160
|
-
|
|
161
|
-
const missing = [
|
|
162
|
-
['id', id],
|
|
163
|
-
['version', Number.isFinite(version) ? String(version) : ''],
|
|
164
|
-
['timestamp', timestamp],
|
|
165
|
-
['path', resourcePath],
|
|
166
|
-
].filter(([_, value]) => typeof value !== 'string' || (value as string).length === 0) as Array<[string, string | undefined]>;
|
|
167
|
-
|
|
168
|
-
if (missing.length) {
|
|
169
|
-
const keys = missing.map(([key]) => key).join(', ');
|
|
170
|
-
throw new Error(`Missing required metadata keys [${keys}] for resource file: ${name}`);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (!provenance || typeof provenance !== 'object' || typeof provenance.resourceProvenanceKind !== 'string') {
|
|
174
|
-
throw new Error(`Missing required metadata key [provenance] for resource file: ${name}`);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (provenance.resourceProvenanceKind === 'strategy') {
|
|
178
|
-
const creationContext = (provenance as { creationContext?: CreationContext }).creationContext;
|
|
179
|
-
if (
|
|
180
|
-
!creationContext ||
|
|
181
|
-
typeof creationContext !== 'object' ||
|
|
182
|
-
typeof creationContext.roleName !== 'string' ||
|
|
183
|
-
typeof creationContext.toolStepPath !== 'string'
|
|
184
|
-
) {
|
|
185
|
-
throw new Error(`Missing required strategy provenance creationContext for resource file: ${name}`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
67
|
+
resourceTypeHandles.map(async (resourceTypeHandle) => {
|
|
68
|
+
const pointers = await fetchTimestampedMetadataUnder(resourceTypeHandle);
|
|
69
|
+
const items: Resource[] = await Promise.all(pointers.map(async (resourcePointer) => {
|
|
70
|
+
const projection = await fetchProjection(resourceTypeHandle, resourcePointer.id);
|
|
189
71
|
return {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
timestamp: timestamp as string,
|
|
195
|
-
path: resourcePath as string,
|
|
196
|
-
nucleus: data as any,
|
|
197
|
-
} as unknown as Resource;
|
|
198
|
-
});
|
|
72
|
+
...resourcePointer,
|
|
73
|
+
projection,
|
|
74
|
+
};
|
|
75
|
+
}));
|
|
199
76
|
|
|
200
|
-
return [
|
|
77
|
+
return [resourceTypeHandle, items] as const;
|
|
201
78
|
}),
|
|
202
79
|
);
|
|
203
80
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CONSTANTS as _CONSTANTS, MAPPINGS as _MAPPINGS } from '@toolproof-core/genesis';
|
|
2
|
+
|
|
3
|
+
export const CONSTANTS = {
|
|
4
|
+
..._CONSTANTS,
|
|
5
|
+
Persistence: {
|
|
6
|
+
Buckets: {
|
|
7
|
+
tp_resources: 'tp-resources' as const,
|
|
8
|
+
tp_strategies: 'tp-strategies' as const,
|
|
9
|
+
},
|
|
10
|
+
Collections: {
|
|
11
|
+
resources: 'resources' as const,
|
|
12
|
+
members: 'members' as const,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
Engine: {
|
|
16
|
+
Graphs: {
|
|
17
|
+
GraphRunStrategy: 'GraphRunStrategy' as const,
|
|
18
|
+
GraphBuildStrategy: 'GraphBuildStrategy' as const,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
Cosmos: {
|
|
22
|
+
ErrorOutputRoleName: 'ErrorOutput' as const,
|
|
23
|
+
}
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
26
|
+
export const MAPPINGS = {
|
|
27
|
+
..._MAPPINGS,
|
|
28
|
+
IdentifierNameToPrefix: {
|
|
29
|
+
..._MAPPINGS.IdentifierNameToPrefix,
|
|
30
|
+
ToolStepKey: 'TOOL_STEP-',
|
|
31
|
+
BranchStepKey: 'BRANCH_STEP-',
|
|
32
|
+
WhileStepKey: 'WHILE_STEP-',
|
|
33
|
+
ForStepKey: 'FOR_STEP-',
|
|
34
|
+
},
|
|
35
|
+
} as const;
|
package/src/types/types.ts
CHANGED
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
StepKind,
|
|
3
2
|
Resource,
|
|
4
|
-
|
|
5
|
-
} from '@toolproof-core/
|
|
6
|
-
import { CONSTANTS } from '../
|
|
7
|
-
import { MAPPINGS } from '../
|
|
3
|
+
ResourceTypeHandle,
|
|
4
|
+
} from '@toolproof-core/genesis/types';
|
|
5
|
+
import { CONSTANTS } from '../lookups/lookups.js';
|
|
6
|
+
import { MAPPINGS } from '../lookups/lookups.js';
|
|
8
7
|
|
|
9
|
-
export type Bucket = typeof CONSTANTS.Persistence.Buckets
|
|
8
|
+
export type Bucket = keyof typeof CONSTANTS.Persistence.Buckets;
|
|
10
9
|
|
|
11
10
|
export type Collection = keyof typeof CONSTANTS.Persistence.Collections;
|
|
12
11
|
|
|
13
12
|
export type SchemaLike = Record<string, unknown>;
|
|
14
13
|
|
|
15
|
-
export type ResourcesByType = Record<
|
|
14
|
+
export type ResourcesByType = Record<ResourceTypeHandle, Resource[]>;
|
|
16
15
|
|
|
17
|
-
export type
|
|
16
|
+
export type IdentifierName = keyof typeof MAPPINGS.IdentifierNameToPrefix;
|
|
18
17
|
|
|
19
|
-
export type
|
|
18
|
+
export type IdentifierStringByName<K extends IdentifierName> = `${(typeof MAPPINGS.IdentifierNameToPrefix)[K]}${string}`;
|
|
20
19
|
|
|
21
|
-
export type
|
|
20
|
+
export type ItemKey = string;
|
|
22
21
|
|
|
23
|
-
export
|
|
24
|
-
|
|
22
|
+
export type BaseItem = {
|
|
23
|
+
itemKey: ItemKey;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
export
|
|
26
|
+
export type DocumentedBaseItem = BaseItem & { // ATTENTION: reuse ontology concept
|
|
28
27
|
name: string;
|
|
29
28
|
description: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type Item = DocumentedBaseItem & {
|
|
32
|
+
label: string;
|
|
30
33
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Resource, TimestampedResource } from '@toolproof-core/genesis';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export function timestampedResourceToResource(timestampedResource: TimestampedResource): Resource {
|
|
5
|
+
const { timestamp: _timestamp, ...resource } = timestampedResource;
|
|
6
|
+
return resource;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function extractProjectionMapByHandle<TKey extends string, TProjection extends { handle: TKey }>(
|
|
10
|
+
resources: Resource[] | undefined,
|
|
11
|
+
): Map<TKey, TProjection> {
|
|
12
|
+
const map = new Map<TKey, TProjection>();
|
|
13
|
+
|
|
14
|
+
for (const resource of resources ?? []) {
|
|
15
|
+
const projection = resource.projection as (TProjection & { handle?: TKey }) | null;
|
|
16
|
+
|
|
17
|
+
if (!projection || typeof projection !== 'object' || !projection.handle) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
map.set(projection.handle, projection);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return map;
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
IdentifierName,
|
|
3
|
+
IdentifierStringByName,
|
|
4
|
+
} from '../types/types.js';
|
|
5
|
+
import { MAPPINGS } from '../lookups/lookups.js';
|
|
6
|
+
|
|
7
|
+
export function generateIdentifier<K extends IdentifierName>(identifierName: K): IdentifierStringByName<K> {
|
|
8
|
+
const prefix = MAPPINGS.IdentifierNameToPrefix[identifierName];
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
return (prefix + crypto.randomUUID()) as IdentifierStringByName<K>;
|
|
12
|
+
}
|