agentfootprint 7.2.0 → 7.3.1

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.
Files changed (61) hide show
  1. package/CLAUDE.md +1 -1
  2. package/dist/adapters/llm/AnthropicProvider.js +5 -1
  3. package/dist/adapters/llm/AnthropicProvider.js.map +1 -1
  4. package/dist/debug.js +5 -2
  5. package/dist/debug.js.map +1 -1
  6. package/dist/embedders/index.js +139 -0
  7. package/dist/embedders/index.js.map +1 -0
  8. package/dist/esm/adapters/llm/AnthropicProvider.d.ts +12 -0
  9. package/dist/esm/adapters/llm/AnthropicProvider.js +5 -1
  10. package/dist/esm/adapters/llm/AnthropicProvider.js.map +1 -1
  11. package/dist/esm/debug.d.ts +1 -1
  12. package/dist/esm/debug.js +1 -1
  13. package/dist/esm/debug.js.map +1 -1
  14. package/dist/esm/embedders/index.d.ts +49 -0
  15. package/dist/esm/embedders/index.js +110 -0
  16. package/dist/esm/embedders/index.js.map +1 -0
  17. package/dist/esm/lib/influence-core/attribute.d.ts +27 -0
  18. package/dist/esm/lib/influence-core/attribute.js +91 -0
  19. package/dist/esm/lib/influence-core/attribute.js.map +1 -0
  20. package/dist/esm/lib/influence-core/explain.d.ts +67 -0
  21. package/dist/esm/lib/influence-core/explain.js +80 -0
  22. package/dist/esm/lib/influence-core/explain.js.map +1 -0
  23. package/dist/esm/lib/influence-core/index.d.ts +4 -1
  24. package/dist/esm/lib/influence-core/index.js +3 -0
  25. package/dist/esm/lib/influence-core/index.js.map +1 -1
  26. package/dist/esm/lib/influence-core/snippets.d.ts +45 -0
  27. package/dist/esm/lib/influence-core/snippets.js +114 -0
  28. package/dist/esm/lib/influence-core/snippets.js.map +1 -0
  29. package/dist/esm/lib/influence-core/types.d.ts +50 -0
  30. package/dist/esm/recorders/observability/ToolChoiceRecorder.d.ts +32 -2
  31. package/dist/esm/recorders/observability/ToolChoiceRecorder.js +24 -6
  32. package/dist/esm/recorders/observability/ToolChoiceRecorder.js.map +1 -1
  33. package/dist/lib/influence-core/attribute.js +95 -0
  34. package/dist/lib/influence-core/attribute.js.map +1 -0
  35. package/dist/lib/influence-core/explain.js +84 -0
  36. package/dist/lib/influence-core/explain.js.map +1 -0
  37. package/dist/lib/influence-core/index.js +7 -1
  38. package/dist/lib/influence-core/index.js.map +1 -1
  39. package/dist/lib/influence-core/snippets.js +118 -0
  40. package/dist/lib/influence-core/snippets.js.map +1 -0
  41. package/dist/recorders/observability/ToolChoiceRecorder.js +24 -6
  42. package/dist/recorders/observability/ToolChoiceRecorder.js.map +1 -1
  43. package/dist/types/adapters/llm/AnthropicProvider.d.ts +12 -0
  44. package/dist/types/adapters/llm/AnthropicProvider.d.ts.map +1 -1
  45. package/dist/types/debug.d.ts +1 -1
  46. package/dist/types/debug.d.ts.map +1 -1
  47. package/dist/types/embedders/index.d.ts +50 -0
  48. package/dist/types/embedders/index.d.ts.map +1 -0
  49. package/dist/types/lib/influence-core/attribute.d.ts +28 -0
  50. package/dist/types/lib/influence-core/attribute.d.ts.map +1 -0
  51. package/dist/types/lib/influence-core/explain.d.ts +68 -0
  52. package/dist/types/lib/influence-core/explain.d.ts.map +1 -0
  53. package/dist/types/lib/influence-core/index.d.ts +4 -1
  54. package/dist/types/lib/influence-core/index.d.ts.map +1 -1
  55. package/dist/types/lib/influence-core/snippets.d.ts +46 -0
  56. package/dist/types/lib/influence-core/snippets.d.ts.map +1 -0
  57. package/dist/types/lib/influence-core/types.d.ts +50 -0
  58. package/dist/types/lib/influence-core/types.d.ts.map +1 -1
  59. package/dist/types/recorders/observability/ToolChoiceRecorder.d.ts +32 -2
  60. package/dist/types/recorders/observability/ToolChoiceRecorder.d.ts.map +1 -1
  61. package/package.json +27 -4
