@telora/daemon 0.19.35 → 0.19.38
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/build-info.json +4 -3
- package/dist/queries/code-metrics.d.ts +4 -0
- package/dist/queries/code-metrics.d.ts.map +1 -1
- package/dist/queries/code-metrics.js.map +1 -1
- package/dist/resolvers/compose/focus-injections-compose.d.ts +61 -0
- package/dist/resolvers/compose/focus-injections-compose.d.ts.map +1 -0
- package/dist/resolvers/compose/focus-injections-compose.js +72 -0
- package/dist/resolvers/compose/focus-injections-compose.js.map +1 -0
- package/dist/resolvers/compose/loop-context-compose.d.ts +51 -0
- package/dist/resolvers/compose/loop-context-compose.d.ts.map +1 -0
- package/dist/resolvers/compose/loop-context-compose.js +66 -0
- package/dist/resolvers/compose/loop-context-compose.js.map +1 -0
- package/dist/resolvers/compose/loop-frt-statement-compose.d.ts +24 -0
- package/dist/resolvers/compose/loop-frt-statement-compose.d.ts.map +1 -0
- package/dist/resolvers/compose/loop-frt-statement-compose.js +30 -0
- package/dist/resolvers/compose/loop-frt-statement-compose.js.map +1 -0
- package/dist/resolvers/compose/loop-injection-compose.d.ts +30 -0
- package/dist/resolvers/compose/loop-injection-compose.d.ts.map +1 -0
- package/dist/resolvers/compose/loop-injection-compose.js +40 -0
- package/dist/resolvers/compose/loop-injection-compose.js.map +1 -0
- package/dist/resolvers/compose/loop-persona-compose.d.ts +24 -0
- package/dist/resolvers/compose/loop-persona-compose.d.ts.map +1 -0
- package/dist/resolvers/compose/loop-persona-compose.js +24 -0
- package/dist/resolvers/compose/loop-persona-compose.js.map +1 -0
- package/dist/resolvers/compose/loop-upstream-udes-compose.d.ts +44 -0
- package/dist/resolvers/compose/loop-upstream-udes-compose.d.ts.map +1 -0
- package/dist/resolvers/compose/loop-upstream-udes-compose.js +75 -0
- package/dist/resolvers/compose/loop-upstream-udes-compose.js.map +1 -0
- package/dist/resolvers/focus-injections.d.ts +4 -0
- package/dist/resolvers/focus-injections.d.ts.map +1 -1
- package/dist/resolvers/focus-injections.js +6 -50
- package/dist/resolvers/focus-injections.js.map +1 -1
- package/dist/resolvers/loop-context.d.ts +12 -9
- package/dist/resolvers/loop-context.d.ts.map +1 -1
- package/dist/resolvers/loop-context.js +87 -102
- package/dist/resolvers/loop-context.js.map +1 -1
- package/dist/resolvers/loop-frt-statement.d.ts +3 -0
- package/dist/resolvers/loop-frt-statement.d.ts.map +1 -1
- package/dist/resolvers/loop-frt-statement.js +7 -8
- package/dist/resolvers/loop-frt-statement.js.map +1 -1
- package/dist/resolvers/loop-injection.d.ts +4 -0
- package/dist/resolvers/loop-injection.d.ts.map +1 -1
- package/dist/resolvers/loop-injection.js +8 -18
- package/dist/resolvers/loop-injection.js.map +1 -1
- package/dist/resolvers/loop-persona.d.ts.map +1 -1
- package/dist/resolvers/loop-persona.js +2 -3
- package/dist/resolvers/loop-persona.js.map +1 -1
- package/dist/resolvers/loop-upstream-udes.d.ts +5 -0
- package/dist/resolvers/loop-upstream-udes.d.ts.map +1 -1
- package/dist/resolvers/loop-upstream-udes.js +14 -51
- package/dist/resolvers/loop-upstream-udes.js.map +1 -1
- package/dist/sensor-sweep.d.ts +58 -6
- package/dist/sensor-sweep.d.ts.map +1 -1
- package/dist/sensor-sweep.js +95 -9
- package/dist/sensor-sweep.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED FILE -- DO NOT EDIT.
|
|
3
|
+
*
|
|
4
|
+
* Deno edge-function copy of src/lib/context-assembly/resolvers/loop-upstream-udes-compose.ts, produced by
|
|
5
|
+
* `npm run gen:shared-mirrors`. The canonical source is the ONLY hand-edited
|
|
6
|
+
* copy of this algorithm; edit it there and regenerate. The drift gate
|
|
7
|
+
* (`npm run lint:shared-mirrors`) fails CI when this file differs from what
|
|
8
|
+
* generation would produce, so the same algorithm runs in both runtimes.
|
|
9
|
+
*
|
|
10
|
+
* @module resolvers/compose/loop-upstream-udes-compose
|
|
11
|
+
*/
|
|
12
|
+
/** The assembly source-reference this module composes. */
|
|
13
|
+
export const REF = 'loop.upstream_udes';
|
|
14
|
+
/** Maximum BFS depth for the upstream UDE walk. */
|
|
15
|
+
export const MAX_UPSTREAM_DEPTH = 3;
|
|
16
|
+
/**
|
|
17
|
+
* For each delivery's injection, seed from the nodes it targets (via 'targets'
|
|
18
|
+
* edges) and BFS upstream along causal edges ('sufficient' and 'and') up to
|
|
19
|
+
* MAX_UPSTREAM_DEPTH hops, returning a markdown list of the upstream UDE/entity
|
|
20
|
+
* nodes the injection indirectly addresses. Cycle-safe; seeds excluded from
|
|
21
|
+
* output. Returns '' when nothing upstream is found.
|
|
22
|
+
*/
|
|
23
|
+
export function composeLoopUpstreamUdes(entries) {
|
|
24
|
+
const sections = [];
|
|
25
|
+
for (const { deliveryName, injectionId, nodes, edges } of entries) {
|
|
26
|
+
const nodeById = new Map();
|
|
27
|
+
for (const n of nodes)
|
|
28
|
+
nodeById.set(n.id, n);
|
|
29
|
+
// Seed: the nodes the injection targets directly.
|
|
30
|
+
const seeds = edges
|
|
31
|
+
.filter((e) => e.edgeType === 'targets' && e.fromNodeId === injectionId)
|
|
32
|
+
.map((e) => e.toNodeId);
|
|
33
|
+
if (seeds.length === 0)
|
|
34
|
+
continue;
|
|
35
|
+
// BFS upstream along causal edges: walk edges where to_node_id is in the
|
|
36
|
+
// current frontier; the from_node_id of those edges is the upstream node.
|
|
37
|
+
// Bounded by MAX_UPSTREAM_DEPTH and cycle-safe via visited set. Seeds
|
|
38
|
+
// themselves are excluded from output (we want their upstream, not the seeds).
|
|
39
|
+
const visited = new Set(seeds);
|
|
40
|
+
const collected = [];
|
|
41
|
+
let frontier = new Set(seeds);
|
|
42
|
+
for (let depth = 0; depth < MAX_UPSTREAM_DEPTH; depth++) {
|
|
43
|
+
if (frontier.size === 0)
|
|
44
|
+
break;
|
|
45
|
+
const next = new Set();
|
|
46
|
+
for (const edge of edges) {
|
|
47
|
+
if (edge.edgeType !== 'sufficient' && edge.edgeType !== 'and')
|
|
48
|
+
continue;
|
|
49
|
+
if (!frontier.has(edge.toNodeId))
|
|
50
|
+
continue;
|
|
51
|
+
const upId = edge.fromNodeId;
|
|
52
|
+
if (visited.has(upId))
|
|
53
|
+
continue;
|
|
54
|
+
visited.add(upId);
|
|
55
|
+
next.add(upId);
|
|
56
|
+
const upNode = nodeById.get(upId);
|
|
57
|
+
if (upNode)
|
|
58
|
+
collected.push(upNode);
|
|
59
|
+
}
|
|
60
|
+
frontier = next;
|
|
61
|
+
}
|
|
62
|
+
if (collected.length === 0)
|
|
63
|
+
continue;
|
|
64
|
+
collected.sort((a, b) => a.seq - b.seq);
|
|
65
|
+
const lines = collected.map((n) => {
|
|
66
|
+
const typeTag = n.nodeType !== 'entity' ? ` [${n.nodeType}]` : '';
|
|
67
|
+
return `- #${n.seq} ${n.statement}${typeTag}`;
|
|
68
|
+
});
|
|
69
|
+
sections.push(`### ${deliveryName}\n\n${lines.join('\n')}`);
|
|
70
|
+
}
|
|
71
|
+
if (sections.length === 0)
|
|
72
|
+
return '';
|
|
73
|
+
return `## Upstream UDEs (per delivery, max depth ${MAX_UPSTREAM_DEPTH})\n\n${sections.join('\n\n')}`;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=loop-upstream-udes-compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop-upstream-udes-compose.js","sourceRoot":"","sources":["../../../src/resolvers/compose/loop-upstream-udes-compose.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
* deliveries; shared-target collisions to avoid two workers changing the same
|
|
9
9
|
* node; and the root-cause clusters. Per-delivery full differentials are pulled
|
|
10
10
|
* on demand via telora_reality_tree_injection_context(seq).
|
|
11
|
+
*
|
|
12
|
+
* THIN FETCH HALF: this resolver only fetches (callApi) the coordination-map
|
|
13
|
+
* data; the markdown is composed by the shared, drift-mirrored
|
|
14
|
+
* `composeFocusInjections` so the inspector's preview renders identically.
|
|
11
15
|
*/
|
|
12
16
|
/** Register this module's resolver(s). Called from initResolvers() -- not an import side effect. */
|
|
13
17
|
export declare function registerFocusInjectionsResolver(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus-injections.d.ts","sourceRoot":"","sources":["../../src/resolvers/focus-injections.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"focus-injections.d.ts","sourceRoot":"","sources":["../../src/resolvers/focus-injections.ts"],"names":[],"mappings":"AA+CA;;;;;;;;;;;;;;GAcG;AACH,oGAAoG;AACpG,wBAAgB,+BAA+B,IAAI,IAAI,CAYtD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { registerSourceResolver } from '../assembly-engine.js';
|
|
2
2
|
import { callApi } from '../queries/shared.js';
|
|
3
|
+
import { composeFocusInjections } from './compose/focus-injections-compose.js';
|
|
3
4
|
/**
|
|
4
5
|
* focus.injections
|
|
5
6
|
*
|
|
@@ -10,6 +11,10 @@ import { callApi } from '../queries/shared.js';
|
|
|
10
11
|
* deliveries; shared-target collisions to avoid two workers changing the same
|
|
11
12
|
* node; and the root-cause clusters. Per-delivery full differentials are pulled
|
|
12
13
|
* on demand via telora_reality_tree_injection_context(seq).
|
|
14
|
+
*
|
|
15
|
+
* THIN FETCH HALF: this resolver only fetches (callApi) the coordination-map
|
|
16
|
+
* data; the markdown is composed by the shared, drift-mirrored
|
|
17
|
+
* `composeFocusInjections` so the inspector's preview renders identically.
|
|
13
18
|
*/
|
|
14
19
|
/** Register this module's resolver(s). Called from initResolvers() -- not an import side effect. */
|
|
15
20
|
export function registerFocusInjectionsResolver() {
|
|
@@ -18,56 +23,7 @@ export function registerFocusInjectionsResolver() {
|
|
|
18
23
|
const result = await callApi('reality_tree_focus_injections', {
|
|
19
24
|
focusId: context.focusId,
|
|
20
25
|
});
|
|
21
|
-
|
|
22
|
-
return '';
|
|
23
|
-
const structure = result.structure ?? {
|
|
24
|
-
dependencyOrder: [],
|
|
25
|
-
sharedTargetCollisions: [],
|
|
26
|
-
rootCauseClusters: [],
|
|
27
|
-
};
|
|
28
|
-
const lines = [
|
|
29
|
-
'## Focus Coordination Map',
|
|
30
|
-
'',
|
|
31
|
-
'The focus reality-tree structure -- your planning surface. Each injection moves a',
|
|
32
|
-
'Now (a current UDE) to a Target (its future desired effect). Use the dependency',
|
|
33
|
-
'order to sequence deliveries, the collisions to avoid two workers changing the same',
|
|
34
|
-
'node, and the clusters to see which root causes drive which problems. Pull a',
|
|
35
|
-
"delivery's full differential on demand with telora_reality_tree_injection_context",
|
|
36
|
-
'(by injection seq).',
|
|
37
|
-
'',
|
|
38
|
-
'### Injections (Now -> Target)',
|
|
39
|
-
'',
|
|
40
|
-
];
|
|
41
|
-
for (const item of result.items) {
|
|
42
|
-
const inj = item.injection;
|
|
43
|
-
const statusTag = inj.injectionStatus ? ` [${inj.injectionStatus}]` : '';
|
|
44
|
-
lines.push(`- #${inj.seq} ${inj.statement}${statusTag}`);
|
|
45
|
-
for (const nt of item.nowTargets ?? []) {
|
|
46
|
-
const target = nt.target && nt.target.trim().length > 0 ? nt.target : '(no FRT overlay yet)';
|
|
47
|
-
lines.push(` - Now: #${nt.seq} ${nt.now} -> Target: ${target}`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
if (structure.dependencyOrder.length > 0) {
|
|
51
|
-
lines.push('', '### Dependency Order (sequence deliveries this way)', '');
|
|
52
|
-
structure.dependencyOrder.forEach((d, i) => {
|
|
53
|
-
lines.push(`${i + 1}. #${d.seq} ${d.statement}`);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
if (structure.sharedTargetCollisions.length > 0) {
|
|
57
|
-
lines.push('', '### Shared-Target Collisions (avoid two workers changing the same node)', '');
|
|
58
|
-
for (const c of structure.sharedTargetCollisions) {
|
|
59
|
-
const injList = c.injectionSeqs.map((s) => `#${s}`).join(', ');
|
|
60
|
-
lines.push(`- #${c.targetSeq} "${c.targetStatement}" <- injections ${injList}`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (structure.rootCauseClusters.length > 0) {
|
|
64
|
-
lines.push('', '### Root-Cause Clusters (which roots drive which UDEs)', '');
|
|
65
|
-
for (const cl of structure.rootCauseClusters) {
|
|
66
|
-
const udeList = cl.udeSeqs.map((s) => `#${s}`).join(', ');
|
|
67
|
-
lines.push(`- #${cl.rootSeq} ${cl.rootStatement} (${cl.rootNodeType}) drives UDEs: ${udeList}`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return lines.join('\n');
|
|
26
|
+
return composeFocusInjections(result);
|
|
71
27
|
}
|
|
72
28
|
catch (err) {
|
|
73
29
|
console.warn(`[assembly-engine] focus.injections: failed: ${err.message}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus-injections.js","sourceRoot":"","sources":["../../src/resolvers/focus-injections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"focus-injections.js","sourceRoot":"","sources":["../../src/resolvers/focus-injections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AA4C/E;;;;;;;;;;;;;;GAcG;AACH,oGAAoG;AACpG,MAAM,UAAU,+BAA+B;IAC7C,sBAAsB,CAAC,kBAAkB,EAAE,KAAK,EAAE,OAAwB,EAAmB,EAAE;QAC7F,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAA2B,+BAA+B,EAAE;gBACtF,OAAO,EAAE,OAAO,CAAC,OAAO;aACzB,CAAC,CAAC;YACH,OAAO,sBAAsB,CAAC,MAA8B,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,+CAAgD,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACtF,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
+
import { reorderDocsByRank } from './compose/loop-context-compose.js';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* ones (sort_order is the floor). Pure -- exported for tests.
|
|
3
|
+
* Back-compat re-export. `reorderDocsByRank` historically lived in this module
|
|
4
|
+
* (and is imported by loop-context-semantic.test.ts); its canonical home is now
|
|
5
|
+
* the shared compose mirror, but the re-export keeps existing importers working.
|
|
6
6
|
*/
|
|
7
|
-
export
|
|
8
|
-
id: string;
|
|
9
|
-
}>(docs: T[], rankedIds: string[]): T[];
|
|
7
|
+
export { reorderDocsByRank };
|
|
10
8
|
/**
|
|
11
9
|
* loop.context
|
|
12
10
|
*
|
|
13
|
-
* Composite resolver that fetches persona + force-ranked documents +
|
|
14
|
-
* for one or more loop layers. Provides complete loop context for agent
|
|
11
|
+
* Composite resolver that fetches persona + force-/semantic-ranked documents +
|
|
12
|
+
* Q&A for one or more loop layers. Provides complete loop context for agent
|
|
15
13
|
* prompt injection.
|
|
16
14
|
*
|
|
17
15
|
* Optional param: layer
|
|
@@ -22,6 +20,11 @@ export declare function reorderDocsByRank<T extends {
|
|
|
22
20
|
*
|
|
23
21
|
* Loop data at focus and delivery layers is scoped to the product ID
|
|
24
22
|
* (layer-based architecture, not per-record).
|
|
23
|
+
*
|
|
24
|
+
* THIN FETCH HALF: the per-layer reads are batched up front and the
|
|
25
|
+
* per-question loop_answer_get N+1 is collapsed into a single loop_answer_list
|
|
26
|
+
* call; rendering is delegated to the shared, drift-mirrored composeLoopContext
|
|
27
|
+
* so the inspector's preview matches a live spawn.
|
|
25
28
|
*/
|
|
26
29
|
/** Register this module's resolver(s). Called from initResolvers() -- not an import side effect. */
|
|
27
30
|
export declare function registerLoopContextResolver(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop-context.d.ts","sourceRoot":"","sources":["../../src/resolvers/loop-context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loop-context.d.ts","sourceRoot":"","sources":["../../src/resolvers/loop-context.ts"],"names":[],"mappings":"AAQA,OAAO,EAAsB,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAG1F;;;;GAIG;AACH,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAuF7B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,oGAAoG;AACpG,wBAAgB,2BAA2B,IAAI,IAAI,CAsDlD"}
|
|
@@ -1,119 +1,72 @@
|
|
|
1
1
|
import { registerSourceResolver } from '../assembly-engine.js';
|
|
2
2
|
import { callApi } from '../queries/shared.js';
|
|
3
|
+
import { composeLoopContext, reorderDocsByRank } from './compose/loop-context-compose.js';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* ones (sort_order is the floor). Pure -- exported for tests.
|
|
5
|
+
* Back-compat re-export. `reorderDocsByRank` historically lived in this module
|
|
6
|
+
* (and is imported by loop-context-semantic.test.ts); its canonical home is now
|
|
7
|
+
* the shared compose mirror, but the re-export keeps existing importers working.
|
|
8
8
|
*/
|
|
9
|
-
export
|
|
10
|
-
if (rankedIds.length === 0)
|
|
11
|
-
return docs;
|
|
12
|
-
const rankOf = new Map(rankedIds.map((id, i) => [id, i]));
|
|
13
|
-
return [...docs].sort((a, b) => (rankOf.get(a.id) ?? Number.MAX_SAFE_INTEGER) -
|
|
14
|
-
(rankOf.get(b.id) ?? Number.MAX_SAFE_INTEGER));
|
|
15
|
-
}
|
|
9
|
+
export { reorderDocsByRank };
|
|
16
10
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
11
|
+
* THIN FETCH HALF for one layer: batches persona + documents (+ optional
|
|
12
|
+
* semantic search ranking) + questions. Answers are NOT fetched here -- they
|
|
13
|
+
* are batched once across all layers by the caller. Every read degrades to
|
|
14
|
+
* empty on failure (missing persona/docs/questions are not errors).
|
|
19
15
|
*/
|
|
20
|
-
async function
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
parts.push(`**Persona:** ${personaResult.persona.content}`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
// No persona -- not an error
|
|
34
|
-
}
|
|
35
|
-
// Documents. By default these are force-ranked by sort_order. When a relevance
|
|
36
|
-
// query is supplied, we reorder the SAME full documents by semantic similarity
|
|
37
|
-
// (loop_document_search blends text rank + cosine over the embedding). The
|
|
38
|
-
// sort_order order is preserved as the floor: if search fails or returns
|
|
39
|
-
// nothing, or for documents the search did not rank, we keep sort_order.
|
|
40
|
-
try {
|
|
41
|
-
const docsResult = await callApi('loop_document_list', {
|
|
16
|
+
async function fetchLayerRaw(layer, query) {
|
|
17
|
+
const { entityType, entityId, label } = layer;
|
|
18
|
+
let persona = null;
|
|
19
|
+
let docs = [];
|
|
20
|
+
let rankedDocIds = [];
|
|
21
|
+
let questions = [];
|
|
22
|
+
const [personaSettled, docsSettled, questionsSettled] = await Promise.allSettled([
|
|
23
|
+
callApi('loop_persona_get', { entityType, entityId }),
|
|
24
|
+
callApi('loop_document_list', {
|
|
42
25
|
entityType,
|
|
43
26
|
entityId,
|
|
44
27
|
detail: 'full',
|
|
45
28
|
limit: 50,
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
const trimmedQuery = query?.trim();
|
|
49
|
-
if (trimmedQuery && docs.length > 1) {
|
|
50
|
-
try {
|
|
51
|
-
const search = await callApi('loop_document_search', {
|
|
52
|
-
entityType,
|
|
53
|
-
entityId,
|
|
54
|
-
query: trimmedQuery,
|
|
55
|
-
limit: docs.length,
|
|
56
|
-
});
|
|
57
|
-
docs = reorderDocsByRank(docs, search.items.map((it) => it.id));
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
// Search unavailable -- keep sort_order ordering.
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (docs.length > 0) {
|
|
64
|
-
const docLines = docs.map((doc, i) => `#### ${i + 1}. ${doc.title}\n\n${doc.content}`);
|
|
65
|
-
parts.push(`### Documents\n\n${docLines.join('\n\n')}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
// No documents -- not an error
|
|
70
|
-
}
|
|
71
|
-
// Questions + answers
|
|
72
|
-
try {
|
|
73
|
-
const qResult = await callApi('loop_question_list', {
|
|
29
|
+
}),
|
|
30
|
+
callApi('loop_question_list', {
|
|
74
31
|
entityType,
|
|
75
32
|
entityId,
|
|
76
33
|
detail: 'full',
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const formatQ = async (q) => {
|
|
82
|
-
try {
|
|
83
|
-
const aResult = await callApi('loop_answer_get', { questionId: q.id });
|
|
84
|
-
const answer = aResult.answer?.content || '_No answer yet._';
|
|
85
|
-
return `**Q:** ${q.text}\n**A:** ${answer}`;
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return `**Q:** ${q.text}\n**A:** _No answer yet._`;
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
const qParts = [];
|
|
92
|
-
if (fixed.length > 0) {
|
|
93
|
-
const fixedLines = await Promise.all(fixed.map(formatQ));
|
|
94
|
-
qParts.push(`#### Fixed Questions\n\n${fixedLines.join('\n\n')}`);
|
|
95
|
-
}
|
|
96
|
-
if (generated.length > 0) {
|
|
97
|
-
const genLines = await Promise.all(generated.map(formatQ));
|
|
98
|
-
qParts.push(`#### Agent-Generated Questions\n\n${genLines.join('\n\n')}`);
|
|
99
|
-
}
|
|
100
|
-
if (qParts.length > 0) {
|
|
101
|
-
parts.push(`### Questions & Answers\n\n${qParts.join('\n\n')}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
34
|
+
}),
|
|
35
|
+
]);
|
|
36
|
+
if (personaSettled.status === 'fulfilled') {
|
|
37
|
+
persona = personaSettled.value.persona?.content ?? null;
|
|
104
38
|
}
|
|
105
|
-
|
|
106
|
-
|
|
39
|
+
if (docsSettled.status === 'fulfilled') {
|
|
40
|
+
docs = docsSettled.value.items ?? [];
|
|
41
|
+
}
|
|
42
|
+
if (questionsSettled.status === 'fulfilled') {
|
|
43
|
+
questions = questionsSettled.value.items ?? [];
|
|
44
|
+
}
|
|
45
|
+
// Semantic ranking depends on the fetched docs, so it runs after loop_document_list.
|
|
46
|
+
// The rank is applied in the (pure) compose module via reorderDocsByRank; here we
|
|
47
|
+
// only fetch the id ordering. sort_order remains the floor when search is absent.
|
|
48
|
+
const trimmedQuery = query?.trim();
|
|
49
|
+
if (trimmedQuery && docs.length > 1) {
|
|
50
|
+
try {
|
|
51
|
+
const search = await callApi('loop_document_search', {
|
|
52
|
+
entityType,
|
|
53
|
+
entityId,
|
|
54
|
+
query: trimmedQuery,
|
|
55
|
+
limit: docs.length,
|
|
56
|
+
});
|
|
57
|
+
rankedDocIds = (search.items ?? []).map((it) => it.id);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Search unavailable -- keep sort_order ordering.
|
|
61
|
+
}
|
|
107
62
|
}
|
|
108
|
-
|
|
109
|
-
return '';
|
|
110
|
-
return `## ${layerLabel} Loop\n\n${parts.join('\n\n')}`;
|
|
63
|
+
return { label, persona, docs, rankedDocIds, questions };
|
|
111
64
|
}
|
|
112
65
|
/**
|
|
113
66
|
* loop.context
|
|
114
67
|
*
|
|
115
|
-
* Composite resolver that fetches persona + force-ranked documents +
|
|
116
|
-
* for one or more loop layers. Provides complete loop context for agent
|
|
68
|
+
* Composite resolver that fetches persona + force-/semantic-ranked documents +
|
|
69
|
+
* Q&A for one or more loop layers. Provides complete loop context for agent
|
|
117
70
|
* prompt injection.
|
|
118
71
|
*
|
|
119
72
|
* Optional param: layer
|
|
@@ -124,6 +77,11 @@ async function fetchLoopLayerContext(entityType, entityId, layerLabel, query) {
|
|
|
124
77
|
*
|
|
125
78
|
* Loop data at focus and delivery layers is scoped to the product ID
|
|
126
79
|
* (layer-based architecture, not per-record).
|
|
80
|
+
*
|
|
81
|
+
* THIN FETCH HALF: the per-layer reads are batched up front and the
|
|
82
|
+
* per-question loop_answer_get N+1 is collapsed into a single loop_answer_list
|
|
83
|
+
* call; rendering is delegated to the shared, drift-mirrored composeLoopContext
|
|
84
|
+
* so the inspector's preview matches a live spawn.
|
|
127
85
|
*/
|
|
128
86
|
/** Register this module's resolver(s). Called from initResolvers() -- not an import side effect. */
|
|
129
87
|
export function registerLoopContextResolver() {
|
|
@@ -142,11 +100,38 @@ export function registerLoopContextResolver() {
|
|
|
142
100
|
if (!layerFilter || layerFilter === 'delivery') {
|
|
143
101
|
layers.push({ entityType: 'delivery', entityId: context.productId, label: 'Delivery' });
|
|
144
102
|
}
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
103
|
+
// Wave 1: fetch persona + documents (+ ranking) + questions for every layer.
|
|
104
|
+
const raw = await Promise.all(layers.map((l) => fetchLayerRaw(l, query)));
|
|
105
|
+
// Wave 2: collapse the answer N+1 -- one batched read for every question id
|
|
106
|
+
// across all layers.
|
|
107
|
+
const allQuestionIds = raw.flatMap((r) => r.questions.map((q) => q.id));
|
|
108
|
+
const answersByQuestion = new Map();
|
|
109
|
+
if (allQuestionIds.length > 0) {
|
|
110
|
+
try {
|
|
111
|
+
const resp = await callApi('loop_answer_list', {
|
|
112
|
+
questionIds: allQuestionIds,
|
|
113
|
+
});
|
|
114
|
+
for (const item of resp.items ?? []) {
|
|
115
|
+
answersByQuestion.set(item.questionId, item.content ?? null);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Answers unavailable -- each question renders "_No answer yet._".
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const toQA = (q) => ({
|
|
123
|
+
question: q.text,
|
|
124
|
+
answer: answersByQuestion.get(q.id) ?? null,
|
|
125
|
+
});
|
|
126
|
+
const composeLayers = raw.map((r) => ({
|
|
127
|
+
label: r.label,
|
|
128
|
+
persona: r.persona,
|
|
129
|
+
docs: r.docs.map((d) => ({ id: d.id, title: d.title, content: d.content })),
|
|
130
|
+
rankedDocIds: r.rankedDocIds,
|
|
131
|
+
fixedQuestions: r.questions.filter((q) => q.questionType === 'fixed').map(toQA),
|
|
132
|
+
generatedQuestions: r.questions.filter((q) => q.questionType === 'generated').map(toQA),
|
|
133
|
+
}));
|
|
134
|
+
return composeLoopContext(composeLayers);
|
|
150
135
|
});
|
|
151
136
|
}
|
|
152
137
|
//# sourceMappingURL=loop-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop-context.js","sourceRoot":"","sources":["../../src/resolvers/loop-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"loop-context.js","sourceRoot":"","sources":["../../src/resolvers/loop-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* statements are joined with blank lines so the agent sees each
|
|
7
7
|
* delivery's target state. Empty string when no delivery has an
|
|
8
8
|
* injection link or no injection has an FRT statement set.
|
|
9
|
+
*
|
|
10
|
+
* THIN FETCH HALF: resolves each delivery's injection bundle, then delegates
|
|
11
|
+
* rendering to the shared, drift-mirrored `composeLoopFrtStatement`.
|
|
9
12
|
*/
|
|
10
13
|
/** Register this module's resolver(s). Called from initResolvers() -- not an import side effect. */
|
|
11
14
|
export declare function registerLoopFrtStatementResolver(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop-frt-statement.d.ts","sourceRoot":"","sources":["../../src/resolvers/loop-frt-statement.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loop-frt-statement.d.ts","sourceRoot":"","sources":["../../src/resolvers/loop-frt-statement.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;GAWG;AACH,oGAAoG;AACpG,wBAAgB,gCAAgC,IAAI,IAAI,CAsBvD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { registerSourceResolver } from '../assembly-engine.js';
|
|
2
2
|
import { getDeliveryInjectionPairs, fetchInjectionBundles } from './shared/loop.js';
|
|
3
|
+
import { composeLoopFrtStatement } from './compose/loop-frt-statement-compose.js';
|
|
3
4
|
/**
|
|
4
5
|
* loop.frt_statement
|
|
5
6
|
*
|
|
@@ -8,6 +9,9 @@ import { getDeliveryInjectionPairs, fetchInjectionBundles } from './shared/loop.
|
|
|
8
9
|
* statements are joined with blank lines so the agent sees each
|
|
9
10
|
* delivery's target state. Empty string when no delivery has an
|
|
10
11
|
* injection link or no injection has an FRT statement set.
|
|
12
|
+
*
|
|
13
|
+
* THIN FETCH HALF: resolves each delivery's injection bundle, then delegates
|
|
14
|
+
* rendering to the shared, drift-mirrored `composeLoopFrtStatement`.
|
|
11
15
|
*/
|
|
12
16
|
/** Register this module's resolver(s). Called from initResolvers() -- not an import side effect. */
|
|
13
17
|
export function registerLoopFrtStatementResolver() {
|
|
@@ -19,19 +23,14 @@ export function registerLoopFrtStatementResolver() {
|
|
|
19
23
|
const bundles = await fetchInjectionBundles(pairs.map((p) => p.injectionId));
|
|
20
24
|
if (bundles.size === 0)
|
|
21
25
|
return '';
|
|
22
|
-
const
|
|
26
|
+
const entries = [];
|
|
23
27
|
for (const { injectionId } of pairs) {
|
|
24
28
|
const bundle = bundles.get(injectionId);
|
|
25
29
|
if (!bundle)
|
|
26
30
|
continue;
|
|
27
|
-
|
|
28
|
-
if (typeof frt !== 'string' || frt.trim().length === 0)
|
|
29
|
-
continue;
|
|
30
|
-
lines.push(frt.trim());
|
|
31
|
+
entries.push({ frtStatement: bundle.injection.frtStatement });
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
-
return '';
|
|
34
|
-
return lines.join('\n\n');
|
|
33
|
+
return composeLoopFrtStatement(entries);
|
|
35
34
|
}
|
|
36
35
|
catch (err) {
|
|
37
36
|
console.warn(`[assembly] loop.frt_statement failed: ${err.message}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop-frt-statement.js","sourceRoot":"","sources":["../../src/resolvers/loop-frt-statement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"loop-frt-statement.js","sourceRoot":"","sources":["../../src/resolvers/loop-frt-statement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAGlF;;;;;;;;;;;GAWG;AACH,oGAAoG;AACpG,MAAM,UAAU,gCAAgC;IAC9C,sBAAsB,CAAC,oBAAoB,EAAE,KAAK,EAAE,OAAwB,EAAmB,EAAE;QAC/F,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAElC,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;YAC7E,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAElC,MAAM,OAAO,GAA4B,EAAE,CAAC;YAC5C,KAAK,MAAM,EAAE,WAAW,EAAE,IAAI,KAAK,EAAE,CAAC;gBACpC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACxC,IAAI,CAAC,MAAM;oBAAE,SAAS;gBACtB,OAAO,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;YAChE,CAAC;YAED,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,yCAA0C,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YAChF,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
* the injection node: statement, lifecycle status, what obstacle it
|
|
6
6
|
* dissolves. Plain markdown; no upstream/downstream walk (that lives in
|
|
7
7
|
* loop.upstream_udes / loop.expected_effects).
|
|
8
|
+
*
|
|
9
|
+
* THIN FETCH HALF: resolves each delivery's injection bundle, then delegates
|
|
10
|
+
* rendering to the shared, drift-mirrored `composeLoopInjection` so the
|
|
11
|
+
* inspector's preview matches a live spawn.
|
|
8
12
|
*/
|
|
9
13
|
/** Register this module's resolver(s). Called from initResolvers() -- not an import side effect. */
|
|
10
14
|
export declare function registerLoopInjectionResolver(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop-injection.d.ts","sourceRoot":"","sources":["../../src/resolvers/loop-injection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loop-injection.d.ts","sourceRoot":"","sources":["../../src/resolvers/loop-injection.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;GAWG;AACH,oGAAoG;AACpG,wBAAgB,6BAA6B,IAAI,IAAI,CAsBpD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { registerSourceResolver } from '../assembly-engine.js';
|
|
2
2
|
import { getDeliveryInjectionPairs, fetchInjectionBundles } from './shared/loop.js';
|
|
3
|
+
import { composeLoopInjection } from './compose/loop-injection-compose.js';
|
|
3
4
|
/**
|
|
4
5
|
* loop.injection
|
|
5
6
|
*
|
|
@@ -7,6 +8,10 @@ import { getDeliveryInjectionPairs, fetchInjectionBundles } from './shared/loop.
|
|
|
7
8
|
* the injection node: statement, lifecycle status, what obstacle it
|
|
8
9
|
* dissolves. Plain markdown; no upstream/downstream walk (that lives in
|
|
9
10
|
* loop.upstream_udes / loop.expected_effects).
|
|
11
|
+
*
|
|
12
|
+
* THIN FETCH HALF: resolves each delivery's injection bundle, then delegates
|
|
13
|
+
* rendering to the shared, drift-mirrored `composeLoopInjection` so the
|
|
14
|
+
* inspector's preview matches a live spawn.
|
|
10
15
|
*/
|
|
11
16
|
/** Register this module's resolver(s). Called from initResolvers() -- not an import side effect. */
|
|
12
17
|
export function registerLoopInjectionResolver() {
|
|
@@ -18,29 +23,14 @@ export function registerLoopInjectionResolver() {
|
|
|
18
23
|
const bundles = await fetchInjectionBundles(pairs.map((p) => p.injectionId));
|
|
19
24
|
if (bundles.size === 0)
|
|
20
25
|
return '';
|
|
21
|
-
const
|
|
26
|
+
const entries = [];
|
|
22
27
|
for (const { deliveryName, injectionId } of pairs) {
|
|
23
28
|
const bundle = bundles.get(injectionId);
|
|
24
29
|
if (!bundle)
|
|
25
30
|
continue;
|
|
26
|
-
|
|
27
|
-
const statusTag = inj.injectionStatus ? ` [${inj.injectionStatus}]` : '';
|
|
28
|
-
const dissolvesLine = inj.dissolvesObstacle
|
|
29
|
-
? `- **Dissolves obstacle:** ${inj.dissolvesObstacle}`
|
|
30
|
-
: null;
|
|
31
|
-
const lines = [
|
|
32
|
-
`### ${deliveryName}`,
|
|
33
|
-
'',
|
|
34
|
-
`- **Injection:** ${inj.statement}${statusTag}`,
|
|
35
|
-
`- **Injection status:** ${inj.injectionStatus ?? '_not set_'}`,
|
|
36
|
-
];
|
|
37
|
-
if (dissolvesLine)
|
|
38
|
-
lines.push(dissolvesLine);
|
|
39
|
-
sections.push(lines.join('\n'));
|
|
31
|
+
entries.push({ deliveryName, injection: bundle.injection });
|
|
40
32
|
}
|
|
41
|
-
|
|
42
|
-
return '';
|
|
43
|
-
return `## Loop Injection (per delivery)\n\n${sections.join('\n\n')}`;
|
|
33
|
+
return composeLoopInjection(entries);
|
|
44
34
|
}
|
|
45
35
|
catch (err) {
|
|
46
36
|
console.warn(`[assembly] loop.injection failed: ${err.message}`);
|