agentfootprint 7.4.0 → 7.6.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/AGENTS.md +1 -1
- package/CLAUDE.md +1 -1
- package/README.md +108 -11
- package/ai-instructions/claude-code/SKILL.md +1 -1
- package/dist/core/Agent.js +19 -1
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/RunnerBase.js +12 -1
- package/dist/core/RunnerBase.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +33 -1
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +225 -16
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/checkin.js +266 -0
- package/dist/core/checkin.js.map +1 -0
- package/dist/core/pause.js +17 -1
- package/dist/core/pause.js.map +1 -1
- package/dist/core/tools.js +3 -0
- package/dist/core/tools.js.map +1 -1
- package/dist/debug.js +17 -2
- package/dist/debug.js.map +1 -1
- package/dist/esm/core/Agent.d.ts +6 -1
- package/dist/esm/core/Agent.js +19 -1
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/RunnerBase.js +12 -1
- package/dist/esm/core/RunnerBase.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +27 -0
- package/dist/esm/core/agent/AgentBuilder.js +33 -1
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.d.ts +9 -0
- package/dist/esm/core/agent/stages/toolCalls.js +225 -16
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +2 -0
- package/dist/esm/core/checkin.d.ts +263 -0
- package/dist/esm/core/checkin.js +254 -0
- package/dist/esm/core/checkin.js.map +1 -0
- package/dist/esm/core/pause.d.ts +24 -0
- package/dist/esm/core/pause.js +15 -0
- package/dist/esm/core/pause.js.map +1 -1
- package/dist/esm/core/tools.d.ts +19 -0
- package/dist/esm/core/tools.js +3 -0
- package/dist/esm/core/tools.js.map +1 -1
- package/dist/esm/debug.d.ts +3 -2
- package/dist/esm/debug.js +10 -2
- package/dist/esm/debug.js.map +1 -1
- package/dist/esm/events/dispatcher.d.ts +1 -1
- package/dist/esm/events/dispatcher.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +19 -0
- package/dist/esm/events/registry.d.ts +7 -1
- package/dist/esm/events/registry.js +6 -0
- package/dist/esm/events/registry.js.map +1 -1
- package/dist/esm/index.d.ts +4 -1
- package/dist/esm/index.js +9 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/context-bisect/index.d.ts +1 -0
- package/dist/esm/lib/context-bisect/index.js +3 -0
- package/dist/esm/lib/context-bisect/index.js.map +1 -1
- package/dist/esm/lib/context-bisect/localize.d.ts +6 -2
- package/dist/esm/lib/context-bisect/localize.js +19 -3
- package/dist/esm/lib/context-bisect/localize.js.map +1 -1
- package/dist/esm/lib/context-bisect/rerun.d.ts +123 -0
- package/dist/esm/lib/context-bisect/rerun.js +155 -0
- package/dist/esm/lib/context-bisect/rerun.js.map +1 -0
- package/dist/esm/lib/context-bisect/types.d.ts +8 -0
- package/dist/esm/lib/context-bisect/types.js.map +1 -1
- package/dist/esm/lib/influence-core/index.d.ts +2 -0
- package/dist/esm/lib/influence-core/index.js +2 -0
- package/dist/esm/lib/influence-core/index.js.map +1 -1
- package/dist/esm/lib/influence-core/lexical.d.ts +60 -0
- package/dist/esm/lib/influence-core/lexical.js +142 -0
- package/dist/esm/lib/influence-core/lexical.js.map +1 -0
- package/dist/esm/lib/influence-core/signals.d.ts +5 -0
- package/dist/esm/lib/influence-core/signals.js +6 -2
- package/dist/esm/lib/influence-core/signals.js.map +1 -1
- package/dist/esm/lib/influence-core/strategies.d.ts +51 -0
- package/dist/esm/lib/influence-core/strategies.js +29 -0
- package/dist/esm/lib/influence-core/strategies.js.map +1 -0
- package/dist/esm/lib/recorded-chat/index.d.ts +11 -0
- package/dist/esm/lib/recorded-chat/index.js +11 -0
- package/dist/esm/lib/recorded-chat/index.js.map +1 -0
- package/dist/esm/lib/recorded-chat/recordedChat.d.ts +20 -0
- package/dist/esm/lib/recorded-chat/recordedChat.js +240 -0
- package/dist/esm/lib/recorded-chat/recordedChat.js.map +1 -0
- package/dist/esm/lib/recorded-chat/types.d.ts +182 -0
- package/dist/esm/lib/recorded-chat/types.js +31 -0
- package/dist/esm/lib/recorded-chat/types.js.map +1 -0
- package/dist/esm/recorders/core/CheckInRecorder.d.ts +90 -0
- package/dist/esm/recorders/core/CheckInRecorder.js +109 -0
- package/dist/esm/recorders/core/CheckInRecorder.js.map +1 -0
- package/dist/events/dispatcher.js.map +1 -1
- package/dist/events/registry.js +6 -0
- package/dist/events/registry.js.map +1 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/context-bisect/index.js +6 -1
- package/dist/lib/context-bisect/index.js.map +1 -1
- package/dist/lib/context-bisect/localize.js +19 -3
- package/dist/lib/context-bisect/localize.js.map +1 -1
- package/dist/lib/context-bisect/rerun.js +160 -0
- package/dist/lib/context-bisect/rerun.js.map +1 -0
- package/dist/lib/context-bisect/types.js.map +1 -1
- package/dist/lib/influence-core/index.js +7 -1
- package/dist/lib/influence-core/index.js.map +1 -1
- package/dist/lib/influence-core/lexical.js +146 -0
- package/dist/lib/influence-core/lexical.js.map +1 -0
- package/dist/lib/influence-core/signals.js +8 -3
- package/dist/lib/influence-core/signals.js.map +1 -1
- package/dist/lib/influence-core/strategies.js +33 -0
- package/dist/lib/influence-core/strategies.js.map +1 -0
- package/dist/lib/recorded-chat/index.js +15 -0
- package/dist/lib/recorded-chat/index.js.map +1 -0
- package/dist/lib/recorded-chat/recordedChat.js +244 -0
- package/dist/lib/recorded-chat/recordedChat.js.map +1 -0
- package/dist/lib/recorded-chat/types.js +32 -0
- package/dist/lib/recorded-chat/types.js.map +1 -0
- package/dist/recorders/core/CheckInRecorder.js +114 -0
- package/dist/recorders/core/CheckInRecorder.js.map +1 -0
- package/dist/types/core/Agent.d.ts +6 -1
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/RunnerBase.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +27 -0
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts +9 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +2 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/checkin.d.ts +264 -0
- package/dist/types/core/checkin.d.ts.map +1 -0
- package/dist/types/core/pause.d.ts +24 -0
- package/dist/types/core/pause.d.ts.map +1 -1
- package/dist/types/core/tools.d.ts +19 -0
- package/dist/types/core/tools.d.ts.map +1 -1
- package/dist/types/debug.d.ts +3 -2
- package/dist/types/debug.d.ts.map +1 -1
- package/dist/types/events/dispatcher.d.ts +1 -1
- package/dist/types/events/dispatcher.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +19 -0
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/events/registry.d.ts +7 -1
- package/dist/types/events/registry.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/context-bisect/index.d.ts +1 -0
- package/dist/types/lib/context-bisect/index.d.ts.map +1 -1
- package/dist/types/lib/context-bisect/localize.d.ts +6 -2
- package/dist/types/lib/context-bisect/localize.d.ts.map +1 -1
- package/dist/types/lib/context-bisect/rerun.d.ts +124 -0
- package/dist/types/lib/context-bisect/rerun.d.ts.map +1 -0
- package/dist/types/lib/context-bisect/types.d.ts +8 -0
- package/dist/types/lib/context-bisect/types.d.ts.map +1 -1
- package/dist/types/lib/influence-core/index.d.ts +2 -0
- package/dist/types/lib/influence-core/index.d.ts.map +1 -1
- package/dist/types/lib/influence-core/lexical.d.ts +61 -0
- package/dist/types/lib/influence-core/lexical.d.ts.map +1 -0
- package/dist/types/lib/influence-core/signals.d.ts +5 -0
- package/dist/types/lib/influence-core/signals.d.ts.map +1 -1
- package/dist/types/lib/influence-core/strategies.d.ts +52 -0
- package/dist/types/lib/influence-core/strategies.d.ts.map +1 -0
- package/dist/types/lib/recorded-chat/index.d.ts +12 -0
- package/dist/types/lib/recorded-chat/index.d.ts.map +1 -0
- package/dist/types/lib/recorded-chat/recordedChat.d.ts +21 -0
- package/dist/types/lib/recorded-chat/recordedChat.d.ts.map +1 -0
- package/dist/types/lib/recorded-chat/types.d.ts +183 -0
- package/dist/types/lib/recorded-chat/types.d.ts.map +1 -0
- package/dist/types/recorders/core/CheckInRecorder.d.ts +91 -0
- package/dist/types/recorders/core/CheckInRecorder.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scoreLexicalInfluence — the DETERMINISTIC, zero-dependency influence
|
|
3
|
+
* scorer: the same four-signal FDL frame as `scoreInfluence`
|
|
4
|
+
* (fa / avg / persist / depth, adaptive weights, composite, stable desc
|
|
5
|
+
* sort), with ONE substitution — cosine-over-embeddings becomes set-cosine
|
|
6
|
+
* over word tokens. Nothing here embeds; nothing here calls the network.
|
|
7
|
+
*
|
|
8
|
+
* ## Honest claim (same discipline as `scoreInfluence`, one rung blinder)
|
|
9
|
+
*
|
|
10
|
+
* Every returned `InfluenceScore.signals` / `weights` / `adapted` is
|
|
11
|
+
* GENUINELY computed — nothing is fabricated. But the FA signal here means
|
|
12
|
+
* "shares words with the final answer", NOT "semantically close" and NOT
|
|
13
|
+
* "caused". It is cheaper and BLINDER than `'semantic-alignment'`: a
|
|
14
|
+
* paraphrase (different words, same meaning) is a miss. The claim-ladder
|
|
15
|
+
* guarantee is unchanged — a scorer only reorders suspects; ablation alone
|
|
16
|
+
* convicts. So the worst a lexical ranking does is confirm slower, never
|
|
17
|
+
* wrong.
|
|
18
|
+
*
|
|
19
|
+
* English / ASCII by construction (the tokenizer splits on non-alphanumerics
|
|
20
|
+
* and folds a single trailing plural `s`) — use `'semantic-alignment'` for
|
|
21
|
+
* other languages.
|
|
22
|
+
*/
|
|
23
|
+
import type { Embedder, EvidenceInput, InfluenceScore, InfluenceWeights } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Args for `scoreLexicalInfluence` — a SUPERTYPE of `ScoreInfluenceArgs`:
|
|
26
|
+
* everything the embedding scorer takes, with `embedder` optional and NEVER
|
|
27
|
+
* called. That supertype relationship is what makes `scoreLexicalInfluence`
|
|
28
|
+
* assignable to `InfluenceScorer` (parameter contravariance) while remaining
|
|
29
|
+
* honestly callable with no embedder at all.
|
|
30
|
+
*/
|
|
31
|
+
export interface ScoreLexicalInfluenceArgs {
|
|
32
|
+
/** Evidence items (tool results / context sources) with ancestors. */
|
|
33
|
+
readonly evidence: readonly EvidenceInput[];
|
|
34
|
+
/** The final answer text the evidence is scored against. */
|
|
35
|
+
readonly finalAnswerText: string;
|
|
36
|
+
/** Accepted only for `InfluenceScorer` compatibility. IGNORED — this scorer never embeds. */
|
|
37
|
+
readonly embedder?: Embedder;
|
|
38
|
+
/** Composite weights (same frame as `scoreInfluence`). Default 0.40/0.30/0.20/0.10. */
|
|
39
|
+
readonly weights?: InfluenceWeights;
|
|
40
|
+
/** PERSIST threshold on the LEXICAL overlap scale (set-cosine, 0..1). Default 0.30. */
|
|
41
|
+
readonly persistenceThreshold?: number;
|
|
42
|
+
/** Accepted for compatibility; unused (nothing async to abort — resolves immediately). */
|
|
43
|
+
readonly signal?: AbortSignal;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Score every evidence item on the four FDL signals — the LEXICAL kernel
|
|
47
|
+
* (set-cosine over word tokens instead of embedding cosine) — and rank by
|
|
48
|
+
* composite, descending. Ties keep input order (stable sort).
|
|
49
|
+
*
|
|
50
|
+
* Deterministic: same inputs → byte-identical output, every run, every
|
|
51
|
+
* machine. Zero dependencies, zero network, sync-fast (async only to satisfy
|
|
52
|
+
* the `InfluenceScorer` seam). Never touches `args.embedder` or `args.signal`.
|
|
53
|
+
*
|
|
54
|
+
* Honest claim: ranked WORD-OVERLAP proxies — cheaper and blinder than the
|
|
55
|
+
* embedding scorer (paraphrase = miss). NOT causal attribution — see module
|
|
56
|
+
* docs.
|
|
57
|
+
*
|
|
58
|
+
* @throws on duplicate evidence ids or invalid weights.
|
|
59
|
+
*/
|
|
60
|
+
export declare function scoreLexicalInfluence(args: ScoreLexicalInfluenceArgs): Promise<InfluenceScore[]>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { DEFAULT_INFLUENCE_WEIGHTS, DEFAULT_PERSISTENCE_THRESHOLD } from './types.js';
|
|
2
|
+
import { adaptWeights, assertUniqueIds, assertValidWeights, compositeScore, structuralProximity, } from './signals.js';
|
|
3
|
+
/** Small, conservative stop list — fillers that would only add noise to
|
|
4
|
+
* the overlap. Copied verbatim from the injection-engine's `EntryScorer`
|
|
5
|
+
* (influence-core is a leaf — it restates rather than imports). */
|
|
6
|
+
const STOP_WORDS = new Set([
|
|
7
|
+
'a',
|
|
8
|
+
'an',
|
|
9
|
+
'the',
|
|
10
|
+
'and',
|
|
11
|
+
'or',
|
|
12
|
+
'but',
|
|
13
|
+
'if',
|
|
14
|
+
'to',
|
|
15
|
+
'of',
|
|
16
|
+
'for',
|
|
17
|
+
'in',
|
|
18
|
+
'on',
|
|
19
|
+
'at',
|
|
20
|
+
'by',
|
|
21
|
+
'with',
|
|
22
|
+
'is',
|
|
23
|
+
'are',
|
|
24
|
+
'was',
|
|
25
|
+
'were',
|
|
26
|
+
'be',
|
|
27
|
+
'been',
|
|
28
|
+
'it',
|
|
29
|
+
'this',
|
|
30
|
+
'that',
|
|
31
|
+
'these',
|
|
32
|
+
'those',
|
|
33
|
+
'i',
|
|
34
|
+
'you',
|
|
35
|
+
'we',
|
|
36
|
+
'my',
|
|
37
|
+
'our',
|
|
38
|
+
'me',
|
|
39
|
+
'please',
|
|
40
|
+
'can',
|
|
41
|
+
'could',
|
|
42
|
+
'would',
|
|
43
|
+
'should',
|
|
44
|
+
'do',
|
|
45
|
+
'does',
|
|
46
|
+
'how',
|
|
47
|
+
'what',
|
|
48
|
+
'need',
|
|
49
|
+
'want',
|
|
50
|
+
]);
|
|
51
|
+
/**
|
|
52
|
+
* Lowercase → split on non-alphanumerics → drop 1-char tokens + stop words →
|
|
53
|
+
* light plural fold → set. The plural fold (drop a single trailing `s` on
|
|
54
|
+
* tokens length ≥ 4, but never `-ss`) lets `refund` match `refunds` while
|
|
55
|
+
* `address` stays `address`. ASCII-only by construction (the regex splits
|
|
56
|
+
* away non-Latin/accented text — use `'semantic-alignment'` for other
|
|
57
|
+
* languages).
|
|
58
|
+
*/
|
|
59
|
+
function tokenize(text) {
|
|
60
|
+
const out = new Set();
|
|
61
|
+
for (const raw of text.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
62
|
+
if (raw.length < 2 || STOP_WORDS.has(raw))
|
|
63
|
+
continue;
|
|
64
|
+
const fold = raw.length >= 4 && raw.endsWith('s') && !raw.endsWith('ss');
|
|
65
|
+
out.add(fold ? raw.slice(0, -1) : raw);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
/** |A ∩ B| / sqrt(|A| · |B|) — set cosine, range [0, 1]. Empty either side → 0.
|
|
70
|
+
* Iterates the smaller set (same kernel as EntryScorer's `setCosine`). */
|
|
71
|
+
function overlap(a, b) {
|
|
72
|
+
if (a.size === 0 || b.size === 0)
|
|
73
|
+
return 0;
|
|
74
|
+
const [small, large] = a.size <= b.size ? [a, b] : [b, a];
|
|
75
|
+
let shared = 0;
|
|
76
|
+
for (const t of small)
|
|
77
|
+
if (large.has(t))
|
|
78
|
+
shared += 1;
|
|
79
|
+
return shared / Math.sqrt(a.size * b.size);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Score every evidence item on the four FDL signals — the LEXICAL kernel
|
|
83
|
+
* (set-cosine over word tokens instead of embedding cosine) — and rank by
|
|
84
|
+
* composite, descending. Ties keep input order (stable sort).
|
|
85
|
+
*
|
|
86
|
+
* Deterministic: same inputs → byte-identical output, every run, every
|
|
87
|
+
* machine. Zero dependencies, zero network, sync-fast (async only to satisfy
|
|
88
|
+
* the `InfluenceScorer` seam). Never touches `args.embedder` or `args.signal`.
|
|
89
|
+
*
|
|
90
|
+
* Honest claim: ranked WORD-OVERLAP proxies — cheaper and blinder than the
|
|
91
|
+
* embedding scorer (paraphrase = miss). NOT causal attribution — see module
|
|
92
|
+
* docs.
|
|
93
|
+
*
|
|
94
|
+
* @throws on duplicate evidence ids or invalid weights.
|
|
95
|
+
*/
|
|
96
|
+
export async function scoreLexicalInfluence(args) {
|
|
97
|
+
const weights = args.weights ?? DEFAULT_INFLUENCE_WEIGHTS;
|
|
98
|
+
assertValidWeights(weights, 'scoreLexicalInfluence');
|
|
99
|
+
const threshold = args.persistenceThreshold ?? DEFAULT_PERSISTENCE_THRESHOLD;
|
|
100
|
+
assertUniqueIds(args.evidence, 'scoreLexicalInfluence');
|
|
101
|
+
// One deduplicated tokenization pass over every distinct text.
|
|
102
|
+
const tokensByText = new Map();
|
|
103
|
+
const tokensOf = (text) => {
|
|
104
|
+
let set = tokensByText.get(text);
|
|
105
|
+
if (set === undefined) {
|
|
106
|
+
set = tokenize(text);
|
|
107
|
+
tokensByText.set(text, set);
|
|
108
|
+
}
|
|
109
|
+
return set;
|
|
110
|
+
};
|
|
111
|
+
const answerTokens = tokensOf(args.finalAnswerText);
|
|
112
|
+
const scored = args.evidence.map((item) => {
|
|
113
|
+
const evidenceTokens = tokensOf(item.text);
|
|
114
|
+
const ancestorTokens = item.ancestorTexts.map((t) => tokensOf(t));
|
|
115
|
+
const n = ancestorTokens.length;
|
|
116
|
+
let avgSum = 0;
|
|
117
|
+
let above = 0;
|
|
118
|
+
for (const ancestor of ancestorTokens) {
|
|
119
|
+
const sim = overlap(evidenceTokens, ancestor);
|
|
120
|
+
avgSum += sim;
|
|
121
|
+
if (sim > threshold)
|
|
122
|
+
above += 1;
|
|
123
|
+
}
|
|
124
|
+
const signals = {
|
|
125
|
+
fa: overlap(evidenceTokens, answerTokens),
|
|
126
|
+
avg: n === 0 ? 0 : avgSum / n,
|
|
127
|
+
persist: n === 0 ? 0 : above / n,
|
|
128
|
+
depth: structuralProximity(n),
|
|
129
|
+
};
|
|
130
|
+
const effective = adaptWeights(weights, n);
|
|
131
|
+
return {
|
|
132
|
+
id: item.id,
|
|
133
|
+
signals,
|
|
134
|
+
weights: effective.weights,
|
|
135
|
+
adapted: effective.adapted,
|
|
136
|
+
score: compositeScore(signals, effective.weights),
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
// Stable sort — equal scores keep evidence input order.
|
|
140
|
+
return scored.sort((a, b) => b.score - a.score);
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=lexical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexical.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/lexical.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,yBAAyB,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAwBtB;;oEAEoE;AACpE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAS;IACjC,GAAG;IACH,IAAI;IACJ,KAAK;IACL,KAAK;IACL,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,MAAM;IACN,IAAI;IACJ,KAAK;IACL,KAAK;IACL,MAAM;IACN,IAAI;IACJ,MAAM;IACN,IAAI;IACJ,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,GAAG;IACH,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,QAAQ;IACR,KAAK;IACL,OAAO;IACP,OAAO;IACP,QAAQ;IACR,IAAI;IACJ,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QACzD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QACpD,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;2EAC2E;AAC3E,SAAS,OAAO,CAAC,CAAsB,EAAE,CAAsB;IAC7D,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,CAAC,CAAC;IACrD,OAAO,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAA+B;IAE/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,yBAAyB,CAAC;IAC1D,kBAAkB,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,IAAI,6BAA6B,CAAC;IAC7E,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC;IAExD,+DAA+D;IAC/D,MAAM,YAAY,GAAG,IAAI,GAAG,EAAuB,CAAC;IACpD,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAe,EAAE;QAC7C,IAAI,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACrB,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAkB,EAAE;QACxD,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAElE,MAAM,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC;QAChC,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;YACtC,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;YAC9C,MAAM,IAAI,GAAG,CAAC;YACd,IAAI,GAAG,GAAG,SAAS;gBAAE,KAAK,IAAI,CAAC,CAAC;QAClC,CAAC;QAED,MAAM,OAAO,GAAiB;YAC5B,EAAE,EAAE,OAAO,CAAC,cAAc,EAAE,YAAY,CAAC;YACzC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;YAC7B,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;YAChC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC;SAC9B,CAAC;QACF,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAE3C,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,OAAO;YACP,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,KAAK,EAAE,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC;SAClD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -126,3 +126,8 @@ export declare function embedAll(embedder: Embedder, texts: readonly string[], s
|
|
|
126
126
|
* attributes the error to the actual caller.
|
|
127
127
|
*/
|
|
128
128
|
export declare function assertValidWeights(weights: InfluenceWeights, fnName?: string): void;
|
|
129
|
+
/**
|
|
130
|
+
* Validate that every evidence id is unique. Shared by `scoreInfluence` and
|
|
131
|
+
* `scoreLexicalInfluence` — `fnName` attributes the error to the actual caller.
|
|
132
|
+
*/
|
|
133
|
+
export declare function assertUniqueIds(evidence: readonly EvidenceInput[], fnName?: string): void;
|
|
@@ -225,11 +225,15 @@ export function assertValidWeights(weights, fnName = 'scoreInfluence') {
|
|
|
225
225
|
throw new Error(`${fnName}: all weights are zero — the composite would always be 0`);
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
|
-
|
|
228
|
+
/**
|
|
229
|
+
* Validate that every evidence id is unique. Shared by `scoreInfluence` and
|
|
230
|
+
* `scoreLexicalInfluence` — `fnName` attributes the error to the actual caller.
|
|
231
|
+
*/
|
|
232
|
+
export function assertUniqueIds(evidence, fnName = 'scoreInfluence') {
|
|
229
233
|
const seen = new Set();
|
|
230
234
|
for (const item of evidence) {
|
|
231
235
|
if (seen.has(item.id)) {
|
|
232
|
-
throw new Error(
|
|
236
|
+
throw new Error(`${fnName}: duplicate evidence id '${item.id}' — ids must be unique`);
|
|
233
237
|
}
|
|
234
238
|
seen.add(item.id);
|
|
235
239
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/signals.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/signals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named influence strategies — a plain-named descriptor AROUND the already-
|
|
3
|
+
* public `InfluenceScorer` function seam, exactly the shape a host UI's
|
|
4
|
+
* strategy selector needs (mirrors the `EntryScorer` / `ConfidenceStrategy`
|
|
5
|
+
* "name shown in any strategy picker" precedent).
|
|
6
|
+
*
|
|
7
|
+
* A strategy is `{ name, description, requirements, scorer }`. Two ship:
|
|
8
|
+
* • `semanticAlignmentStrategy` — the FDL four-signal embedding composite
|
|
9
|
+
* (`scoreInfluence`). The default; needs an embedder.
|
|
10
|
+
* • `lexicalOverlapStrategy` — deterministic word overlap
|
|
11
|
+
* (`scoreLexicalInfluence`). Free, zero deps; requires nothing.
|
|
12
|
+
*
|
|
13
|
+
* `listInfluenceStrategies()` enumerates them so a selector can render the
|
|
14
|
+
* two options and grey out what the host can't run (`requirements`).
|
|
15
|
+
*
|
|
16
|
+
* Sugar, not a replacement: `localizeContextBug({ scorer })` still accepts a
|
|
17
|
+
* bare `InfluenceScorer` function; it now ALSO accepts one of these.
|
|
18
|
+
*/
|
|
19
|
+
import type { InfluenceScorer } from './signals.js';
|
|
20
|
+
/**
|
|
21
|
+
* What a strategy needs the host to supply before it can run. A selector UI
|
|
22
|
+
* greys out strategies whose requirements the host can't meet. `'embedder'`
|
|
23
|
+
* is the only well-known value today; the type stays open for consumer
|
|
24
|
+
* strategies (`'llm'`, `'reference-run'`, …).
|
|
25
|
+
*/
|
|
26
|
+
export type InfluenceStrategyRequirement = 'embedder' | (string & Record<never, never>);
|
|
27
|
+
/**
|
|
28
|
+
* A NAMED influence-scoring strategy — an `InfluenceScorer` plus the metadata
|
|
29
|
+
* a strategy picker needs. Sugar AROUND the function seam, not a replacement:
|
|
30
|
+
* `localizeContextBug({ scorer })` accepts either a bare `InfluenceScorer` or
|
|
31
|
+
* one of these.
|
|
32
|
+
*/
|
|
33
|
+
export interface InfluenceStrategy {
|
|
34
|
+
/** Stable kebab-case id — shown in a selector, echoed on `ContextBugReport.rankedBy`. */
|
|
35
|
+
readonly name: string;
|
|
36
|
+
/** One-or-two-sentence plain description for the picker, honesty caveat included. */
|
|
37
|
+
readonly description: string;
|
|
38
|
+
/** What the host must supply to run this strategy (empty = runs anywhere, $0). */
|
|
39
|
+
readonly requirements: readonly InfluenceStrategyRequirement[];
|
|
40
|
+
/** The scorer itself — plugs into `localizeContextBug({ scorer })` directly. */
|
|
41
|
+
readonly scorer: InfluenceScorer;
|
|
42
|
+
}
|
|
43
|
+
/** The DEFAULT: the FDL four-signal embedding composite (`scoreInfluence`). */
|
|
44
|
+
export declare const semanticAlignmentStrategy: InfluenceStrategy;
|
|
45
|
+
/** The cheap option: deterministic word overlap (`scoreLexicalInfluence`), zero deps. */
|
|
46
|
+
export declare const lexicalOverlapStrategy: InfluenceStrategy;
|
|
47
|
+
/**
|
|
48
|
+
* The built-in strategies, default first. Frozen — a host UI renders its
|
|
49
|
+
* selector straight off this (concat your own custom strategies after).
|
|
50
|
+
*/
|
|
51
|
+
export declare function listInfluenceStrategies(): readonly InfluenceStrategy[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { scoreInfluence } from './signals.js';
|
|
2
|
+
import { scoreLexicalInfluence } from './lexical.js';
|
|
3
|
+
/** The DEFAULT: the FDL four-signal embedding composite (`scoreInfluence`). */
|
|
4
|
+
export const semanticAlignmentStrategy = Object.freeze({
|
|
5
|
+
name: 'semantic-alignment',
|
|
6
|
+
description: 'Ranks sources by how semantically close their content is to the final answer, using ' +
|
|
7
|
+
'embeddings (the four-signal composite). The default. Needs an embedder; scores are a ' +
|
|
8
|
+
'proxy for alignment, never proof of cause.',
|
|
9
|
+
requirements: Object.freeze(['embedder']),
|
|
10
|
+
scorer: scoreInfluence,
|
|
11
|
+
});
|
|
12
|
+
/** The cheap option: deterministic word overlap (`scoreLexicalInfluence`), zero deps. */
|
|
13
|
+
export const lexicalOverlapStrategy = Object.freeze({
|
|
14
|
+
name: 'lexical-overlap',
|
|
15
|
+
description: 'Ranks sources by plain word overlap with the final answer. Deterministic, free, no ' +
|
|
16
|
+
'dependencies — the simpler, cheaper option. Misses paraphrases; same proxy caveat: ' +
|
|
17
|
+
'overlap is not cause.',
|
|
18
|
+
requirements: Object.freeze([]),
|
|
19
|
+
scorer: scoreLexicalInfluence,
|
|
20
|
+
});
|
|
21
|
+
const BUILT_IN = Object.freeze([semanticAlignmentStrategy, lexicalOverlapStrategy]);
|
|
22
|
+
/**
|
|
23
|
+
* The built-in strategies, default first. Frozen — a host UI renders its
|
|
24
|
+
* selector straight off this (concat your own custom strategies after).
|
|
25
|
+
*/
|
|
26
|
+
export function listInfluenceStrategies() {
|
|
27
|
+
return BUILT_IN;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=strategies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategies.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/strategies.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AA2BrD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,yBAAyB,GAAsB,MAAM,CAAC,MAAM,CAAC;IACxE,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,sFAAsF;QACtF,uFAAuF;QACvF,4CAA4C;IAC9C,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,CAAU,CAAC;IAClD,MAAM,EAAE,cAAc;CACvB,CAAC,CAAC;AAEH,yFAAyF;AACzF,MAAM,CAAC,MAAM,sBAAsB,GAAsB,MAAM,CAAC,MAAM,CAAC;IACrE,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,qFAAqF;QACrF,qFAAqF;QACrF,uBAAuB;IACzB,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,EAAW,CAAC;IACxC,MAAM,EAAE,qBAAqB;CAC9B,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,yBAAyB,EAAE,sBAAsB,CAAC,CAAC,CAAC;AAEpF;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* recorded-chat — the session-scoped turn recorder over the context-bisect
|
|
3
|
+
* product loop. Absorbs the three correctness traps every chat host re-writes
|
|
4
|
+
* (per-turn artifact freezing, byte-exact history threading, same-factory
|
|
5
|
+
* runner derivation) while COMPOSING with the 7.5 surface, not duplicating it.
|
|
6
|
+
*
|
|
7
|
+
* Exported from `agentfootprint/debug` (every symbol it composes with lives
|
|
8
|
+
* there). Named exports — `export *` is not the house style.
|
|
9
|
+
*/
|
|
10
|
+
export { recordedChat } from './recordedChat.js';
|
|
11
|
+
export type { ChatFormat, ChatMessage, ChatTurn, ForkOptions, ForkOrigin, MakeChatAgent, ReasonOptions, RecordedChat, RecordedChatOptions, RerunTurnOptions, SendOptions, } from './types.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* recorded-chat — the session-scoped turn recorder over the context-bisect
|
|
3
|
+
* product loop. Absorbs the three correctness traps every chat host re-writes
|
|
4
|
+
* (per-turn artifact freezing, byte-exact history threading, same-factory
|
|
5
|
+
* runner derivation) while COMPOSING with the 7.5 surface, not duplicating it.
|
|
6
|
+
*
|
|
7
|
+
* Exported from `agentfootprint/debug` (every symbol it composes with lives
|
|
8
|
+
* there). Named exports — `export *` is not the house style.
|
|
9
|
+
*/
|
|
10
|
+
export { recordedChat } from './recordedChat.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/recorded-chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* recordedChat — the session-scoped turn recorder.
|
|
3
|
+
*
|
|
4
|
+
* `recordedChat({ makeAgent })` returns a `RecordedChat`: `send()` runs one
|
|
5
|
+
* recorded turn through the consumer's agent factory and freezes that turn's
|
|
6
|
+
* evidence immediately; `reason(k)` / `rerunTurn(k)` / `fork(k)` are the
|
|
7
|
+
* per-turn transparency loop, composing with the existing context-bisect
|
|
8
|
+
* surface (`localizeContextBug`, `rerunWithoutSources`) rather than
|
|
9
|
+
* duplicating it. See `./types.ts` for the three traps this owns.
|
|
10
|
+
*
|
|
11
|
+
* Compose-don't-inherit house style: a module-private session class,
|
|
12
|
+
* factory-returned; no base classes.
|
|
13
|
+
*/
|
|
14
|
+
import type { RecordedChat, RecordedChatOptions } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Record a chat turn-by-turn so any reply can be explained, counterfactually
|
|
17
|
+
* re-run, and forked — without re-writing the correctness-critical glue every
|
|
18
|
+
* chat host gets subtly wrong. See the [recordedChat guide](doc:recorded-chat).
|
|
19
|
+
*/
|
|
20
|
+
export declare function recordedChat(options: RecordedChatOptions): RecordedChat;
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* recordedChat — the session-scoped turn recorder.
|
|
3
|
+
*
|
|
4
|
+
* `recordedChat({ makeAgent })` returns a `RecordedChat`: `send()` runs one
|
|
5
|
+
* recorded turn through the consumer's agent factory and freezes that turn's
|
|
6
|
+
* evidence immediately; `reason(k)` / `rerunTurn(k)` / `fork(k)` are the
|
|
7
|
+
* per-turn transparency loop, composing with the existing context-bisect
|
|
8
|
+
* surface (`localizeContextBug`, `rerunWithoutSources`) rather than
|
|
9
|
+
* duplicating it. See `./types.ts` for the three traps this owns.
|
|
10
|
+
*
|
|
11
|
+
* Compose-don't-inherit house style: a module-private session class,
|
|
12
|
+
* factory-returned; no base classes.
|
|
13
|
+
*/
|
|
14
|
+
import { llmCallIdsFromEvents, localizeContextBug, rerunWithoutSources, } from '../context-bisect/index.js';
|
|
15
|
+
const DEFAULT_HEADER = 'Recent conversation:';
|
|
16
|
+
const DEFAULT_USER_LABEL = 'User';
|
|
17
|
+
const DEFAULT_ASSISTANT_LABEL = 'Assistant';
|
|
18
|
+
/** Deterministic key for spec dedup — recursively sorts object keys. */
|
|
19
|
+
function canonicalKey(value) {
|
|
20
|
+
return JSON.stringify(value, (_key, val) => {
|
|
21
|
+
if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
|
|
22
|
+
const sorted = {};
|
|
23
|
+
for (const k of Object.keys(val).sort()) {
|
|
24
|
+
sorted[k] = val[k];
|
|
25
|
+
}
|
|
26
|
+
return sorted;
|
|
27
|
+
}
|
|
28
|
+
return val;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Union of ablation specs, deduped by canonical JSON (order-preserving, first wins). */
|
|
32
|
+
function dedupeSpecs(specs) {
|
|
33
|
+
const seen = new Set();
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const spec of specs) {
|
|
36
|
+
const key = canonicalKey(spec);
|
|
37
|
+
if (seen.has(key))
|
|
38
|
+
continue;
|
|
39
|
+
seen.add(key);
|
|
40
|
+
out.push(spec);
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
class RecordedChatSession {
|
|
45
|
+
makeAgentFn;
|
|
46
|
+
formatOpt;
|
|
47
|
+
header;
|
|
48
|
+
userLabel;
|
|
49
|
+
assistantLabel;
|
|
50
|
+
/** seed + one (user, assistant) pair per recorded turn. */
|
|
51
|
+
entries;
|
|
52
|
+
seedMessages;
|
|
53
|
+
removedSpecs;
|
|
54
|
+
turnsInternal = [];
|
|
55
|
+
reports = new Map();
|
|
56
|
+
/** result -> turnIndex, the in-process fork-provenance guard. */
|
|
57
|
+
rerunOwner = new WeakMap();
|
|
58
|
+
sending = false;
|
|
59
|
+
forkedFromValue = undefined;
|
|
60
|
+
constructor(options) {
|
|
61
|
+
this.makeAgentFn = options.makeAgent;
|
|
62
|
+
this.formatOpt = options.format;
|
|
63
|
+
this.header = options.format?.header ?? DEFAULT_HEADER;
|
|
64
|
+
this.userLabel = options.format?.userLabel ?? DEFAULT_USER_LABEL;
|
|
65
|
+
this.assistantLabel = options.format?.assistantLabel ?? DEFAULT_ASSISTANT_LABEL;
|
|
66
|
+
this.seedMessages = Object.freeze((options.seed ?? []).map((m) => ({ ...m })));
|
|
67
|
+
this.entries = [...this.seedMessages];
|
|
68
|
+
this.removedSpecs = Object.freeze([...(options.removed ?? [])]);
|
|
69
|
+
}
|
|
70
|
+
get turns() {
|
|
71
|
+
return this.turnsInternal;
|
|
72
|
+
}
|
|
73
|
+
get seed() {
|
|
74
|
+
return this.seedMessages;
|
|
75
|
+
}
|
|
76
|
+
get removed() {
|
|
77
|
+
return this.removedSpecs;
|
|
78
|
+
}
|
|
79
|
+
get forkedFrom() {
|
|
80
|
+
return this.forkedFromValue;
|
|
81
|
+
}
|
|
82
|
+
renderLine(message) {
|
|
83
|
+
const label = message.role === 'user' ? this.userLabel : this.assistantLabel;
|
|
84
|
+
return `${label}: ${message.text}`;
|
|
85
|
+
}
|
|
86
|
+
composeMessage(lines, userMessage) {
|
|
87
|
+
if (lines.length === 0)
|
|
88
|
+
return `${this.userLabel}: ${userMessage}`;
|
|
89
|
+
return `${this.header}\n${lines.join('\n')}\n\n${this.userLabel}: ${userMessage}`;
|
|
90
|
+
}
|
|
91
|
+
async send(userMessage, options) {
|
|
92
|
+
if (this.sending) {
|
|
93
|
+
throw new Error('recordedChat.send: a turn is already in flight — one turn at a time; await the previous send');
|
|
94
|
+
}
|
|
95
|
+
this.sending = true;
|
|
96
|
+
try {
|
|
97
|
+
// Compose the message ONCE, at record time, from the frozen transcript
|
|
98
|
+
// (trap 2 — byte-exact history is threaded HERE and replayed verbatim).
|
|
99
|
+
const transcriptBefore = Object.freeze(this.entries.map((m) => this.renderLine(m)));
|
|
100
|
+
const message = this.composeMessage(transcriptBefore, userMessage);
|
|
101
|
+
const agent = await this.makeAgentFn({ specs: this.removedSpecs, seed: 0 });
|
|
102
|
+
const events = [];
|
|
103
|
+
// Attach the tap BEFORE run() — listener-presence gating drops events
|
|
104
|
+
// otherwise (agentfootprint invariant). Unsubscribe in finally.
|
|
105
|
+
const off = agent.on('*', (event) => {
|
|
106
|
+
events.push(event);
|
|
107
|
+
});
|
|
108
|
+
let out;
|
|
109
|
+
try {
|
|
110
|
+
const raw = await agent.run({
|
|
111
|
+
message,
|
|
112
|
+
...(options?.identity !== undefined ? { identity: options.identity } : {}),
|
|
113
|
+
});
|
|
114
|
+
if (typeof raw !== 'string') {
|
|
115
|
+
throw new Error("recordedChat.send: the run paused (askHuman/checkIn) — recorded chat turns don't " +
|
|
116
|
+
'support pauses; drive pausing agents with agent.run() directly');
|
|
117
|
+
}
|
|
118
|
+
out = raw;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
off();
|
|
122
|
+
}
|
|
123
|
+
// Capture IMMEDIATELY (trap 1) — getLastSnapshot() is last-run-only, but
|
|
124
|
+
// the per-turn agent is discarded here, so clobbering is impossible.
|
|
125
|
+
const snapshot = agent.getLastSnapshot();
|
|
126
|
+
if (snapshot === undefined) {
|
|
127
|
+
throw new Error('recordedChat.send: the run produced no snapshot — cannot record the turn');
|
|
128
|
+
}
|
|
129
|
+
const lastLlmCallId = llmCallIdsFromEvents(events).at(-1);
|
|
130
|
+
const index = this.turnsInternal.length;
|
|
131
|
+
this.entries.push({ role: 'user', text: userMessage }, { role: 'assistant', text: out });
|
|
132
|
+
const turn = Object.freeze({
|
|
133
|
+
index,
|
|
134
|
+
userMessage,
|
|
135
|
+
reply: out,
|
|
136
|
+
message,
|
|
137
|
+
transcriptBefore,
|
|
138
|
+
artifacts: Object.freeze({ snapshot, events: Object.freeze(events) }),
|
|
139
|
+
lastLlmCallId,
|
|
140
|
+
identity: options?.identity,
|
|
141
|
+
});
|
|
142
|
+
this.turnsInternal.push(turn);
|
|
143
|
+
return turn;
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
this.sending = false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
turn(k) {
|
|
150
|
+
const n = this.turnsInternal.length;
|
|
151
|
+
if (!Number.isInteger(k) || k < 0 || k >= n) {
|
|
152
|
+
const range = n === 0 ? '(no turns recorded yet)' : `0..${n - 1}`;
|
|
153
|
+
throw new RangeError(`recordedChat.turn: no turn ${k} — valid range is ${range}`);
|
|
154
|
+
}
|
|
155
|
+
return this.turnsInternal[k];
|
|
156
|
+
}
|
|
157
|
+
async reason(k, options) {
|
|
158
|
+
const turn = this.turn(k);
|
|
159
|
+
const { fresh, atStep, ...rest } = options;
|
|
160
|
+
const memo = this.reports.get(k);
|
|
161
|
+
if (memo !== undefined && fresh !== true)
|
|
162
|
+
return memo;
|
|
163
|
+
const resolvedAtStep = atStep ?? turn.lastLlmCallId;
|
|
164
|
+
const report = await localizeContextBug({
|
|
165
|
+
...rest,
|
|
166
|
+
artifacts: turn.artifacts,
|
|
167
|
+
...(resolvedAtStep !== undefined ? { atStep: resolvedAtStep } : {}),
|
|
168
|
+
});
|
|
169
|
+
this.reports.set(k, report);
|
|
170
|
+
return report;
|
|
171
|
+
}
|
|
172
|
+
async rerunTurn(k, options) {
|
|
173
|
+
const turn = this.turn(k);
|
|
174
|
+
const { report: reportOption, ...rerunRest } = options;
|
|
175
|
+
let report = reportOption ?? this.reports.get(k);
|
|
176
|
+
if (report === undefined) {
|
|
177
|
+
report = await this.reason(k, { embedder: options.embedder });
|
|
178
|
+
}
|
|
179
|
+
// Derive the runner from the SAME factory (traps 2 + 3): the frozen
|
|
180
|
+
// message bytes are replayed verbatim, and the session's persistent
|
|
181
|
+
// removals ALWAYS apply on top of the probe's specs (empty specs = the
|
|
182
|
+
// baseline probe, which replays the identical turn).
|
|
183
|
+
const runner = async (specs, run) => {
|
|
184
|
+
const agent = await this.makeAgentFn({
|
|
185
|
+
specs: [...this.removedSpecs, ...specs],
|
|
186
|
+
seed: run.seed,
|
|
187
|
+
});
|
|
188
|
+
const out = await agent.run({
|
|
189
|
+
message: turn.message,
|
|
190
|
+
...(turn.identity !== undefined ? { identity: turn.identity } : {}),
|
|
191
|
+
});
|
|
192
|
+
if (typeof out !== 'string') {
|
|
193
|
+
throw new Error('recordedChat.rerunTurn: a probe run paused (askHuman/checkIn) — recorded chat re-runs ' +
|
|
194
|
+
"don't support pauses");
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
};
|
|
198
|
+
const result = await rerunWithoutSources({
|
|
199
|
+
...rerunRest,
|
|
200
|
+
report,
|
|
201
|
+
runner,
|
|
202
|
+
originalAnswer: turn.reply,
|
|
203
|
+
});
|
|
204
|
+
this.rerunOwner.set(result, k);
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
fork(k, options) {
|
|
208
|
+
const turn = this.turn(k);
|
|
209
|
+
const fromRerun = options?.fromRerun;
|
|
210
|
+
if (fromRerun !== undefined && this.rerunOwner.get(fromRerun) !== k) {
|
|
211
|
+
throw new Error(`recordedChat.fork: that result was not produced by this session's rerunTurn for turn ${k} — ` +
|
|
212
|
+
're-run this turn first, then fork');
|
|
213
|
+
}
|
|
214
|
+
const reply = fromRerun?.answer ?? turn.reply;
|
|
215
|
+
const cut = this.seedMessages.length + 2 * k;
|
|
216
|
+
const seed = [
|
|
217
|
+
...this.entries.slice(0, cut).map((m) => ({ ...m })),
|
|
218
|
+
{ role: 'user', text: turn.userMessage },
|
|
219
|
+
{ role: 'assistant', text: reply },
|
|
220
|
+
];
|
|
221
|
+
const removed = dedupeSpecs([...this.removedSpecs, ...(fromRerun?.removed ?? [])]);
|
|
222
|
+
const child = new RecordedChatSession({
|
|
223
|
+
makeAgent: this.makeAgentFn,
|
|
224
|
+
...(this.formatOpt !== undefined ? { format: this.formatOpt } : {}),
|
|
225
|
+
seed,
|
|
226
|
+
removed,
|
|
227
|
+
});
|
|
228
|
+
child.forkedFromValue = { parent: this, turnIndex: k, viaRerun: fromRerun !== undefined };
|
|
229
|
+
return child;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Record a chat turn-by-turn so any reply can be explained, counterfactually
|
|
234
|
+
* re-run, and forked — without re-writing the correctness-critical glue every
|
|
235
|
+
* chat host gets subtly wrong. See the [recordedChat guide](doc:recorded-chat).
|
|
236
|
+
*/
|
|
237
|
+
export function recordedChat(options) {
|
|
238
|
+
return new RecordedChatSession(options);
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=recordedChat.js.map
|