@@ -0,0 +1,91 @@
1
+ /**
2
+ * attributeChoice — which context UNIT best explains one tool choice
3
+ * (the transpose of `scoreMargin`).
4
+ *
5
+ * `scoreMargin` fixes the context and ranks candidate tools against it —
6
+ * so a CONSTANT part of the context (the system prompt, identical on every
7
+ * call) is excluded, because it adds no power to tell one call apart from
8
+ * another. But that exclusion also makes procedural picks unexplainable:
9
+ * the agent calls `whats_here` because a RULE in the system prompt says
10
+ * "orient first", and margin scoring can never see that rule.
11
+ *
12
+ * `attributeChoice` fixes the CHOSEN TOOL and ranks the context units
13
+ * against it. Here a constant-but-load-bearing rule is exactly what we
14
+ * want surfaced: cosine(tool, "call whats_here first") is high and
15
+ * specific, so the answer becomes a citation — "picked because rule-1".
16
+ * The units are tagged by channel (`'system' | 'task' | 'result' | …`) so
17
+ * the result also reports HOW procedural vs topical the pick was.
18
+ *
19
+ * Pattern: pure async function, embedder-injected. No agent/runtime
20
+ * imports — `src/lib/influence-core/` leaf, same as `scoreMargin`.
21
+ *
22
+ * Honest claim (RFC-002 §2): `score` is embedding geometry between the
23
+ * tool text and each instruction unit — a PROXY for which instruction the
24
+ * pick ALIGNS with, never proof the model used that rule. This is Tier 1
25
+ * (similarity); Tier 3 (counterfactual ablation of each unit) is the
26
+ * ground truth that would validate it.
27
+ */
28
+ import { cosineSimilarity } from '../../memory/embedding/cosine.js';
29
+ /**
30
+ * Embed the tool text and every unit once (deduplicated batch), rank the
31
+ * units by cosine to the tool, and report the top unit plus the per-channel
32
+ * share of positive similarity mass.
33
+ *
34
+ * Fail-loud validation: empty units or duplicate unit ids throw — those are
35
+ * caller wiring bugs, not runtime conditions.
36
+ */
37
+ export async function attributeChoice(args) {
38
+ const { tool, units, embedder } = args;
39
+ validate(units);
40
+ // One deduplicated embedding pass: the tool text + each distinct unit text.
41
+ const distinct = [...new Set([tool.text, ...units.map((u) => u.text)])];
42
+ const vectors = embedder.embedBatch
43
+ ? await embedder.embedBatch({ texts: distinct, ...(args.signal ? { signal: args.signal } : {}) })
44
+ : await sequentialEmbed(embedder, distinct, args.signal);
45
+ const vectorByText = new Map();
46
+ for (let i = 0; i < distinct.length; i++)
47
+ vectorByText.set(distinct[i], vectors[i]);
48
+ const toolVec = vectorByText.get(tool.text);
49
+ const scored = units.map((u) => ({
50
+ id: u.id,
51
+ channel: u.channel,
52
+ score: cosineSimilarity(toolVec, vectorByText.get(u.text)),
53
+ }));
54
+ // Stable sort — ties keep input order.
55
+ scored.sort((a, b) => b.score - a.score);
56
+ // Per-channel share of POSITIVE mass (negatives are anti-alignment, not
57
+ // evidence FOR a channel — clamp to 0 so they neither add nor subtract).
58
+ const positiveByChannel = {};
59
+ let total = 0;
60
+ for (const s of scored) {
61
+ const w = Math.max(0, s.score);
62
+ if (w === 0)
63
+ continue;
64
+ positiveByChannel[s.channel] = (positiveByChannel[s.channel] ?? 0) + w;
65
+ total += w;
66
+ }
67
+ const byChannel = {};
68
+ if (total > 0)
69
+ for (const [ch, w] of Object.entries(positiveByChannel))
70
+ byChannel[ch] = w / total;
71
+ return { tool: tool.name, units: scored, top: scored[0], byChannel };
72
+ }
73
+ async function sequentialEmbed(embedder, texts, signal) {
74
+ const out = [];
75
+ for (const text of texts)
76
+ out.push(await embedder.embed({ text, ...(signal ? { signal } : {}) }));
77
+ return out;
78
+ }
79
+ function validate(units) {
80
+ if (units.length === 0) {
81
+ throw new Error('attributeChoice: units must be non-empty — nothing to attribute to');
82
+ }
83
+ const ids = new Set();
84
+ for (const u of units) {
85
+ if (ids.has(u.id)) {
86
+ throw new Error(`attributeChoice: duplicate unit id '${u.id}' — ids must be unique`);
87
+ }
88
+ ids.add(u.id);
89
+ }
90
+ }
91
+ //# sourceMappingURL=attribute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/attribute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import type { AttributionUnit, Embedder, UnitScore } from './types.js';
2
+ export interface ExplainChoiceArgs {
3
+ /**
4
+ * The chosen tool being explained. `text` is what gets embedded — pass
5
+ * name + description (the name matters: a data snippet that NAMES the
6
+ * thing the tool acts on, e.g. "id: d42", is its strongest citation).
7
+ */
8
+ readonly tool: {
9
+ readonly name: string;
10
+ readonly text: string;
11
+ };
12
+ /**
13
+ * The context units, tagged by channel — e.g. `'system'` rules,
14
+ * the `'task'`, `'data'` snippets from `snippetUnits`. Channels are
15
+ * free-form strings; the verdict reports whatever labels it is given.
16
+ */
17
+ readonly units: readonly AttributionUnit[];
18
+ /** Injected embedder. Wrap in an `EmbeddingCache` so rule texts embed once. */
19
+ readonly embedder: Embedder;
20
+ /** Abort signal threaded to the embedder (network backends). */
21
+ readonly signal?: AbortSignal;
22
+ }
23
+ /** One channel's verdict: how much of the pick's positive similarity
24
+ * mass it owns, and the best unit inside it to quote. */
25
+ export interface ChannelVerdict {
26
+ readonly channel: string;
27
+ /**
28
+ * 0..1 share of POSITIVE similarity mass (negatives are clamped out,
29
+ * same as `attributeChoice.byChannel`). Shares across all channels sum
30
+ * to ~1 — or are all 0 when no unit had positive similarity.
31
+ */
32
+ readonly share: number;
33
+ /** The best-scoring unit IN this channel, text included for quoting.
34
+ * Omitted only when the channel has no units. */
35
+ readonly top?: UnitScore & {
36
+ readonly text: string;
37
+ };
38
+ }
39
+ /** The full explanation for one tool pick — `attributeChoice` reshaped
40
+ * for display: text carried through, channels ranked. */
41
+ export interface ChoiceExplanation {
42
+ /** The chosen tool being explained. */
43
+ readonly tool: string;
44
+ /**
45
+ * One verdict per channel present in the units, sorted by share
46
+ * descending (ties keep first-appearance order). Zero-share channels
47
+ * are listed too — absence of pull is part of the verdict.
48
+ */
49
+ readonly channels: readonly ChannelVerdict[];
50
+ /** The overall best unit — the citation ("picked because …"). */
51
+ readonly top: UnitScore & {
52
+ readonly text: string;
53
+ };
54
+ /** Every unit ranked descending (ties keep input order), text included. */
55
+ readonly units: readonly (UnitScore & {
56
+ readonly text: string;
57
+ })[];
58
+ }
59
+ /**
60
+ * Run `attributeChoice` and reshape the result for a UI: join each unit's
61
+ * text back by id, pick the best unit per channel, and rank the channels
62
+ * by their share of positive similarity mass.
63
+ *
64
+ * Fail-loud validation is inherited from `attributeChoice`: empty units
65
+ * or duplicate unit ids throw — caller wiring bugs, not runtime conditions.
66
+ */
67
+ export declare function explainChoice(args: ExplainChoiceArgs): Promise<ChoiceExplanation>;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * explainChoice — a UI-ready VERDICT for one tool pick: which context
3
+ * CHANNEL (system rules / user task / data from earlier tool results)
4
+ * best explains it, with the exact unit text to quote.
5
+ *
6
+ * Thin composite over `attributeChoice` — same math, zero duplication:
7
+ * the ranking, the top unit, and the per-channel share of positive
8
+ * similarity mass all come from the one existing engine. What this adds
9
+ * is presentation shape: the unit TEXT carried through (so a UI can
10
+ * quote the citation verbatim), a per-channel top unit, and a channels
11
+ * array sorted by share that lists EVERY channel present in the units —
12
+ * including zero-share ones, so "the data channel contributed nothing"
13
+ * is a visible verdict, not a missing key.
14
+ *
15
+ * Pattern: pure async function, embedder-injected. No agent/runtime
16
+ * imports — `src/lib/influence-core/` leaf, same as
17
+ * `attributeChoice` / `scoreMargin`.
18
+ *
19
+ * Honest claim (RFC-002 §2): every score and share here is embedding
20
+ * geometry between the tool text and each unit — a PROXY for which
21
+ * context the pick ALIGNS with, never proof the model used that unit.
22
+ * This is Tier 1 (similarity); counterfactual ablation (Tier 3) is the
23
+ * ground truth that would validate it.
24
+ */
25
+ import { attributeChoice } from './attribute.js';
26
+ /**
27
+ * Run `attributeChoice` and reshape the result for a UI: join each unit's
28
+ * text back by id, pick the best unit per channel, and rank the channels
29
+ * by their share of positive similarity mass.
30
+ *
31
+ * Fail-loud validation is inherited from `attributeChoice`: empty units
32
+ * or duplicate unit ids throw — caller wiring bugs, not runtime conditions.
33
+ */
34
+ export async function explainChoice(args) {
35
+ const attribution = await attributeChoice({
36
+ tool: args.tool,
37
+ units: args.units,
38
+ embedder: args.embedder,
39
+ ...(args.signal ? { signal: args.signal } : {}),
40
+ });
41
+ // Join the unit text back by id (ids are unique — attributeChoice validated).
42
+ const textById = new Map();
43
+ for (const u of args.units)
44
+ textById.set(u.id, u.text);
45
+ const withText = (score) => ({
46
+ ...score,
47
+ text: textById.get(score.id),
48
+ });
49
+ const ranked = attribution.units.map(withText);
50
+ // One verdict per channel, in first-appearance order (stable tiebreak),
51
+ // then sorted by share descending. `ranked` is already descending, so
52
+ // the first unit seen per channel is that channel's top.
53
+ const channelOrder = [];
54
+ const topByChannel = new Map();
55
+ for (const u of args.units) {
56
+ if (!channelOrder.includes(u.channel))
57
+ channelOrder.push(u.channel);
58
+ }
59
+ for (const unit of ranked) {
60
+ if (!topByChannel.has(unit.channel))
61
+ topByChannel.set(unit.channel, unit);
62
+ }
63
+ const channels = channelOrder.map((channel) => {
64
+ const top = topByChannel.get(channel);
65
+ return {
66
+ channel,
67
+ share: attribution.byChannel[channel] ?? 0,
68
+ ...(top ? { top } : {}),
69
+ };
70
+ });
71
+ // Stable sort — zero-share channels sink to the end, ties keep order.
72
+ channels.sort((a, b) => b.share - a.share);
73
+ return {
74
+ tool: attribution.tool,
75
+ channels,
76
+ top: withText(attribution.top),
77
+ units: ranked,
78
+ };
79
+ }
80
+ //# sourceMappingURL=explain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/explain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAsDjD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAuB;IACzD,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC;QACxC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAC,CAAC;IAEH,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK;QAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,CAAC,KAAgB,EAAyC,EAAE,CAAC,CAAC;QAC7E,GAAG,KAAK;QACR,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAW;KACvC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE/C,wEAAwE;IACxE,sEAAsE;IACtE,yDAAyD;IACzD,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAiD,CAAC;IAC9E,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACtE,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,QAAQ,GAAqB,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9D,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO;YACL,OAAO;YACP,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;YAC1C,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxB,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,sEAAsE;IACtE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAE3C,OAAO;QACL,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,QAAQ;QACR,GAAG,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC;QAC9B,KAAK,EAAE,MAAM;KACd,CAAC;AACJ,CAAC"}
@@ -24,7 +24,7 @@
24
24
  * embedding-geometry PROXY — semantic alignment, never model internals
