pi-ghost-autocomplete 0.3.1 → 0.3.2

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 (155) hide show
  1. package/README.md +101 -6
  2. package/dist/bench-cli.js +81 -5
  3. package/dist/bench-cli.js.map +1 -1
  4. package/dist/bench.d.ts +130 -2
  5. package/dist/bench.d.ts.map +1 -1
  6. package/dist/bench.js +285 -4
  7. package/dist/bench.js.map +1 -1
  8. package/dist/cache.d.ts +124 -0
  9. package/dist/cache.d.ts.map +1 -0
  10. package/dist/cache.js +173 -0
  11. package/dist/cache.js.map +1 -0
  12. package/dist/candidate-rerank.d.ts +57 -0
  13. package/dist/candidate-rerank.d.ts.map +1 -0
  14. package/dist/candidate-rerank.js +78 -0
  15. package/dist/candidate-rerank.js.map +1 -0
  16. package/dist/config.d.ts +43 -0
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +148 -18
  19. package/dist/config.js.map +1 -1
  20. package/dist/context-aggregator.d.ts +14 -5
  21. package/dist/context-aggregator.d.ts.map +1 -1
  22. package/dist/context-aggregator.js +38 -9
  23. package/dist/context-aggregator.js.map +1 -1
  24. package/dist/context-selector.d.ts +128 -0
  25. package/dist/context-selector.d.ts.map +1 -0
  26. package/dist/context-selector.js +300 -0
  27. package/dist/context-selector.js.map +1 -0
  28. package/dist/cycle-manager.d.ts +102 -0
  29. package/dist/cycle-manager.d.ts.map +1 -0
  30. package/dist/cycle-manager.js +168 -0
  31. package/dist/cycle-manager.js.map +1 -0
  32. package/dist/edit-history-ring.d.ts +148 -0
  33. package/dist/edit-history-ring.d.ts.map +1 -0
  34. package/dist/edit-history-ring.js +262 -0
  35. package/dist/edit-history-ring.js.map +1 -0
  36. package/dist/entropy-stop.d.ts +102 -0
  37. package/dist/entropy-stop.d.ts.map +1 -0
  38. package/dist/entropy-stop.js +141 -0
  39. package/dist/entropy-stop.js.map +1 -0
  40. package/dist/eval-dataset.d.ts +66 -0
  41. package/dist/eval-dataset.d.ts.map +1 -0
  42. package/dist/eval-dataset.js +127 -0
  43. package/dist/eval-dataset.js.map +1 -0
  44. package/dist/fast-path-engine.d.ts +286 -0
  45. package/dist/fast-path-engine.d.ts.map +1 -0
  46. package/dist/fast-path-engine.js +341 -0
  47. package/dist/fast-path-engine.js.map +1 -0
  48. package/dist/fuzzy-matcher.d.ts +8 -0
  49. package/dist/fuzzy-matcher.d.ts.map +1 -1
  50. package/dist/fuzzy-matcher.js +5 -3
  51. package/dist/fuzzy-matcher.js.map +1 -1
  52. package/dist/ghost-editor.d.ts +321 -4
  53. package/dist/ghost-editor.d.ts.map +1 -1
  54. package/dist/ghost-editor.js +1190 -144
  55. package/dist/ghost-editor.js.map +1 -1
  56. package/dist/index.d.ts +17 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +81 -2
  59. package/dist/index.js.map +1 -1
  60. package/dist/keystroke-timer.d.ts +59 -0
  61. package/dist/keystroke-timer.d.ts.map +1 -0
  62. package/dist/keystroke-timer.js +94 -0
  63. package/dist/keystroke-timer.js.map +1 -0
  64. package/dist/metrics-builder.d.ts +71 -0
  65. package/dist/metrics-builder.d.ts.map +1 -0
  66. package/dist/metrics-builder.js +71 -0
  67. package/dist/metrics-builder.js.map +1 -0
  68. package/dist/metrics.d.ts +99 -2
  69. package/dist/metrics.d.ts.map +1 -1
  70. package/dist/metrics.js +131 -17
  71. package/dist/metrics.js.map +1 -1
  72. package/dist/path-matcher.d.ts +9 -0
  73. package/dist/path-matcher.d.ts.map +1 -1
  74. package/dist/path-matcher.js +5 -2
  75. package/dist/path-matcher.js.map +1 -1
  76. package/dist/profile-store.d.ts +82 -0
  77. package/dist/profile-store.d.ts.map +1 -0
  78. package/dist/profile-store.js +199 -0
  79. package/dist/profile-store.js.map +1 -0
  80. package/dist/profile.d.ts +185 -0
  81. package/dist/profile.d.ts.map +1 -0
  82. package/dist/profile.js +434 -0
  83. package/dist/profile.js.map +1 -0
  84. package/dist/providers/cloud-provider.d.ts +10 -1
  85. package/dist/providers/cloud-provider.d.ts.map +1 -1
  86. package/dist/providers/cloud-provider.js +71 -14
  87. package/dist/providers/cloud-provider.js.map +1 -1
  88. package/dist/providers/local-provider.d.ts +8 -1
  89. package/dist/providers/local-provider.d.ts.map +1 -1
  90. package/dist/providers/local-provider.js +15 -3
  91. package/dist/providers/local-provider.js.map +1 -1
  92. package/dist/providers/openai-compat-provider.d.ts +11 -1
  93. package/dist/providers/openai-compat-provider.d.ts.map +1 -1
  94. package/dist/providers/openai-compat-provider.js +93 -6
  95. package/dist/providers/openai-compat-provider.js.map +1 -1
  96. package/dist/providers/openai-completions-runner.d.ts +25 -1
  97. package/dist/providers/openai-completions-runner.d.ts.map +1 -1
  98. package/dist/providers/openai-completions-runner.js +109 -14
  99. package/dist/providers/openai-completions-runner.js.map +1 -1
  100. package/dist/providers/race.d.ts +58 -1
  101. package/dist/providers/race.d.ts.map +1 -1
  102. package/dist/providers/race.js +317 -4
  103. package/dist/providers/race.js.map +1 -1
  104. package/dist/providers/truncate.d.ts.map +1 -1
  105. package/dist/providers/truncate.js +20 -2
  106. package/dist/providers/truncate.js.map +1 -1
  107. package/dist/providers/types.d.ts +96 -1
  108. package/dist/providers/types.d.ts.map +1 -1
  109. package/dist/providers/types.js +59 -1
  110. package/dist/providers/types.js.map +1 -1
  111. package/dist/provisional-manager.d.ts +93 -0
  112. package/dist/provisional-manager.d.ts.map +1 -0
  113. package/dist/provisional-manager.js +98 -0
  114. package/dist/provisional-manager.js.map +1 -0
  115. package/dist/provisional.d.ts +150 -0
  116. package/dist/provisional.d.ts.map +1 -0
  117. package/dist/provisional.js +238 -0
  118. package/dist/provisional.js.map +1 -0
  119. package/dist/regret-tracker.d.ts +84 -0
  120. package/dist/regret-tracker.d.ts.map +1 -0
  121. package/dist/regret-tracker.js +145 -0
  122. package/dist/regret-tracker.js.map +1 -0
  123. package/dist/replay-cli.d.ts +13 -0
  124. package/dist/replay-cli.d.ts.map +1 -0
  125. package/dist/replay-cli.js +167 -0
  126. package/dist/replay-cli.js.map +1 -0
  127. package/dist/replay.d.ts +107 -0
  128. package/dist/replay.d.ts.map +1 -0
  129. package/dist/replay.js +225 -0
  130. package/dist/replay.js.map +1 -0
  131. package/dist/reranker.d.ts +181 -0
  132. package/dist/reranker.d.ts.map +1 -0
  133. package/dist/reranker.js +324 -0
  134. package/dist/reranker.js.map +1 -0
  135. package/dist/session-trie.d.ts +103 -0
  136. package/dist/session-trie.d.ts.map +1 -0
  137. package/dist/session-trie.js +280 -0
  138. package/dist/session-trie.js.map +1 -0
  139. package/dist/speculative.d.ts +74 -0
  140. package/dist/speculative.d.ts.map +1 -0
  141. package/dist/speculative.js +107 -0
  142. package/dist/speculative.js.map +1 -0
  143. package/dist/tool-summarize.d.ts +40 -0
  144. package/dist/tool-summarize.d.ts.map +1 -0
  145. package/dist/tool-summarize.js +245 -0
  146. package/dist/tool-summarize.js.map +1 -0
  147. package/dist/trie-sanitize.d.ts +22 -0
  148. package/dist/trie-sanitize.d.ts.map +1 -0
  149. package/dist/trie-sanitize.js +142 -0
  150. package/dist/trie-sanitize.js.map +1 -0
  151. package/dist/versions.d.ts +23 -0
  152. package/dist/versions.d.ts.map +1 -0
  153. package/dist/versions.js +31 -0
  154. package/dist/versions.js.map +1 -0
  155. package/package.json +3 -2
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Multi-source candidate reranker. See PRD §M3c.
3
+ *
4
+ * Pure function (`candidates, opts → ranked[]`). No I/O, no provider calls,
5
+ * no editor state — easy to unit-test without mocks.
6
+ *
7
+ * Pipeline:
8
+ * 1. Merge candidates by exact text (collapsing race-member duplicates,
9
+ * taking the max logprob across sources and accumulating the source set).
10
+ * 2. Score each merged candidate as a weighted sum of normalized features:
11
+ * logprob, profile-bias (M4 hook), length-prior, agreement bonus.
12
+ * 3. Tie-break (within 1e-6) on length-around-median, local-over-cloud,
13
+ * lexicographic.
14
+ *
15
+ * Missing logprobs (Mercury FIM today) map to the neutral mid-value 0.5
16
+ * after normalization so a single-provider Mercury candidate isn't
17
+ * penalized against a multi-provider race that returns logprobs.
18
+ */
19
+ export const TIE_EPSILON = 1e-6;
20
+ export const LENGTH_PRIOR_LOW = 5;
21
+ export const LENGTH_PRIOR_HIGH = 30;
22
+ export const LENGTH_PRIOR_ZERO_AT = 80;
23
+ /**
24
+ * Prefix-length threshold above which the lengthPrior plateau and decay
25
+ * tail scale up. Empirically (ChaI-TeA + Copilot data): the longer the
26
+ * typed prefix, the longer the completion the user actually wants. Below
27
+ * this threshold the curve matches the original (prefix-blind) behavior.
28
+ */
29
+ export const PREFIX_LENGTH_SCALE_THRESHOLD = 30;
30
+ export const FALLBACK_MEDIAN_LENGTH = 15;
31
+ export const MISSING_LOGPROB_NEUTRAL = 0.5;
32
+ export const DEFAULT_WEIGHTS = {
33
+ logprob: 0.40,
34
+ profileBias: 0.25,
35
+ lengthPrior: 0.15,
36
+ agreement: 0.10,
37
+ editProximity: 0.10,
38
+ };
39
+ /**
40
+ * Merge candidates by exact text, accumulating sources and taking the max
41
+ * logprob across providers (agreement = positive evidence).
42
+ */
43
+ export function mergeCandidates(cands) {
44
+ const map = new Map();
45
+ for (const c of cands) {
46
+ const existing = map.get(c.text);
47
+ if (existing) {
48
+ existing.sources.add(c.provider);
49
+ if (c.local)
50
+ existing.anyLocal = true;
51
+ if (c.avgLogprob !== undefined) {
52
+ if (existing.avgLogprob === undefined || c.avgLogprob > existing.avgLogprob) {
53
+ existing.avgLogprob = c.avgLogprob;
54
+ }
55
+ }
56
+ }
57
+ else {
58
+ map.set(c.text, {
59
+ text: c.text,
60
+ avgLogprob: c.avgLogprob,
61
+ sources: new Set([c.provider]),
62
+ anyLocal: !!c.local,
63
+ });
64
+ }
65
+ }
66
+ return [...map.values()];
67
+ }
68
+ /**
69
+ * Length prior for a candidate of `len` characters. `prefixLen` adjusts the
70
+ * plateau and decay bounds: completions get scored against a curve scaled to
71
+ * the typed prefix length, so long prefixes don't penalize long completions.
72
+ *
73
+ * When `prefixLen <= PREFIX_LENGTH_SCALE_THRESHOLD` (or omitted), the curve
74
+ * matches the original prefix-blind behavior: plateau over
75
+ * `[LENGTH_PRIOR_LOW, LENGTH_PRIOR_HIGH]`, linear ramp below LOW, linear
76
+ * decay between HIGH and `LENGTH_PRIOR_ZERO_AT`, and zero above ZERO_AT.
77
+ *
78
+ * When `prefixLen > PREFIX_LENGTH_SCALE_THRESHOLD`, the upper plateau (HIGH)
79
+ * and the zero-crossing (ZERO_AT) both scale by `prefixLen / THRESHOLD`:
80
+ * - prefixLen = 30: scale = 1.0 → HIGH=30, ZERO_AT=80 (unchanged)
81
+ * - prefixLen = 60: scale = 2.0 → HIGH=60, ZERO_AT=160
82
+ * - prefixLen = 120: scale = 4.0 → HIGH=120, ZERO_AT=320
83
+ * LOW stays fixed — even very long prefixes still penalize trivially-short
84
+ * (1–4 char) completions, matching empirical user behavior.
85
+ */
86
+ export function lengthPrior(len, prefixLen = 0) {
87
+ const bounds = lengthPriorBounds(prefixLen);
88
+ if (len <= 0 || len >= bounds.zeroAt)
89
+ return 0;
90
+ if (len >= LENGTH_PRIOR_LOW && len <= bounds.high)
91
+ return 1;
92
+ if (len < LENGTH_PRIOR_LOW)
93
+ return len / LENGTH_PRIOR_LOW;
94
+ // len between HIGH and ZERO_AT — linear decay
95
+ return (bounds.zeroAt - len) / (bounds.zeroAt - bounds.high);
96
+ }
97
+ /**
98
+ * Compute the prefix-length-aware HIGH and ZERO_AT bounds. Exposed for
99
+ * diagnostics + tests so the scaling logic can be verified directly.
100
+ */
101
+ export function lengthPriorBounds(prefixLen) {
102
+ if (!Number.isFinite(prefixLen) || prefixLen <= PREFIX_LENGTH_SCALE_THRESHOLD) {
103
+ return { high: LENGTH_PRIOR_HIGH, zeroAt: LENGTH_PRIOR_ZERO_AT };
104
+ }
105
+ const scale = prefixLen / PREFIX_LENGTH_SCALE_THRESHOLD;
106
+ return {
107
+ high: LENGTH_PRIOR_HIGH * scale,
108
+ zeroAt: LENGTH_PRIOR_ZERO_AT * scale,
109
+ };
110
+ }
111
+ /**
112
+ * Min-max normalize `xs` into [0, 1]. If the spread is below `TIE_EPSILON`,
113
+ * every entry maps to 0.5 (neutral); this matches the spec's "missing
114
+ * logprob → 0.5" rule when applied to a uniform-logprob set.
115
+ */
116
+ function minMaxNormalize(xs) {
117
+ if (xs.length === 0)
118
+ return [];
119
+ let min = Infinity;
120
+ let max = -Infinity;
121
+ for (const x of xs) {
122
+ if (x < min)
123
+ min = x;
124
+ if (x > max)
125
+ max = x;
126
+ }
127
+ const spread = max - min;
128
+ if (spread < TIE_EPSILON)
129
+ return xs.map(() => 0.5);
130
+ return xs.map((x) => (x - min) / spread);
131
+ }
132
+ export function rerank(cands, opts = {}) {
133
+ const w = opts.weights ?? DEFAULT_WEIGHTS;
134
+ const raceMembers = Math.max(1, opts.raceMembers ?? 1);
135
+ const profileBias = opts.profileBias ?? (() => 0);
136
+ // Track whether an editProximityScorer was supplied. Without one, the
137
+ // feature contributes nothing (raw zeros → uniform 0.5 after min-max
138
+ // would dilute all other signals by `w.editProximity` × 0.5). We
139
+ // short-circuit that by zeroing the editProximity term in the score
140
+ // sum when no signal is present.
141
+ const editProximityScorer = opts.editProximityScorer;
142
+ const median = opts.medianAcceptedLength ?? FALLBACK_MEDIAN_LENGTH;
143
+ const merged = mergeCandidates(cands);
144
+ if (merged.length === 0)
145
+ return [];
146
+ // Raw feature extraction.
147
+ const logprobs = merged.map((m) => m.avgLogprob === undefined ? Number.NaN : m.avgLogprob);
148
+ const profile = merged.map((m) => profileBias(m.text));
149
+ const editProx = editProximityScorer
150
+ ? merged.map((m) => editProximityScorer(m.text))
151
+ : merged.map(() => 0);
152
+ // `hasEditSignal` is true only when at least two raw values differ
153
+ // (so min-max norm produces useful ordering, not the uniform-0.5
154
+ // fallback). Single-candidate runs also count as no signal.
155
+ const editProxMin = editProx.length > 0 ? Math.min(...editProx) : 0;
156
+ const editProxMax = editProx.length > 0 ? Math.max(...editProx) : 0;
157
+ const hasEditSignal = editProxMax - editProxMin > TIE_EPSILON;
158
+ const prefixLen = opts.prefixLen ?? 0;
159
+ const lengths = merged.map((m) => lengthPrior(m.text.length, prefixLen));
160
+ const agreement = merged.map((m) => raceMembers > 1 ? (m.sources.size - 1) / (raceMembers - 1) : 0);
161
+ // Normalize each feature axis independently. For logprob, NaN slots get
162
+ // replaced with the neutral mid-value 0.5 after normalization.
163
+ const logprobsClean = logprobs.filter((x) => !Number.isNaN(x));
164
+ const normLp = logprobsClean.length > 0 ? minMaxNormalize(logprobsClean) : [];
165
+ let lpIdx = 0;
166
+ const logprobNorm = logprobs.map((x) => Number.isNaN(x) ? MISSING_LOGPROB_NEUTRAL : normLp[lpIdx++]);
167
+ const profileNorm = minMaxNormalize(profile);
168
+ const editProxNorm = minMaxNormalize(editProx);
169
+ const lengthNorm = minMaxNormalize(lengths);
170
+ // Agreement is already in [0, 1] — no normalization (PRD §M3c step 2).
171
+ const scored = merged.map((m, i) => {
172
+ const lp = logprobNorm[i];
173
+ const pb = profileNorm[i];
174
+ const lpr = lengthNorm[i];
175
+ const agr = agreement[i];
176
+ const ep = editProxNorm[i];
177
+ // `editProximity` may be undefined if the caller built RerankWeights
178
+ // via JSON / pre-#1 fixtures. Treat as 0 to preserve legacy behavior.
179
+ // When `hasEditSignal` is false (no scorer, or scorer produces a flat
180
+ // vector), min-max normalize would map every entry to the neutral
181
+ // 0.5, contributing a constant `w.editProximity * 0.5` to every
182
+ // score. Two harms: (1) dilutes effective contrast of all other
183
+ // signals; (2) shifts the score range below the calibrated
184
+ // `applyConfidenceGate` threshold. Fix: when dormant, zero this term
185
+ // AND scale the four other-feature weights up so the active weights
186
+ // sum back to the original total (preserves score range + threshold
187
+ // calibration).
188
+ //
189
+ // Caveat: the renormalization only restores the [0, 1] range when
190
+ // the other four weights summed to exactly `1 - editProximity`
191
+ // before scaling. Default `DEFAULT_WEIGHTS` and the parsed-env
192
+ // shapes satisfy this; arbitrary externally-supplied weights with
193
+ // a non-unit total may still shift the score range.
194
+ const wEp = w.editProximity ?? 0;
195
+ const inactive = !hasEditSignal && wEp > 0;
196
+ const scale = inactive ? 1 / Math.max(TIE_EPSILON, 1 - wEp) : 1;
197
+ const score = inactive
198
+ ? (w.logprob * lp + w.profileBias * pb + w.lengthPrior * lpr + w.agreement * agr) * scale
199
+ : w.logprob * lp + w.profileBias * pb + w.lengthPrior * lpr + w.agreement * agr + wEp * ep;
200
+ return {
201
+ text: m.text,
202
+ score,
203
+ avgLogprob: m.avgLogprob,
204
+ sources: [...m.sources].sort(),
205
+ scoreBreakdown: {
206
+ logprob: lp,
207
+ profileBias: pb,
208
+ lengthPrior: lpr,
209
+ agreement: agr,
210
+ editProximity: ep,
211
+ },
212
+ };
213
+ });
214
+ // Sort with tie-break chain.
215
+ scored.sort((a, b) => {
216
+ const ds = b.score - a.score;
217
+ if (Math.abs(ds) > TIE_EPSILON)
218
+ return ds;
219
+ // 1. Length closest to median.
220
+ const da = Math.abs(a.text.length - median);
221
+ const db = Math.abs(b.text.length - median);
222
+ if (da !== db)
223
+ return da - db;
224
+ // 2. Local provider preferred.
225
+ const aLocal = mergedHasLocal(merged, a.text);
226
+ const bLocal = mergedHasLocal(merged, b.text);
227
+ if (aLocal !== bLocal)
228
+ return aLocal ? -1 : 1;
229
+ // 3. Byte-compare (NOT localeCompare) for cross-machine determinism.
230
+ // localeCompare varies by locale and could change cycling order
231
+ // between Windows/Linux users on the same input.
232
+ if (a.text < b.text)
233
+ return -1;
234
+ if (a.text > b.text)
235
+ return 1;
236
+ return 0;
237
+ });
238
+ return scored;
239
+ }
240
+ function mergedHasLocal(merged, text) {
241
+ for (const m of merged)
242
+ if (m.text === text)
243
+ return m.anyLocal;
244
+ return false;
245
+ }
246
+ /** Default confidence gate threshold (PRD §M3c.1). Set to 0 to disable. */
247
+ export const DEFAULT_MIN_CONFIDENCE = 0.55;
248
+ /** Default top-vs-second margin gate (PRD §M3c.1). */
249
+ export const DEFAULT_DISAGREEMENT_MARGIN = 0.05;
250
+ /**
251
+ * After rerank, decide whether to show the top candidate at all. Returns the
252
+ * top candidate when both gates pass, else `null` (caller should fall back to
253
+ * cache miss / no ghost). PRD §M3c.1.
254
+ *
255
+ * Both gates apply only to the top vs. second-best. With a single candidate,
256
+ * the margin gate trivially passes (no rival to disagree with) and only
257
+ * `minConfidence` matters.
258
+ *
259
+ * Score range: with default weights summing to 1.0 (PRD §M3c) and each
260
+ * feature normalized to [0, 1], the weighted sum lands in [0, 1] too —
261
+ * `minConfidence=0.55` and `minMargin=0.05` are calibrated against that
262
+ * range. User-supplied weights via `PI_GHOST_RERANK_WEIGHTS` that don't
263
+ * sum to 1.0 shift the effective score range; adjust gates accordingly
264
+ * or set them to 0 to disable.
265
+ *
266
+ * PRD §M3c.1 lists a third gate ("`avgLogprob` exists and falls below a
267
+ * calibrated provider-specific threshold"). It depends on accept-rate
268
+ * buckets from M5/M5c replay — deferred until that data is in hand.
269
+ * Setting `minConfidence=0` disables both implemented gates.
270
+ */
271
+ export function applyConfidenceGate(ranked, opts = {}) {
272
+ if (ranked.length === 0)
273
+ return null;
274
+ const minConfidence = opts.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
275
+ const minMargin = opts.minMargin ?? DEFAULT_DISAGREEMENT_MARGIN;
276
+ const top = ranked[0];
277
+ if (top.score < minConfidence)
278
+ return null;
279
+ if (ranked.length >= 2) {
280
+ const second = ranked[1];
281
+ if (top.score - second.score < minMargin)
282
+ return null;
283
+ }
284
+ return top;
285
+ }
286
+ /**
287
+ * Parse `PI_GHOST_MIN_CONFIDENCE`. Returns fallback when unset, non-finite,
288
+ * or outside [0, 1].
289
+ */
290
+ export function parseMinConfidenceEnv(raw) {
291
+ if (raw === undefined)
292
+ return DEFAULT_MIN_CONFIDENCE;
293
+ const v = Number(raw);
294
+ if (!Number.isFinite(v) || v < 0 || v > 1)
295
+ return DEFAULT_MIN_CONFIDENCE;
296
+ return v;
297
+ }
298
+ /**
299
+ * Parse `PI_GHOST_RERANK_WEIGHTS=a,b,c,d[,e]` into a `RerankWeights`.
300
+ * Accepts 4 or 5 comma-separated weights:
301
+ * - 4 values: `logprob,profileBias,lengthPrior,agreement` (legacy form;
302
+ * `editProximity` defaults to 0 to preserve pre-#1 behavior).
303
+ * - 5 values: same plus `editProximity` (Enhancement #1).
304
+ * Falls back to defaults on parse error or invalid count. Negative weights
305
+ * are clamped to 0 ("ignore this signal").
306
+ */
307
+ export function parseWeightsEnv(raw) {
308
+ if (!raw)
309
+ return DEFAULT_WEIGHTS;
310
+ const parts = raw.split(",").map((s) => Number(s.trim()));
311
+ if ((parts.length !== 4 && parts.length !== 5) || parts.some((n) => !Number.isFinite(n))) {
312
+ return DEFAULT_WEIGHTS;
313
+ }
314
+ const clamped = parts.map((n) => Math.max(0, n));
315
+ const [logprob, profileBias, lengthPrior, agreement, editProximity = 0] = clamped;
316
+ return {
317
+ logprob: logprob,
318
+ profileBias: profileBias,
319
+ lengthPrior: lengthPrior,
320
+ agreement: agreement,
321
+ editProximity,
322
+ };
323
+ }
324
+ //# sourceMappingURL=reranker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reranker.js","sourceRoot":"","sources":["../src/reranker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Session trie — fast-path completion source backed by the user's own past
3
+ * accepts and committed messages. See PRD §M2.
4
+ *
5
+ * Structurally this is `Map<prefix, Map<suffix, weight>>` rather than a true
6
+ * trie. At the PRD's 5000-entry cap, hash-lookup-by-exact-prefix is faster
7
+ * than walking a character trie, and the simpler shape is easier to reason
8
+ * about for decay and eviction.
9
+ *
10
+ * Insertion sources and weights (PRD §M2 "Insertion signals"):
11
+ * - full accept: +3
12
+ * - partial accept: +2 on the partial word, +1 on the full candidate
13
+ * - committed user message: +1, prefix length 3..12 chars, suffix capped at
14
+ * 4 word-boundary shingles
15
+ * - divergent dismiss: -0.5 (caller decides what counts as divergent;
16
+ * per-keystroke dismisses must NOT call here, per PRD)
17
+ *
18
+ * Lookup gates (PRD §M2 "Lookup"):
19
+ * - prefix length ≥ 3
20
+ * - winner weight ≥ 1.5
21
+ * - winner margin over runner-up ≥ 1.0
22
+ */
23
+ export declare const MIN_PREFIX_LEN = 3;
24
+ export declare const MIN_WEIGHT = 1.5;
25
+ export declare const MIN_MARGIN = 1;
26
+ export declare const DEFAULT_CAPACITY = 5000;
27
+ export declare const DEFAULT_DECAY_EVERY = 200;
28
+ export declare const DEFAULT_DECAY_FACTOR = 0.5;
29
+ export declare const MAX_COMMITTED_PREFIX_LEN = 12;
30
+ export declare const MAX_COMMITTED_SUFFIX_WORDS = 4;
31
+ export interface TrieMatch {
32
+ ghost: string;
33
+ weight: number;
34
+ margin: number;
35
+ }
36
+ export interface TrieStats {
37
+ prefixes: number;
38
+ candidates: number;
39
+ insertsSinceDecay: number;
40
+ }
41
+ export declare class SessionTrie {
42
+ private readonly capacity;
43
+ private readonly decayEvery;
44
+ private readonly decayFactor;
45
+ /**
46
+ * `Map` insertion order is the LRU stamp — we re-insert a prefix key after
47
+ * touching it. Beyond capacity, the oldest key (first in iteration order)
48
+ * is evicted.
49
+ */
50
+ private readonly map;
51
+ private insertsSinceDecay;
52
+ constructor(capacity?: number, decayEvery?: number, decayFactor?: number);
53
+ get size(): number;
54
+ get stats(): TrieStats;
55
+ insert(prefix: string, suffix: string, weight: number): void;
56
+ /**
57
+ * Insert prefix→remainder pairs from an accepted ghost: prefix is the
58
+ * editor text immediately before the ghost; the full accepted suffix is
59
+ * the value. Weight is the caller's choice (+3 full, +2 partial-word, +1
60
+ * full-candidate-on-partial). Caller handles signal selection.
61
+ */
62
+ insertFromAccept(prefix: string, suffix: string, weight: number): void;
63
+ /**
64
+ * Insert sliding-window prefix→remainder pairs from a committed user
65
+ * message at weight +1 each (PRD §M2). Prefix lengths 3..12 chars,
66
+ * remainder capped at 4 word-boundary shingles to limit memory and avoid
67
+ * memorizing entire messages.
68
+ *
69
+ * Skips the whole message if any token matches a sensitive pattern.
70
+ */
71
+ insertFromCommittedMessage(text: string, weightPerShingle?: number): void;
72
+ /**
73
+ * Penalize an entry that diverged from the user's eventual commit.
74
+ * Per-keystroke dismisses must NOT call this (would penalize correct
75
+ * ghosts mid-typing). See PRD §M2.
76
+ */
77
+ penalize(prefix: string, suffix: string, magnitude?: number): void;
78
+ lookup(prefix: string): TrieMatch | null;
79
+ clear(): void;
80
+ /**
81
+ * Halve all weights. Exposed for testing; callers normally rely on the
82
+ * automatic decay every `decayEvery` inserts.
83
+ */
84
+ decayNow(): void;
85
+ private bumpCandidate;
86
+ private tickDecayCounter;
87
+ private enforceCapacity;
88
+ }
89
+ /**
90
+ * Return the end-of-word offsets in `text` (exclusive). For "ab cd ef", returns
91
+ * [2, 5, 8]. Used to align committed-message shingles to word boundaries.
92
+ */
93
+ /**
94
+ * Pure helper used by `GhostEditor.onPromptCommitted`. Seeds `trie` from the
95
+ * committed text. If `accepted` is non-null AND the committed text contains
96
+ * the accepted ghost, the per-shingle weight drops from +1 to +0.25 to avoid
97
+ * double-counting (PRD §M2 "Insertion signals").
98
+ */
99
+ export declare function seedTrieFromCommit(trie: SessionTrie, text: string, accepted: {
100
+ prefix: string;
101
+ ghost: string;
102
+ } | null): void;
103
+ //# sourceMappingURL=session-trie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-trie.d.ts","sourceRoot":"","sources":["../src/session-trie.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,UAAU,MAAM,CAAC;AAC9B,eAAO,MAAM,UAAU,IAAM,CAAC;AAC9B,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,WAAW;IAUtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAX7B;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA0C;IAC9D,OAAO,CAAC,iBAAiB,CAAK;gBAGZ,QAAQ,GAAE,MAAyB,EACnC,UAAU,GAAE,MAA4B,EACxC,WAAW,GAAE,MAA6B;IAO5D,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,KAAK,IAAI,SAAS,CAQrB;IAED,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ5D;;;;;OAKG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAItE;;;;;;;OAOG;IACH,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,SAAI,GAAG,IAAI;IAyBpE;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,SAAM,GAAG,IAAI;IAe/D,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IA8CxC,KAAK,IAAI,IAAI;IAKb;;;OAGG;IACH,QAAQ,IAAI,IAAI;IAehB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,eAAe;CAOvB;AAED;;;GAGG;AACH;;;;;GAKG;AACH,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAChD,IAAI,CAIN"}