@exellix/graphs-studio-data-flow 0.1.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 +33 -0
- package/src/graphContractMetadata.js +484 -0
- package/src/index.js +8 -0
- package/src/informationFlow.js +225 -0
- package/src/informationFlowFocus.js +332 -0
- package/src/informationFlowLayerDocument.js +69 -0
- package/src/informationFlowOutputSurface.js +339 -0
- package/src/ioLinking.js +236 -0
- package/src/lib/flatRuntimeInput.js +38 -0
- package/src/lib/memorixEntityContentTypes.js +116 -0
- package/src/lib/memorixScopedConfig.js +108 -0
- package/src/lib/nodeMetadataAccessors.js +59 -0
- package/src/lib/recordEligibilityRules.js +542 -0
- package/src/lib/recordFiltersJsonConditionsBridge.js +97 -0
- package/src/lib/taskNodeConfiguration.js +117 -0
- package/src/lib/webQueryTemplate.js +277 -0
- package/src/pathClassification.js +133 -0
- package/src/planning.js +3 -0
- package/src/planningSourceFamily.js +109 -0
- package/src/types.ts +246 -0
- package/src/webScopingPlanning.js +131 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memorix entity **content types** for graph entry (`metadata.graphEntry.inputs[].inputTypes`).
|
|
3
|
+
*
|
|
4
|
+
* Catalox catalog `memorix_entity_content_types` holds **metadata only** (labels, which XMemory
|
|
5
|
+
* op-tier to count via `data.countBinding`, optional `data.editorSlot`). Document counts for
|
|
6
|
+
* **Current records** come from Memorix / XMemory via `@exellix/exellix-runtime`, not from Catalox.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const MEMORIX_ENTITY_CONTENT_TYPES_CATALOG_ID = 'memorix_entity_content_types';
|
|
10
|
+
|
|
11
|
+
/** @type {Readonly<Record<string, string>>} Deprecated graph-entry ids → canonical `contentTypeKey`. */
|
|
12
|
+
export const DEPRECATED_GRAPH_ENTRY_INPUT_TYPE_IDS = Object.freeze({
|
|
13
|
+
snapshotsRecords: 'snapshots',
|
|
14
|
+
scoppedQuestions: 'scoping_questions',
|
|
15
|
+
eventTrigger: 'event_trigger',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {unknown} v
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
export function pickMemorixContentTypeStr(v) {
|
|
23
|
+
return typeof v === 'string' ? v.trim() : '';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} typeId
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
export function normalizeMemorixEntityContentTypeId(typeId) {
|
|
31
|
+
const id = pickMemorixContentTypeStr(typeId);
|
|
32
|
+
if (!id) return '';
|
|
33
|
+
return DEPRECATED_GRAPH_ENTRY_INPUT_TYPE_IDS[id] ?? id;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {unknown} rawTypes
|
|
38
|
+
* @returns {string[]|undefined}
|
|
39
|
+
*/
|
|
40
|
+
export function normalizeGraphEntryInputTypes(rawTypes) {
|
|
41
|
+
if (!Array.isArray(rawTypes)) return undefined;
|
|
42
|
+
const out = [];
|
|
43
|
+
const seen = new Set();
|
|
44
|
+
for (const t of rawTypes) {
|
|
45
|
+
const id = normalizeMemorixEntityContentTypeId(t);
|
|
46
|
+
if (!id || seen.has(id)) continue;
|
|
47
|
+
seen.add(id);
|
|
48
|
+
out.push(id);
|
|
49
|
+
}
|
|
50
|
+
return out.length ? out : undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {{ itemId?: string, data?: unknown }} row
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
export function memorixEntityContentTypeKeyFromRow(row) {
|
|
58
|
+
if (!row || typeof row !== 'object') return '';
|
|
59
|
+
const itemId = pickMemorixContentTypeStr(row.itemId);
|
|
60
|
+
const data =
|
|
61
|
+
row.data != null && typeof row.data === 'object' && !Array.isArray(row.data)
|
|
62
|
+
? /** @type {Record<string, unknown>} */ (row.data)
|
|
63
|
+
: {};
|
|
64
|
+
const fromData = pickMemorixContentTypeStr(data.contentTypeKey ?? data.key ?? data.slug);
|
|
65
|
+
return fromData || itemId;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {Array<{ itemId?: string, data?: unknown }>} catalogRows
|
|
70
|
+
* @param {string} typeId
|
|
71
|
+
* @returns {{ itemId?: string, data?: unknown } | null}
|
|
72
|
+
*/
|
|
73
|
+
export function findMemorixEntityContentTypeCatalogRow(catalogRows, typeId) {
|
|
74
|
+
const id = normalizeMemorixEntityContentTypeId(typeId);
|
|
75
|
+
if (!id || !Array.isArray(catalogRows)) return null;
|
|
76
|
+
for (const row of catalogRows) {
|
|
77
|
+
if (!row || typeof row !== 'object') continue;
|
|
78
|
+
const key = memorixEntityContentTypeKeyFromRow(row);
|
|
79
|
+
const itemId = pickMemorixContentTypeStr(row.itemId);
|
|
80
|
+
if (key === id || itemId === id) return row;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {Array<{ itemId?: string, data?: unknown }>} items
|
|
87
|
+
* @param {string} typeId
|
|
88
|
+
* @returns {{ countBinding: string, editorSlot: string | null } | null}
|
|
89
|
+
*/
|
|
90
|
+
export function memorixEntityContentTypeBindingFromCatalogItems(items, typeId) {
|
|
91
|
+
const id = normalizeMemorixEntityContentTypeId(typeId);
|
|
92
|
+
if (!id || !Array.isArray(items)) return null;
|
|
93
|
+
for (const it of items) {
|
|
94
|
+
if (!it || typeof it !== 'object') continue;
|
|
95
|
+
const row = /** @type {{ itemId?: string, data?: unknown }} */ (it);
|
|
96
|
+
const key = memorixEntityContentTypeKeyFromRow(row);
|
|
97
|
+
const itemId = pickMemorixContentTypeStr(row.itemId);
|
|
98
|
+
if (key !== id && itemId !== id) continue;
|
|
99
|
+
const data =
|
|
100
|
+
row.data != null && typeof row.data === 'object' && !Array.isArray(row.data)
|
|
101
|
+
? /** @type {Record<string, unknown>} */ (row.data)
|
|
102
|
+
: {};
|
|
103
|
+
const countBinding =
|
|
104
|
+
pickMemorixContentTypeStr(data.countBinding) || pickMemorixContentTypeStr(data.countTier);
|
|
105
|
+
const editorSlot = pickMemorixContentTypeStr(data.editorSlot) || null;
|
|
106
|
+
if (!countBinding) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
`Memorix entity content type "${id}" is missing data.countBinding in Catalox catalog ` +
|
|
109
|
+
`"${MEMORIX_ENTITY_CONTENT_TYPES_CATALOG_ID}". ` +
|
|
110
|
+
'Counts are loaded from Memorix (XMemory op-tier); Catalox only declares which tier to use.',
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return { countBinding, editorSlot };
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memorix descriptor helpers for scoped local skills — aligned with
|
|
3
|
+
* `@exellix/graph-engine` `memorixScopedConfig.ts` (graph-engine 6.x).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** @typedef {import('@exellix/graph-engine/dist/src/types/taskNodeConfiguration.js').TaskNodeTaskConfiguration} TaskNodeTaskConfiguration */
|
|
7
|
+
|
|
8
|
+
export const DEFAULT_SCOPED_CONTENT_TYPES = ['inferences', 'decisions'];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {TaskNodeTaskConfiguration | Record<string, unknown> | null | undefined} cfg
|
|
12
|
+
* @returns {string | undefined}
|
|
13
|
+
*/
|
|
14
|
+
export function resolveMemorixItemDescriptorId(cfg) {
|
|
15
|
+
if (!cfg || typeof cfg !== 'object') return undefined;
|
|
16
|
+
const memorix = typeof cfg.memorixItemDescriptorId === 'string' ? cfg.memorixItemDescriptorId.trim() : '';
|
|
17
|
+
if (memorix) return memorix;
|
|
18
|
+
const item = typeof cfg.itemDescriptorId === 'string' ? cfg.itemDescriptorId.trim() : '';
|
|
19
|
+
return item || undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {TaskNodeTaskConfiguration | Record<string, unknown> | null | undefined} cfg
|
|
24
|
+
* @param {string} contentType
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
27
|
+
export function resolveMemorixWriteDescriptorId(cfg, contentType) {
|
|
28
|
+
const base = cfg && typeof cfg === 'object' ? cfg : {};
|
|
29
|
+
const mapped = base.memorixWriteDescriptors?.[contentType];
|
|
30
|
+
if (typeof mapped === 'string' && mapped.trim()) return mapped.trim();
|
|
31
|
+
if (contentType === 'inferences' || contentType === 'decisions') {
|
|
32
|
+
const legacy =
|
|
33
|
+
(typeof base.memorixWriteDescriptorId === 'string' ? base.memorixWriteDescriptorId.trim() : '') ||
|
|
34
|
+
(typeof base.writeDescriptorId === 'string' ? base.writeDescriptorId.trim() : '');
|
|
35
|
+
if (legacy && contentType === 'inferences') return legacy;
|
|
36
|
+
}
|
|
37
|
+
return contentType;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Pure metadata + `taskConfiguration` execution bag (graph-engine 5.0+).
|
|
42
|
+
*
|
|
43
|
+
* @param {unknown} node
|
|
44
|
+
* @returns {Record<string, unknown>}
|
|
45
|
+
*/
|
|
46
|
+
export function nodeAuthoringBag(node) {
|
|
47
|
+
const n = /** @type {{ metadata?: unknown; taskConfiguration?: unknown }} */ (node);
|
|
48
|
+
const meta =
|
|
49
|
+
n?.metadata && typeof n.metadata === 'object' && !Array.isArray(n.metadata)
|
|
50
|
+
? /** @type {Record<string, unknown>} */ (n.metadata)
|
|
51
|
+
: {};
|
|
52
|
+
const tc =
|
|
53
|
+
n?.taskConfiguration && typeof n.taskConfiguration === 'object' && !Array.isArray(n.taskConfiguration)
|
|
54
|
+
? /** @type {Record<string, unknown>} */ (n.taskConfiguration)
|
|
55
|
+
: {};
|
|
56
|
+
return { ...meta, ...tc };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {unknown} node
|
|
61
|
+
* @returns {string | undefined}
|
|
62
|
+
*/
|
|
63
|
+
export function resolveMemorixItemDescriptorIdFromNode(node) {
|
|
64
|
+
return resolveMemorixItemDescriptorId(nodeAuthoringBag(node));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Collect unique Memorix item descriptor ids from scoped-data-reader nodes.
|
|
69
|
+
*
|
|
70
|
+
* @param {unknown} graph
|
|
71
|
+
* @returns {string[]}
|
|
72
|
+
*/
|
|
73
|
+
export function collectMemorixItemDescriptorIdsFromGraph(graph) {
|
|
74
|
+
/** @type {Set<string>} */
|
|
75
|
+
const ids = new Set();
|
|
76
|
+
const nodes = Array.isArray(graph?.nodes)
|
|
77
|
+
? graph.nodes
|
|
78
|
+
: graph?.nodes && typeof graph.nodes === 'object'
|
|
79
|
+
? Object.values(graph.nodes)
|
|
80
|
+
: [];
|
|
81
|
+
for (const node of nodes) {
|
|
82
|
+
if (!node || typeof node !== 'object') continue;
|
|
83
|
+
const sk = /** @type {{ skillKey?: string }} */ (node).skillKey;
|
|
84
|
+
if (sk !== 'scoped-data-reader') continue;
|
|
85
|
+
const bag = nodeAuthoringBag(node);
|
|
86
|
+
const id = resolveMemorixItemDescriptorId(bag);
|
|
87
|
+
if (id) ids.add(id);
|
|
88
|
+
const pack = bag.pack;
|
|
89
|
+
if (Array.isArray(pack)) {
|
|
90
|
+
for (const slot of pack) {
|
|
91
|
+
if (!slot || typeof slot !== 'object') continue;
|
|
92
|
+
const slotId = resolveMemorixItemDescriptorId(/** @type {Record<string, unknown>} */ (slot));
|
|
93
|
+
if (slotId) ids.add(slotId);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return [...ids].sort();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {unknown} node
|
|
102
|
+
* @returns {boolean}
|
|
103
|
+
*/
|
|
104
|
+
export function nodeUsesLegacyScopingMapId(node) {
|
|
105
|
+
const bag = nodeAuthoringBag(node);
|
|
106
|
+
const legacy = typeof bag.scopingMapId === 'string' ? bag.scopingMapId.trim() : '';
|
|
107
|
+
return !!legacy && !resolveMemorixItemDescriptorId(bag);
|
|
108
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical graph-engine 5.0+ readers for task execution fields on **`taskConfiguration`**.
|
|
3
|
+
*
|
|
4
|
+
* Legacy shapes (`metadata.aiTaskProfile`, …) are migrated on load by
|
|
5
|
+
* {@link migrateGraphDocumentTaskNodesForEngine5} and {@link migrateTaskNodeWebQueryTemplate}.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
readWebScoping,
|
|
10
|
+
readNodeWebScopingEnabled,
|
|
11
|
+
readNodeWebScopingQuestions,
|
|
12
|
+
readNodeWebQueryTemplate,
|
|
13
|
+
readNodeWebQueryTemplates,
|
|
14
|
+
readNodeWebScopeOptions,
|
|
15
|
+
readNodeWebScopeEnabled,
|
|
16
|
+
readNodeWebQueryStrings,
|
|
17
|
+
readAiTaskProfile,
|
|
18
|
+
patchWebQueryTemplateOnNode,
|
|
19
|
+
patchWebScopingOnNode,
|
|
20
|
+
migrateTaskNodeWebQueryTemplate,
|
|
21
|
+
} from './webQueryTemplate.js';
|
|
22
|
+
|
|
23
|
+
import { readTaskConfiguration } from './taskNodeConfiguration.js';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {unknown} node
|
|
27
|
+
* @returns {Record<string, unknown> | null}
|
|
28
|
+
*/
|
|
29
|
+
function readAiTaskProfileLocal(node) {
|
|
30
|
+
const tc = readTaskConfiguration(node);
|
|
31
|
+
if (!tc) return null;
|
|
32
|
+
const profile = tc.aiTaskProfile;
|
|
33
|
+
if (!profile || typeof profile !== 'object' || Array.isArray(profile)) return null;
|
|
34
|
+
return /** @type {Record<string, unknown>} */ (profile);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {unknown} node
|
|
39
|
+
* @returns {Record<string, unknown> | null}
|
|
40
|
+
*/
|
|
41
|
+
export function readInputSynthesis(node) {
|
|
42
|
+
const profile = readAiTaskProfileLocal(node);
|
|
43
|
+
if (!profile) return null;
|
|
44
|
+
const is = profile.inputSynthesis;
|
|
45
|
+
if (!is || typeof is !== 'object' || Array.isArray(is)) return null;
|
|
46
|
+
return /** @type {Record<string, unknown>} */ (is);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* PRE synthesized-context phase is active iff
|
|
51
|
+
* `taskConfiguration.aiTaskProfile.inputSynthesis.enabled === true`.
|
|
52
|
+
*
|
|
53
|
+
* @param {unknown} node
|
|
54
|
+
* @returns {boolean}
|
|
55
|
+
*/
|
|
56
|
+
export function readNodeInputSynthesisEnabled(node) {
|
|
57
|
+
const is = readInputSynthesis(node);
|
|
58
|
+
return is != null && is.enabled === true;
|
|
59
|
+
}
|