25
25
  * and never causal attribution.
26
26
  */
27
- export type { CandidateScore, ConfidenceStrategy, EmbedArgs, EmbedBatchArgs, Embedder, EvidenceInput, InfluenceScore, InfluenceWeights, MarginCandidate, MarginResult, PairwiseSimilarityResult, RankingConfidence, SignalScores, SimilarityItem, SimilarityPair, } from './types.js';
27
+ export type { CandidateScore, AttributionUnit, ChoiceAttribution, ConfidenceStrategy, EmbedArgs, EmbedBatchArgs, Embedder, EvidenceInput, InfluenceScore, InfluenceWeights, MarginCandidate, MarginResult, PairwiseSimilarityResult, RankingConfidence, SignalScores, SimilarityItem, SimilarityPair, UnitScore, } from './types.js';
28
28
  export { DEFAULT_CLEAR_WINNER_MARGIN, DEFAULT_CLEAR_WINNER_RATIO, DEFAULT_INFLUENCE_WEIGHTS, DEFAULT_MARGIN_THRESHOLD, DEFAULT_PERSISTENCE_THRESHOLD, DEFAULT_SHORTLIST_BAND, } from './types.js';
29
29
  export { marginStrategy, rankingConfidence, ratioStrategy, type RankingConfidenceOptions, } from './attributability.js';
30
30
  export { scoreContrastiveInfluence, type ScoreContrastiveInfluenceArgs } from './contrastive.js';
@@ -32,3 +32,6 @@ export { contentHash, EmbeddingCache, embeddingCache, type EmbeddingCacheOptions
32
32
  export { adaptWeights, averageRelevancy, compositeScore, finalAnswerSimilarity, persistence, scoreInfluence, structuralProximity, type InfluenceScorer, type ScoreInfluenceArgs, } from './signals.js';
33
33
  export { pairwiseSimilarity, type PairwiseSimilarityArgs } from './similarity.js';
34
34
  export { scoreMargin, type ScoreMarginArgs } from './margin.js';
35
+ export { attributeChoice, type AttributeChoiceArgs } from './attribute.js';
36
+ export { explainChoice, type ChannelVerdict, type ChoiceExplanation, type ExplainChoiceArgs, } from './explain.js';
37
+ export { snippetUnits, type SnippetUnitsOptions } from './snippets.js';
@@ -31,4 +31,7 @@ export { contentHash, EmbeddingCache, embeddingCache, } from './cache.js';
31
31
  export { adaptWeights, averageRelevancy, compositeScore, finalAnswerSimilarity, persistence, scoreInfluence, structuralProximity, } from './signals.js';
32
32
  export { pairwiseSimilarity } from './similarity.js';
33
33
  export { scoreMargin } from './margin.js';
34
+ export { attributeChoice } from './attribute.js';
35
+ export { explainChoice, } from './explain.js';
36
+ export { snippetUnits } from './snippets.js';
34
37
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAmBH,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,GAEd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,yBAAyB,EAAsC,MAAM,kBAAkB,CAAC;AAEjG,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,GAGf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,cAAc,EACd,mBAAmB,GAGpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,kBAAkB,EAA+B,MAAM,iBAAiB,CAAC;AAElF,OAAO,EAAE,WAAW,EAAwB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAsBH,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,GAEd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,yBAAyB,EAAsC,MAAM,kBAAkB,CAAC;AAEjG,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,GAGf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,cAAc,EACd,mBAAmB,GAGpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,kBAAkB,EAA+B,MAAM,iBAAiB,CAAC;AAElF,OAAO,EAAE,WAAW,EAAwB,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,eAAe,EAA4B,MAAM,gBAAgB,CAAC;AAE3E,OAAO,EACL,aAAa,GAId,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,YAAY,EAA4B,MAAM,eAAe,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * snippetUnits — cut a tool result into citable AttributionUnits for the
3
+ * `'data'` channel.
4
+ *
5
+ * `explainChoice` can only credit the data channel with units to point
6
+ * at — a raw tool result (arbitrary JSON or prose) is not citable as one
7
+ * blob. This helper cuts it at the natural citation grain so a pick like
8
+ * "open dress d42" can be attributed to the exact search-result snippet
9
+ * that returned d42:
10
+ *
11
+ * • a string → one unit per sentence/line (non-empty, trimmed),
12
+ * • an array element that is an object → ONE unit summarizing it — its
13
+ * primitive fields joined as `key: value` pairs (a search hit, a row),
14
+ * • any other object → its primitive fields grouped into one unit,
15
+ * then the walk continues into nested objects/arrays,
16
+ * • null/undefined/booleans/empty strings/functions/symbols → skipped.
17
+ *
18
+ * Bounded and total: at most `max` units, each truncated to `maxLength`
19
+ * characters; circular references are guarded (WeakSet) — weird input
20
+ * yields fewer units, never a throw.
21
+ *
22
+ * Pattern: pure synchronous function, zero imports beyond the shared
23
+ * types — `src/lib/influence-core/` leaf. No embedding happens
24
+ * here; the units feed `attributeChoice` / `explainChoice`.
25
+ *
26
+ * Honest claim: this is a CUTTER, not a ranker — it decides what is
27
+ * quotable, not what mattered. Whether a snippet explains the pick is
28
+ * the (proxy) verdict of the similarity scoring downstream.
29
+ */
30
+ import type { AttributionUnit } from './types.js';
31
+ export interface SnippetUnitsOptions {
32
+ /** Channel tag stamped on every unit. Default `'data'`. */
33
+ readonly channel?: string;
34
+ /** Unit id prefix — ids become `'<prefix>-1'`, `'<prefix>-2'`, … Default `'data'`. */
35
+ readonly idPrefix?: string;
36
+ /** Cap on units returned. Default 12. */
37
+ readonly max?: number;
38
+ /** Cap on characters per unit text (ellipsis included). Default 200. */
39
+ readonly maxLength?: number;
40
+ }
41
+ /**
42
+ * Cut `value` (a tool result — arbitrary JSON value or prose string)
43
+ * into at most `max` citable units for the data channel.
44
+ */
45
+ export declare function snippetUnits(value: unknown, options?: SnippetUnitsOptions): AttributionUnit[];
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Cut `value` (a tool result — arbitrary JSON value or prose string)
3
+ * into at most `max` citable units for the data channel.
4
+ */
5
+ export function snippetUnits(value, options = {}) {
6
+ const channel = options.channel ?? 'data';
7
+ const idPrefix = options.idPrefix ?? 'data';
8
+ const max = options.max ?? 12;
9
+ const maxLength = options.maxLength ?? 200;
10
+ const texts = [];
11
+ collect(value, texts, max, new WeakSet());
12
+ return texts.map((text, i) => ({
13
+ id: `${idPrefix}-${i + 1}`,
14
+ channel,
15
+ text: truncate(text, maxLength),
16
+ }));
17
+ }
18
+ /** Walk `value` depth-first, pushing snippet texts until `max` is reached. */
19
+ function collect(value, out, max, seen) {
20
+ if (out.length >= max)
21
+ return;
22
+ if (typeof value === 'string') {
23
+ for (const sentence of splitSentences(value)) {
24
+ if (out.length >= max)
25
+ return;
26
+ out.push(sentence);
27
+ }
28
+ return;
29
+ }
30
+ if (isCitablePrimitive(value)) {
31
+ out.push(String(value));
32
+ return;
33
+ }
34
+ if (typeof value !== 'object' || value === null)
35
+ return; // boolean/null/undefined/function/symbol
36
+ if (seen.has(value))
37
+ return; // circular reference — already visited
38
+ seen.add(value);
39
+ if (Array.isArray(value)) {
40
+ for (const element of value) {
41
+ if (out.length >= max)
42
+ return;
43
+ if (isPlainRecord(element)) {
44
+ // The natural citation grain: one unit per row/hit, then walk its
45
+ // nested values (a hit may itself contain an array of hits).
46
+ if (seen.has(element))
47
+ continue;
48
+ seen.add(element);
49
+ const summary = summarizeFields(element);
50
+ if (summary !== '')
51
+ out.push(summary);
52
+ for (const nested of Object.values(element)) {
53
+ if (typeof nested === 'object' && nested !== null)
54
+ collect(nested, out, max, seen);
55
+ }
56
+ }
57
+ else {
58
+ collect(element, out, max, seen);
59
+ }
60
+ }
61
+ return;
62
+ }
63
+ // Non-array object: group its primitive fields into one unit, recurse
64
+ // into the rest.
65
+ const summary = summarizeFields(value);
66
+ if (summary !== '')
67
+ out.push(summary);
68
+ for (const nested of Object.values(value)) {
69
+ if (out.length >= max)
70
+ return;
71
+ if (typeof nested === 'object' && nested !== null)
72
+ collect(nested, out, max, seen);
73
+ }
74
+ }
75
+ /** Join an object's own citable primitive fields as `key: value` pairs. */
76
+ function summarizeFields(record) {
77
+ const pairs = [];
78
+ for (const [key, v] of Object.entries(record)) {
79
+ if (typeof v === 'string') {
80
+ const trimmed = v.trim();
81
+ if (trimmed !== '')
82
+ pairs.push(`${key}: ${trimmed}`);
83
+ }
84
+ else if (isCitablePrimitive(v)) {
85
+ pairs.push(`${key}: ${String(v)}`);
86
+ }
87
+ }
88
+ return pairs.join(', ');
89
+ }
90
+ /** Non-string primitives worth quoting: numbers and bigints. Booleans,
91
+ * null, and undefined carry no citable content — skipped. */
92
+ function isCitablePrimitive(value) {
93
+ return typeof value === 'number' || typeof value === 'bigint';
94
+ }
95
+ /** A record-shaped object (not an array) — the row/hit case. */
96
+ function isPlainRecord(value) {
97
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
98
+ }
99
+ /** Split prose into sentences/lines; non-empty, trimmed. */
100
+ function splitSentences(text) {
101
+ return text
102
+ .split(/(?<=[.!?])\s+|\n+/)
103
+ .map((s) => s.trim())
104
+ .filter((s) => s !== '');
105
+ }
106
+ /** Cap text at `maxLength` characters, ellipsis included. */
107
+ function truncate(text, maxLength) {
108
+ if (text.length <= maxLength)
109
+ return text;
110
+ if (maxLength <= 1)
111
+ return '…';
112
+ return `${text.slice(0, maxLength - 1)}…`;
113
+ }
114
+ //# sourceMappingURL=snippets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snippets.js","sourceRoot":"","sources":["../../../../src/lib/influence-core/snippets.ts"],"names":[],"mappings":"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"}
@@ -250,3 +250,53 @@ export interface MarginResult {
250
250
  readonly proxyDisagreement: boolean;
251
251
  };
252
252
  }
253
+ /**
254
+ * One piece of the context the chooser saw, tagged by which channel it
255
+ * came from. `scoreMargin` asks "which tool best fits ONE context";
256
+ * `attributeChoice` asks the transpose — "which context UNIT best explains
257
+ * ONE chosen tool" — so the unit is the thing being scored here.
258
+ *
259
+ * A channel groups units by origin so the attribution can report where the
260
+ * pull came from: `'system'` (a rule in the system prompt), `'task'` (the
261
+ * user's request), `'result'` (data a prior tool returned), `'history'`
262
+ * (an earlier turn). Channels are free-form strings — the caller decides
263
+ * the taxonomy; the engine only sums by whatever labels it is given.
264
+ *
265
+ * (Named `AttributionUnit`, not `ContextUnit`, to stay distinct from
266
+ * context-bisect's own `ContextUnit`, which is a different subsystem.)
267
+ */
268
+ export interface AttributionUnit {
269
+ /** Unique id — the citation the attribution points at, e.g. `'rule-1'`. */
270
+ readonly id: string;
271
+ /** Origin group, e.g. `'system' | 'task' | 'result' | 'history'`. */
272
+ readonly channel: string;
273
+ /** The text of the unit (a rule sentence, the user task, …). */
274
+ readonly text: string;
275
+ }
276
+ /** One context unit's proximity to the chosen tool, ranked. */
277
+ export interface UnitScore {
278
+ readonly id: string;
279
+ readonly channel: string;
280
+ /** cosine(embed(tool text), embed(unit.text)). */
281
+ readonly score: number;
282
+ }
283
+ /**
284
+ * Which context best explains one tool choice — the transpose of a
285
+ * `MarginResult`. Same honesty caveat: `score` is embedding geometry
286
+ * between the tool text and each instruction unit, a PROXY for which
287
+ * instruction the pick aligns with, never proof the model used that rule.
288
+ */
289
+ export interface ChoiceAttribution {
290
+ /** The chosen tool being explained. */
291
+ readonly tool: string;
292
+ /** Every unit scored against the tool, descending (ties keep input order). */
293
+ readonly units: readonly UnitScore[];
294
+ /** The single best-attributing unit — the citation ("picked because …"). */
295
+ readonly top: UnitScore;
296
+ /**
297
+ * Share of total POSITIVE similarity mass per channel, summing to ~1
298
+ * (empty when no unit had positive similarity). A pick dominated by the
299
+ * `system` channel is procedural; one dominated by `task` is topical.
300
+ */
301
+ readonly byChannel: Readonly<Record<string, number>>;
302
+ }
@@ -69,13 +69,42 @@
69
69
  */
70
70
  import type { EmitEvent } from 'footprintjs';
71
71
  import { type Embedder, type MarginResult } from '../../lib/influence-core/index.js';
72
- /** Minimal structural slice of footprintjs's FlowRunEvent (runId is all
73
- * we read Convention 4). */
72
+ /** Minimal structural slice of footprintjs's run-boundary events the
73
+ * `FlowRunEvent` (`onRunStart`/`onRunEnd`/`onRunFailed`). runId is all we
74
+ * read (Convention 4). */
74
75
  interface RunBoundaryEvent {
75
76
  readonly traversalContext?: {
76
77
  readonly runId?: string;
77
78
  };
78
79
  }
80
+ /** Minimal structural slice of footprintjs's `onResume` union — on
81
+ * `CombinedRecorder`, `onResume` is one of the SharedLifecycleOverlap
82
+ * methods (declared on both `ScopeRecorder` and `FlowRecorder` with
83
+ * DIFFERENT payloads), so its type is `ResumeEvent | FlowResumeEvent`, not
84
+ * a single `FlowRunEvent`-shaped type like the three siblings above. Only
85
+ * the control-flow `FlowResumeEvent` carries `traversalContext`; the
86
+ * scope-channel `ResumeEvent` (this recorder also receives it, via
87
+ * `onEmit`) has none — `traversalContext?.runId` is `undefined` there and
88
+ * the handler ignores it.
89
+ *
90
+ * `hasInput` is listed here too, even though the handler never reads it.
91
+ * Both union members declare `hasInput: boolean`, and TypeScript's
92
+ * weak-type check rejects an assignment to an object type whose
93
+ * properties are ALL optional when the source has NO property name in
94
+ * common with it at all. A slice with only `traversalContext` shares zero
95
+ * property names with the scope-channel `ResumeEvent` (it has no
96
+ * `traversalContext` field), so TypeScript flagged the whole handle as not
97
+ * assignable to `CombinedRecorder` (the 7.3.0 regression: f0a87de added
98
+ * `onResume` typed with exactly that too-narrow slice). Declaring
99
+ * `hasInput` gives this slice at least one property name in common with
100
+ * BOTH union members, which is all the weak-type check requires — the
101
+ * field carries no behavior. */
102
+ interface ResumeBoundaryEvent {
103
+ readonly hasInput?: boolean;
104
+ readonly traversalContext?: {
105
+ readonly runId?: string;
106
+ };
107
+ }
79
108
  /** One offered tool, as the model saw it on `llm_start`. */
80
109
  export interface OfferedTool {
81
110
  readonly name: string;
@@ -149,6 +178,7 @@ export interface ToolChoiceRecorderHandle {
149
178
  clear(): void;
150
179
  onEmit(event: EmitEvent): void;
151
180
  onRunStart(event: RunBoundaryEvent): void;
181
+ onResume(event: ResumeBoundaryEvent): void;
152
182
  onRunEnd(event: RunBoundaryEvent): void;
153
183
  onRunFailed(event: RunBoundaryEvent): void;
154
184
  }
@@ -206,12 +206,19 @@ export function toolChoiceRecorder(options) {
206
206
  break;
207
207
  }
208
208
  },
209
- /** Convention 4 — a new runId means a new run: reset accumulation so
210
- * runtimeStageId keys (which restart per run) cannot collide. The
211
- * executor also calls `clear()` before each `run()` — this hook is
212
- * the detection that works regardless of attach surface. Same-
213
- * executor `resume()` fires `onResume` (not `onRunStart`) and skips
214
- * `clear()`, so pre-pause entries SURVIVE a resume by design. */
209
+ /** Convention 4 — a new runId means a new logical run: reset
210
+ * accumulation so runtimeStageId keys (which restart per run) cannot
211
+ * collide. The executor also calls `clear()` before each `run()` —
212
+ * this hook is the detection that works regardless of attach surface.
213
+ *
214
+ * Pause/resume is NOT a fresh run. `executor.resume()` regenerates the
215
+ * runId, fires `onResume` (which stamps that new runId below WITHOUT
216
+ * resetting), and only THEN runs `traverser.execute()`, which fires
217
+ * this `onRunStart` at the top level with the SAME regenerated runId.
218
+ * Because `onResume` already advanced `lastRunId`, the guard here sees
219
+ * `runId === lastRunId` and does NOT reset — so pre-pause entries
220
+ * survive across the pause. A genuine `run()` arrives with a runId that
221
+ * `onResume` never stamped, so it still resets exactly as before. */
215
222
  onRunStart(event) {
216
223
  const runId = event.traversalContext?.runId;
217
224
  if (runId !== undefined && runId !== lastRunId) {
@@ -219,6 +226,17 @@ export function toolChoiceRecorder(options) {
219
226
  lastRunId = runId;
220
227
  }
221
228
  },
229
+ /** Resume adopts the regenerated runId WITHOUT resetting, so the
230
+ * `onRunStart` footprintjs fires immediately afterward (same runId) is
231
+ * a no-op and pre-pause tool-choice entries are retained. Only the
232
+ * control-flow (`FlowRecorder`) resume variant carries
233
+ * `traversalContext.runId`; the scope-channel `ResumeEvent` (this
234
+ * recorder also lands there via `onEmit`) has none → ignored. */
235
+ onResume(event) {
236
+ const runId = event.traversalContext?.runId;
237
+ if (runId !== undefined)
238
+ lastRunId = runId;
239
+ },
222
240
  onRunEnd() {
223
241
  closeOpen();
224
242
  },
@@ -1 +1 @@
1
- {"version":3,"file":"ToolChoiceRecorder.js","sourceRoot":"","sources":["../../../../src/recorders/observability/ToolChoiceRecorder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ToolChoiceRecorder.js","sourceRoot":"","sources":["../../../../src/recorders/observability/ToolChoiceRecorder.ts"],"names":[],"mappings":"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"}