pi-ghost-autocomplete 0.3.2 → 0.4.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.
Files changed (168) hide show
  1. package/LICENSE +561 -0
  2. package/README.md +464 -331
  3. package/dist/bench-cli.js +1 -123
  4. package/dist/bench.d.ts +7 -3
  5. package/dist/bench.js +1 -522
  6. package/dist/config.d.ts +4 -1
  7. package/dist/context-aggregator.d.ts +4 -1
  8. package/dist/cycle-manager.d.ts +2 -21
  9. package/dist/entropy-stop.d.ts +4 -1
  10. package/dist/eval-dataset.d.ts +2 -13
  11. package/dist/fuzzy-matcher.d.ts +4 -1
  12. package/dist/ghost-editor.d.ts +11 -2
  13. package/dist/index.d.ts +4 -1
  14. package/dist/index.js +1 -289
  15. package/dist/intent.d.ts +179 -0
  16. package/dist/metrics.d.ts +4 -1
  17. package/dist/path-index.d.ts +4 -1
  18. package/dist/path-matcher.d.ts +4 -1
  19. package/dist/profile-store.d.ts +4 -1
  20. package/dist/profile.d.ts +2 -20
  21. package/dist/providers/cloud-provider.d.ts +4 -1
  22. package/dist/providers/local-provider.d.ts +4 -1
  23. package/dist/providers/openai-compat-provider.d.ts +24 -1
  24. package/dist/providers/race.d.ts +4 -1
  25. package/dist/providers/types.d.ts +13 -1
  26. package/dist/recent-paths.d.ts +4 -1
  27. package/dist/replay-cli.js +1 -166
  28. package/dist/replay.d.ts +2 -7
  29. package/package.json +90 -80
  30. package/dist/bench-cli.d.ts +0 -3
  31. package/dist/bench-cli.d.ts.map +0 -1
  32. package/dist/bench-cli.js.map +0 -1
  33. package/dist/bench.d.ts.map +0 -1
  34. package/dist/bench.js.map +0 -1
  35. package/dist/cache.d.ts +0 -124
  36. package/dist/cache.d.ts.map +0 -1
  37. package/dist/cache.js +0 -173
  38. package/dist/cache.js.map +0 -1
  39. package/dist/candidate-rerank.d.ts +0 -57
  40. package/dist/candidate-rerank.d.ts.map +0 -1
  41. package/dist/candidate-rerank.js +0 -78
  42. package/dist/candidate-rerank.js.map +0 -1
  43. package/dist/config.d.ts.map +0 -1
  44. package/dist/config.js +0 -317
  45. package/dist/config.js.map +0 -1
  46. package/dist/context-aggregator.d.ts.map +0 -1
  47. package/dist/context-aggregator.js +0 -87
  48. package/dist/context-aggregator.js.map +0 -1
  49. package/dist/context-selector.d.ts +0 -128
  50. package/dist/context-selector.d.ts.map +0 -1
  51. package/dist/context-selector.js +0 -300
  52. package/dist/context-selector.js.map +0 -1
  53. package/dist/cycle-manager.d.ts.map +0 -1
  54. package/dist/cycle-manager.js +0 -168
  55. package/dist/cycle-manager.js.map +0 -1
  56. package/dist/edit-history-ring.d.ts +0 -148
  57. package/dist/edit-history-ring.d.ts.map +0 -1
  58. package/dist/edit-history-ring.js +0 -262
  59. package/dist/edit-history-ring.js.map +0 -1
  60. package/dist/entropy-stop.d.ts.map +0 -1
  61. package/dist/entropy-stop.js +0 -141
  62. package/dist/entropy-stop.js.map +0 -1
  63. package/dist/eval-dataset.d.ts.map +0 -1
  64. package/dist/eval-dataset.js +0 -127
  65. package/dist/eval-dataset.js.map +0 -1
  66. package/dist/fast-path-engine.d.ts +0 -286
  67. package/dist/fast-path-engine.d.ts.map +0 -1
  68. package/dist/fast-path-engine.js +0 -341
  69. package/dist/fast-path-engine.js.map +0 -1
  70. package/dist/fuzzy-matcher.d.ts.map +0 -1
  71. package/dist/fuzzy-matcher.js +0 -162
  72. package/dist/fuzzy-matcher.js.map +0 -1
  73. package/dist/ghost-editor.d.ts.map +0 -1
  74. package/dist/ghost-editor.js +0 -1491
  75. package/dist/ghost-editor.js.map +0 -1
  76. package/dist/index.d.ts.map +0 -1
  77. package/dist/index.js.map +0 -1
  78. package/dist/keystroke-timer.d.ts +0 -59
  79. package/dist/keystroke-timer.d.ts.map +0 -1
  80. package/dist/keystroke-timer.js +0 -94
  81. package/dist/keystroke-timer.js.map +0 -1
  82. package/dist/metrics-builder.d.ts +0 -71
  83. package/dist/metrics-builder.d.ts.map +0 -1
  84. package/dist/metrics-builder.js +0 -71
  85. package/dist/metrics-builder.js.map +0 -1
  86. package/dist/metrics.d.ts.map +0 -1
  87. package/dist/metrics.js +0 -212
  88. package/dist/metrics.js.map +0 -1
  89. package/dist/path-index.d.ts.map +0 -1
  90. package/dist/path-index.js +0 -148
  91. package/dist/path-index.js.map +0 -1
  92. package/dist/path-matcher.d.ts.map +0 -1
  93. package/dist/path-matcher.js +0 -88
  94. package/dist/path-matcher.js.map +0 -1
  95. package/dist/profile-store.d.ts.map +0 -1
  96. package/dist/profile-store.js +0 -199
  97. package/dist/profile-store.js.map +0 -1
  98. package/dist/profile.d.ts.map +0 -1
  99. package/dist/profile.js +0 -434
  100. package/dist/profile.js.map +0 -1
  101. package/dist/providers/cloud-provider.d.ts.map +0 -1
  102. package/dist/providers/cloud-provider.js +0 -109
  103. package/dist/providers/cloud-provider.js.map +0 -1
  104. package/dist/providers/local-provider.d.ts.map +0 -1
  105. package/dist/providers/local-provider.js +0 -48
  106. package/dist/providers/local-provider.js.map +0 -1
  107. package/dist/providers/openai-compat-provider.d.ts.map +0 -1
  108. package/dist/providers/openai-compat-provider.js +0 -215
  109. package/dist/providers/openai-compat-provider.js.map +0 -1
  110. package/dist/providers/openai-completions-runner.d.ts +0 -52
  111. package/dist/providers/openai-completions-runner.d.ts.map +0 -1
  112. package/dist/providers/openai-completions-runner.js +0 -141
  113. package/dist/providers/openai-completions-runner.js.map +0 -1
  114. package/dist/providers/race.d.ts.map +0 -1
  115. package/dist/providers/race.js +0 -441
  116. package/dist/providers/race.js.map +0 -1
  117. package/dist/providers/truncate.d.ts +0 -7
  118. package/dist/providers/truncate.d.ts.map +0 -1
  119. package/dist/providers/truncate.js +0 -57
  120. package/dist/providers/truncate.js.map +0 -1
  121. package/dist/providers/types.d.ts.map +0 -1
  122. package/dist/providers/types.js +0 -60
  123. package/dist/providers/types.js.map +0 -1
  124. package/dist/provisional-manager.d.ts +0 -93
  125. package/dist/provisional-manager.d.ts.map +0 -1
  126. package/dist/provisional-manager.js +0 -98
  127. package/dist/provisional-manager.js.map +0 -1
  128. package/dist/provisional.d.ts +0 -150
  129. package/dist/provisional.d.ts.map +0 -1
  130. package/dist/provisional.js +0 -238
  131. package/dist/provisional.js.map +0 -1
  132. package/dist/recent-paths.d.ts.map +0 -1
  133. package/dist/recent-paths.js +0 -114
  134. package/dist/recent-paths.js.map +0 -1
  135. package/dist/regret-tracker.d.ts +0 -84
  136. package/dist/regret-tracker.d.ts.map +0 -1
  137. package/dist/regret-tracker.js +0 -145
  138. package/dist/regret-tracker.js.map +0 -1
  139. package/dist/replay-cli.d.ts +0 -13
  140. package/dist/replay-cli.d.ts.map +0 -1
  141. package/dist/replay-cli.js.map +0 -1
  142. package/dist/replay.d.ts.map +0 -1
  143. package/dist/replay.js +0 -225
  144. package/dist/replay.js.map +0 -1
  145. package/dist/reranker.d.ts +0 -181
  146. package/dist/reranker.d.ts.map +0 -1
  147. package/dist/reranker.js +0 -324
  148. package/dist/reranker.js.map +0 -1
  149. package/dist/session-trie.d.ts +0 -103
  150. package/dist/session-trie.d.ts.map +0 -1
  151. package/dist/session-trie.js +0 -280
  152. package/dist/session-trie.js.map +0 -1
  153. package/dist/speculative.d.ts +0 -74
  154. package/dist/speculative.d.ts.map +0 -1
  155. package/dist/speculative.js +0 -107
  156. package/dist/speculative.js.map +0 -1
  157. package/dist/tool-summarize.d.ts +0 -40
  158. package/dist/tool-summarize.d.ts.map +0 -1
  159. package/dist/tool-summarize.js +0 -245
  160. package/dist/tool-summarize.js.map +0 -1
  161. package/dist/trie-sanitize.d.ts +0 -22
  162. package/dist/trie-sanitize.d.ts.map +0 -1
  163. package/dist/trie-sanitize.js +0 -142
  164. package/dist/trie-sanitize.js.map +0 -1
  165. package/dist/versions.d.ts +0 -23
  166. package/dist/versions.d.ts.map +0 -1
  167. package/dist/versions.js +0 -31
  168. package/dist/versions.js.map +0 -1
@@ -1,280 +0,0 @@
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
- import { containsSensitive } from "./trie-sanitize.js";
24
- export const MIN_PREFIX_LEN = 3;
25
- export const MIN_WEIGHT = 1.5;
26
- export const MIN_MARGIN = 1.0;
27
- export const DEFAULT_CAPACITY = 5000;
28
- export const DEFAULT_DECAY_EVERY = 200;
29
- export const DEFAULT_DECAY_FACTOR = 0.5;
30
- export const MAX_COMMITTED_PREFIX_LEN = 12;
31
- export const MAX_COMMITTED_SUFFIX_WORDS = 4;
32
- export class SessionTrie {
33
- capacity;
34
- decayEvery;
35
- decayFactor;
36
- /**
37
- * `Map` insertion order is the LRU stamp — we re-insert a prefix key after
38
- * touching it. Beyond capacity, the oldest key (first in iteration order)
39
- * is evicted.
40
- */
41
- map = new Map();
42
- insertsSinceDecay = 0;
43
- constructor(capacity = DEFAULT_CAPACITY, decayEvery = DEFAULT_DECAY_EVERY, decayFactor = DEFAULT_DECAY_FACTOR) {
44
- this.capacity = capacity;
45
- this.decayEvery = decayEvery;
46
- this.decayFactor = decayFactor;
47
- if (capacity <= 0) {
48
- this.capacity = DEFAULT_CAPACITY;
49
- }
50
- }
51
- get size() {
52
- return this.map.size;
53
- }
54
- get stats() {
55
- let candidates = 0;
56
- for (const m of this.map.values())
57
- candidates += m.size;
58
- return {
59
- prefixes: this.map.size,
60
- candidates,
61
- insertsSinceDecay: this.insertsSinceDecay,
62
- };
63
- }
64
- insert(prefix, suffix, weight) {
65
- if (prefix.length === 0 || suffix.length === 0)
66
- return;
67
- if (containsSensitive(prefix) || containsSensitive(suffix))
68
- return;
69
- this.bumpCandidate(prefix, suffix, weight);
70
- this.tickDecayCounter();
71
- this.enforceCapacity();
72
- }
73
- /**
74
- * Insert prefix→remainder pairs from an accepted ghost: prefix is the
75
- * editor text immediately before the ghost; the full accepted suffix is
76
- * the value. Weight is the caller's choice (+3 full, +2 partial-word, +1
77
- * full-candidate-on-partial). Caller handles signal selection.
78
- */
79
- insertFromAccept(prefix, suffix, weight) {
80
- this.insert(prefix, suffix, weight);
81
- }
82
- /**
83
- * Insert sliding-window prefix→remainder pairs from a committed user
84
- * message at weight +1 each (PRD §M2). Prefix lengths 3..12 chars,
85
- * remainder capped at 4 word-boundary shingles to limit memory and avoid
86
- * memorizing entire messages.
87
- *
88
- * Skips the whole message if any token matches a sensitive pattern.
89
- */
90
- insertFromCommittedMessage(text, weightPerShingle = 1) {
91
- const trimmed = text.trim();
92
- if (!trimmed)
93
- return;
94
- if (containsSensitive(trimmed))
95
- return;
96
- const wordBoundaries = collectWordBoundaries(trimmed);
97
- if (wordBoundaries.length === 0)
98
- return;
99
- for (let prefixLen = MIN_PREFIX_LEN; prefixLen <= MAX_COMMITTED_PREFIX_LEN && prefixLen < trimmed.length; prefixLen++) {
100
- const prefix = trimmed.slice(0, prefixLen);
101
- const suffix = sliceWordsAfter(trimmed, prefixLen, wordBoundaries, MAX_COMMITTED_SUFFIX_WORDS);
102
- if (!suffix)
103
- continue;
104
- this.bumpCandidate(prefix, suffix, weightPerShingle);
105
- }
106
- this.tickDecayCounter();
107
- this.enforceCapacity();
108
- }
109
- /**
110
- * Penalize an entry that diverged from the user's eventual commit.
111
- * Per-keystroke dismisses must NOT call this (would penalize correct
112
- * ghosts mid-typing). See PRD §M2.
113
- */
114
- penalize(prefix, suffix, magnitude = 0.5) {
115
- magnitude = Math.max(0, magnitude);
116
- const bucket = this.map.get(prefix);
117
- if (!bucket)
118
- return;
119
- const current = bucket.get(suffix);
120
- if (current === undefined)
121
- return;
122
- const next = current - magnitude;
123
- if (next <= 0) {
124
- bucket.delete(suffix);
125
- if (bucket.size === 0)
126
- this.map.delete(prefix);
127
- }
128
- else {
129
- bucket.set(suffix, next);
130
- }
131
- }
132
- lookup(prefix) {
133
- if (prefix.length < MIN_PREFIX_LEN)
134
- return null;
135
- // Walk from longest to shortest prefix. The longest match that satisfies
136
- // weight + margin wins. For a stored entry whose key is shorter than the
137
- // user's current prefix, the user has already typed part of the
138
- // suggested suffix → shift the ghost accordingly (typeahead-delta logic,
139
- // same idea as `tryWarm`'s typeahead branch). If the user's typing
140
- // diverges from the stored suffix, that candidate is skipped.
141
- const maxLen = prefix.length;
142
- for (let keyLen = maxLen; keyLen >= MIN_PREFIX_LEN; keyLen--) {
143
- const key = prefix.slice(0, keyLen);
144
- const bucket = this.map.get(key);
145
- if (!bucket || bucket.size === 0)
146
- continue;
147
- const typedDelta = prefix.slice(keyLen);
148
- let bestSuffix = null;
149
- let bestWeight = -Infinity;
150
- let runnerUp = 0;
151
- for (const [suffix, weight] of bucket) {
152
- // Stored suffix must agree with what the user typed since `key`.
153
- if (typedDelta.length > 0 && !suffix.startsWith(typedDelta))
154
- continue;
155
- if (weight > bestWeight) {
156
- runnerUp = bestWeight === -Infinity ? 0 : bestWeight;
157
- bestWeight = weight;
158
- bestSuffix = suffix;
159
- }
160
- else if (weight > runnerUp) {
161
- runnerUp = weight;
162
- }
163
- }
164
- if (bestSuffix === null)
165
- continue;
166
- if (bestWeight < MIN_WEIGHT)
167
- continue;
168
- const margin = bestWeight - runnerUp;
169
- if (margin < MIN_MARGIN)
170
- continue;
171
- const shifted = bestSuffix.slice(typedDelta.length);
172
- if (shifted.length === 0)
173
- continue;
174
- // LRU touch on hit.
175
- this.map.delete(key);
176
- this.map.set(key, bucket);
177
- return { ghost: shifted, weight: bestWeight, margin };
178
- }
179
- return null;
180
- }
181
- clear() {
182
- this.map.clear();
183
- this.insertsSinceDecay = 0;
184
- }
185
- /**
186
- * Halve all weights. Exposed for testing; callers normally rely on the
187
- * automatic decay every `decayEvery` inserts.
188
- */
189
- decayNow() {
190
- for (const bucket of this.map.values()) {
191
- for (const [suffix, weight] of bucket) {
192
- const next = weight * this.decayFactor;
193
- if (next < 0.05)
194
- bucket.delete(suffix);
195
- else
196
- bucket.set(suffix, next);
197
- }
198
- }
199
- // Drop empty buckets.
200
- for (const [prefix, bucket] of this.map) {
201
- if (bucket.size === 0)
202
- this.map.delete(prefix);
203
- }
204
- this.insertsSinceDecay = 0;
205
- }
206
- bumpCandidate(prefix, suffix, weight) {
207
- let bucket = this.map.get(prefix);
208
- if (bucket) {
209
- // LRU touch.
210
- this.map.delete(prefix);
211
- }
212
- else {
213
- bucket = new Map();
214
- }
215
- bucket.set(suffix, (bucket.get(suffix) ?? 0) + weight);
216
- this.map.set(prefix, bucket);
217
- }
218
- tickDecayCounter() {
219
- this.insertsSinceDecay++;
220
- if (this.insertsSinceDecay >= this.decayEvery) {
221
- this.decayNow();
222
- }
223
- }
224
- enforceCapacity() {
225
- while (this.map.size > this.capacity) {
226
- const oldest = this.map.keys().next().value;
227
- if (oldest === undefined)
228
- break;
229
- this.map.delete(oldest);
230
- }
231
- }
232
- }
233
- /**
234
- * Return the end-of-word offsets in `text` (exclusive). For "ab cd ef", returns
235
- * [2, 5, 8]. Used to align committed-message shingles to word boundaries.
236
- */
237
- /**
238
- * Pure helper used by `GhostEditor.onPromptCommitted`. Seeds `trie` from the
239
- * committed text. If `accepted` is non-null AND the committed text contains
240
- * the accepted ghost, the per-shingle weight drops from +1 to +0.25 to avoid
241
- * double-counting (PRD §M2 "Insertion signals").
242
- */
243
- export function seedTrieFromCommit(trie, text, accepted) {
244
- if (!text)
245
- return;
246
- const overlaps = accepted ? text.includes(accepted.ghost) : false;
247
- trie.insertFromCommittedMessage(text, overlaps ? 0.25 : 1);
248
- }
249
- function collectWordBoundaries(text) {
250
- const out = [];
251
- let inWord = false;
252
- for (let i = 0; i < text.length; i++) {
253
- const ch = text[i];
254
- const isWS = /\s/.test(ch);
255
- if (!isWS && !inWord)
256
- inWord = true;
257
- if (isWS && inWord) {
258
- out.push(i);
259
- inWord = false;
260
- }
261
- }
262
- if (inWord)
263
- out.push(text.length);
264
- return out;
265
- }
266
- function sliceWordsAfter(text, start, boundaries, maxWords) {
267
- let crossed = 0;
268
- let end = text.length;
269
- for (const b of boundaries) {
270
- if (b <= start)
271
- continue;
272
- crossed++;
273
- if (crossed >= maxWords) {
274
- end = b;
275
- break;
276
- }
277
- }
278
- return text.slice(start, end);
279
- }
280
- //# sourceMappingURL=session-trie.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-trie.js","sourceRoot":"","sources":["../src/session-trie.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAChC,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC;AAC9B,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AACrC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACxC,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAC3C,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAc5C,MAAM,OAAO,WAAW;IAUL;IACA;IACA;IAXlB;;;;OAIG;IACc,GAAG,GAAG,IAAI,GAAG,EAA+B,CAAC;IACtD,iBAAiB,GAAG,CAAC,CAAC;IAE9B,YACkB,WAAmB,gBAAgB,EACnC,aAAqB,mBAAmB,EACxC,cAAsB,oBAAoB;QAF1C,aAAQ,GAAR,QAAQ,CAA2B;QACnC,eAAU,GAAV,UAAU,CAA8B;QACxC,gBAAW,GAAX,WAAW,CAA+B;QAE3D,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,gBAAgB,CAAC;QAClC,CAAC;IACF,CAAC;IAED,IAAI,IAAI;QACP,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACtB,CAAC;IAED,IAAI,KAAK;QACR,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE;YAAE,UAAU,IAAI,CAAC,CAAC,IAAI,CAAC;QACxD,OAAO;YACN,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI;YACvB,UAAU;YACV,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;SACzC,CAAC;IACH,CAAC;IAED,MAAM,CAAC,MAAc,EAAE,MAAc,EAAE,MAAc;QACpD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACvD,IAAI,iBAAiB,CAAC,MAAM,CAAC,IAAI,iBAAiB,CAAC,MAAM,CAAC;YAAE,OAAO;QACnE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACH,gBAAgB,CAAC,MAAc,EAAE,MAAc,EAAE,MAAc;QAC9D,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAED;;;;;;;OAOG;IACH,0BAA0B,CAAC,IAAY,EAAE,gBAAgB,GAAG,CAAC;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,IAAI,iBAAiB,CAAC,OAAO,CAAC;YAAE,OAAO;QACvC,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACxC,KACC,IAAI,SAAS,GAAG,cAAc,EAC9B,SAAS,IAAI,wBAAwB,IAAI,SAAS,GAAG,OAAO,CAAC,MAAM,EACnE,SAAS,EAAE,EACV,CAAC;YACF,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,eAAe,CAC7B,OAAO,EACP,SAAS,EACT,cAAc,EACd,0BAA0B,CAC1B,CAAC;YACF,IAAI,CAAC,MAAM;gBAAE,SAAS;YACtB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,MAAc,EAAE,MAAc,EAAE,SAAS,GAAG,GAAG;QACvD,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO;QAClC,MAAM,IAAI,GAAG,OAAO,GAAG,SAAS,CAAC;QACjC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACf,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtB,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1B,CAAC;IACF,CAAC;IAED,MAAM,CAAC,MAAc;QACpB,IAAI,MAAM,CAAC,MAAM,GAAG,cAAc;YAAE,OAAO,IAAI,CAAC;QAEhD,yEAAyE;QACzE,yEAAyE;QACzE,gEAAgE;QAChE,yEAAyE;QACzE,mEAAmE;QACnE,8DAA8D;QAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,KAAK,IAAI,MAAM,GAAG,MAAM,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;YAC9D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;gBAAE,SAAS;YAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAExC,IAAI,UAAU,GAAkB,IAAI,CAAC;YACrC,IAAI,UAAU,GAAG,CAAC,QAAQ,CAAC;YAC3B,IAAI,QAAQ,GAAG,CAAC,CAAC;YACjB,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvC,iEAAiE;gBACjE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;oBAAE,SAAS;gBACtE,IAAI,MAAM,GAAG,UAAU,EAAE,CAAC;oBACzB,QAAQ,GAAG,UAAU,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;oBACrD,UAAU,GAAG,MAAM,CAAC;oBACpB,UAAU,GAAG,MAAM,CAAC;gBACrB,CAAC;qBAAM,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;oBAC9B,QAAQ,GAAG,MAAM,CAAC;gBACnB,CAAC;YACF,CAAC;YACD,IAAI,UAAU,KAAK,IAAI;gBAAE,SAAS;YAClC,IAAI,UAAU,GAAG,UAAU;gBAAE,SAAS;YACtC,MAAM,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;YACrC,IAAI,MAAM,GAAG,UAAU;gBAAE,SAAS;YAElC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEnC,oBAAoB;YACpB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC1B,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QACvD,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACjB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,QAAQ;QACP,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;YACxC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvC,MAAM,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC;gBACvC,IAAI,IAAI,GAAG,IAAI;oBAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;;oBAClC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC/B,CAAC;QACF,CAAC;QACD,sBAAsB;QACtB,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACzC,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAC5B,CAAC;IAEO,aAAa,CAAC,MAAc,EAAE,MAAc,EAAE,MAAc;QACnE,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,MAAM,EAAE,CAAC;YACZ,aAAa;YACb,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACP,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACpC,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,CAAC;IAEO,gBAAgB;QACvB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjB,CAAC;IACF,CAAC;IAEO,eAAe;QACtB,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAC5C,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM;YAChC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;IACF,CAAC;CACD;AAED;;;GAGG;AACH;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CACjC,IAAiB,EACjB,IAAY,EACZ,QAAkD;IAElD,IAAI,CAAC,IAAI;QAAE,OAAO;IAClB,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,IAAI,CAAC,0BAA0B,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,GAAG,IAAI,CAAC;QACpC,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;YACpB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACZ,MAAM,GAAG,KAAK,CAAC;QAChB,CAAC;IACF,CAAC;IACD,IAAI,MAAM;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,SAAS,eAAe,CACvB,IAAY,EACZ,KAAa,EACb,UAAoB,EACpB,QAAgB;IAEhB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,KAAK;YAAE,SAAS;QACzB,OAAO,EAAE,CAAC;QACV,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;YACzB,GAAG,GAAG,CAAC,CAAC;YACR,MAAM;QACP,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC"}
@@ -1,74 +0,0 @@
1
- /**
2
- * Speculative cache warm — covers the gap between an exact cache hit and a
3
- * full LLM call. See PRD §6 M1b.
4
- *
5
- * Three match branches:
6
- * - exact: prefix matches a recent ghost's prefix → reuse the ghost.
7
- * - typeahead-delta: user typed forward into the ghost text → return the
8
- * remaining ghost suffix.
9
- * - backspace-of-N: user backspaced ≤3 chars within an old prefix → return
10
- * droppedTail + oldGhost. Only fires while the race is in cooldown,
11
- * because a fresh LLM call is preferable when budget allows.
12
- *
13
- * All branches require context/provider/version fingerprints to match the
14
- * shown ghost to avoid leaking stale results across context shifts.
15
- */
16
- export interface LastGhost {
17
- prefix: string;
18
- ghost: string;
19
- ts: number;
20
- contextFingerprint: string;
21
- providerFingerprint: string;
22
- versionFingerprint: string;
23
- /** Engine config fingerprint at the time this entry was recorded
24
- * (refactor #57 phase 2). Optional — entries without it match any
25
- * fingerprint (legacy + test-fixture compatibility). */
26
- configFingerprint?: string;
27
- /**
28
- * Originating provider name (e.g. "mercury-edit", "ghost-race:..."). Used
29
- * by the editor to attribute speculative-warm metrics back to the provider
30
- * that produced the source ghost, instead of the synthetic "speculative-warm"
31
- * label. See PRD §5b.
32
- */
33
- providerName: string;
34
- }
35
- export interface SpeculativeMatchInput {
36
- prefix: string;
37
- contextFingerprint: string;
38
- providerFingerprint: string;
39
- versionFingerprint: string;
40
- /** Engine config fingerprint to match against. Optional — when omitted,
41
- * the warm path skips the config check (legacy / test compatibility). */
42
- configFingerprint?: string;
43
- cooldownActive: boolean;
44
- }
45
- export type SpeculativeBranch = "exact" | "typeahead-delta" | "backspace-of-N";
46
- export interface SpeculativeMatch {
47
- ghost: string;
48
- branch: SpeculativeBranch;
49
- source: LastGhost;
50
- }
51
- /**
52
- * Fixed-capacity ring of recent ghosts. The newest entry sits at the end.
53
- */
54
- export declare class LastGhostsRing {
55
- private readonly capacity;
56
- private readonly buf;
57
- constructor(capacity?: number);
58
- get size(): number;
59
- push(entry: LastGhost): void;
60
- entries(): readonly LastGhost[];
61
- clear(): void;
62
- }
63
- /**
64
- * Try to satisfy a prefix from `ring` without firing the LLM. Returns the
65
- * first match across exact / typeahead-delta / backspace-N. Newest entries
66
- * are checked first.
67
- *
68
- * Grapheme-aware slicing is NOT applied here — the editor passes string
69
- * prefixes/ghosts that were already produced grapheme-aware in
70
- * `ghost-editor.ts`. The PRD's grapheme-awareness requirement is for the
71
- * editor's slicing; this helper operates on the resulting strings.
72
- */
73
- export declare function tryWarm(ring: LastGhostsRing, input: SpeculativeMatchInput): SpeculativeMatch | null;
74
- //# sourceMappingURL=speculative.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"speculative.d.ts","sourceRoot":"","sources":["../src/speculative.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,WAAW,SAAS;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;6DAEyD;IACzD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B;8EAC0E;IAC1E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE/E,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,SAAS,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,cAAc;IAGd,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAFrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAmB;gBAEV,QAAQ,GAAE,MAAU;IAEjD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAoB5B,OAAO,IAAI,SAAS,SAAS,EAAE;IAI/B,KAAK,IAAI,IAAI;CAGb;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CACtB,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,qBAAqB,GAC1B,gBAAgB,GAAG,IAAI,CAmDzB"}
@@ -1,107 +0,0 @@
1
- /**
2
- * Speculative cache warm — covers the gap between an exact cache hit and a
3
- * full LLM call. See PRD §6 M1b.
4
- *
5
- * Three match branches:
6
- * - exact: prefix matches a recent ghost's prefix → reuse the ghost.
7
- * - typeahead-delta: user typed forward into the ghost text → return the
8
- * remaining ghost suffix.
9
- * - backspace-of-N: user backspaced ≤3 chars within an old prefix → return
10
- * droppedTail + oldGhost. Only fires while the race is in cooldown,
11
- * because a fresh LLM call is preferable when budget allows.
12
- *
13
- * All branches require context/provider/version fingerprints to match the
14
- * shown ghost to avoid leaking stale results across context shifts.
15
- */
16
- const BACKSPACE_MAX_DELTA = 3;
17
- /**
18
- * Fixed-capacity ring of recent ghosts. The newest entry sits at the end.
19
- */
20
- export class LastGhostsRing {
21
- capacity;
22
- buf = [];
23
- constructor(capacity = 8) {
24
- this.capacity = capacity;
25
- }
26
- get size() {
27
- return this.buf.length;
28
- }
29
- push(entry) {
30
- // Treat (prefix, providerFingerprint, contextFingerprint, versionFingerprint)
31
- // as the identity. A new completion for the same prefix in the same context
32
- // supersedes the older one.
33
- for (let i = 0; i < this.buf.length; i++) {
34
- const e = this.buf[i];
35
- if (e.prefix === entry.prefix &&
36
- e.contextFingerprint === entry.contextFingerprint &&
37
- e.providerFingerprint === entry.providerFingerprint &&
38
- e.versionFingerprint === entry.versionFingerprint) {
39
- this.buf.splice(i, 1);
40
- break;
41
- }
42
- }
43
- this.buf.push(entry);
44
- while (this.buf.length > this.capacity)
45
- this.buf.shift();
46
- }
47
- entries() {
48
- return this.buf;
49
- }
50
- clear() {
51
- this.buf.length = 0;
52
- }
53
- }
54
- /**
55
- * Try to satisfy a prefix from `ring` without firing the LLM. Returns the
56
- * first match across exact / typeahead-delta / backspace-N. Newest entries
57
- * are checked first.
58
- *
59
- * Grapheme-aware slicing is NOT applied here — the editor passes string
60
- * prefixes/ghosts that were already produced grapheme-aware in
61
- * `ghost-editor.ts`. The PRD's grapheme-awareness requirement is for the
62
- * editor's slicing; this helper operates on the resulting strings.
63
- */
64
- export function tryWarm(ring, input) {
65
- const entries = ring.entries();
66
- // Newest first.
67
- for (let i = entries.length - 1; i >= 0; i--) {
68
- const lg = entries[i];
69
- if (lg.contextFingerprint !== input.contextFingerprint ||
70
- lg.providerFingerprint !== input.providerFingerprint ||
71
- lg.versionFingerprint !== input.versionFingerprint) {
72
- continue;
73
- }
74
- // Config fingerprint folded in #57 phase 2 — skip the check when
75
- // either side is undefined (legacy entries / test fixtures); reject
76
- // only when both are defined and differ.
77
- if (lg.configFingerprint !== undefined &&
78
- input.configFingerprint !== undefined &&
79
- lg.configFingerprint !== input.configFingerprint) {
80
- continue;
81
- }
82
- // Branch 1: exact prefix match (always short-circuit).
83
- if (lg.prefix === input.prefix) {
84
- return { ghost: lg.ghost, branch: "exact", source: lg };
85
- }
86
- // Branch 2: typeahead-delta — user typed forward into the ghost.
87
- if (input.prefix.startsWith(lg.prefix)) {
88
- const delta = input.prefix.slice(lg.prefix.length);
89
- if (delta.length > 0 && lg.ghost.startsWith(delta)) {
90
- const remainder = lg.ghost.slice(delta.length);
91
- if (remainder.length > 0) {
92
- return { ghost: remainder, branch: "typeahead-delta", source: lg };
93
- }
94
- }
95
- }
96
- // Branch 3: backspace-of-N — only when cooldown is active.
97
- if (input.cooldownActive &&
98
- lg.prefix.startsWith(input.prefix) &&
99
- lg.prefix.length > input.prefix.length &&
100
- lg.prefix.length - input.prefix.length <= BACKSPACE_MAX_DELTA) {
101
- const droppedTail = lg.prefix.slice(input.prefix.length);
102
- return { ghost: droppedTail + lg.ghost, branch: "backspace-of-N", source: lg };
103
- }
104
- }
105
- return null;
106
- }
107
- //# sourceMappingURL=speculative.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"speculative.js","sourceRoot":"","sources":["../src/speculative.ts"],"names":[],"mappings":"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"}
@@ -1,40 +0,0 @@
1
- /**
2
- * Type-aware compact summaries of tool outputs for inclusion in ghost
3
- * context. See PRD §M6c.
4
- *
5
- * Each summarizer takes the flattened tool message (`toolName` + raw
6
- * `text`) and produces a short, typed description. The goal is to
7
- * preserve the *signal* of the tool result (file path, command, exit
8
- * code, top symbol) without dragging the full output into the prompt.
9
- *
10
- * Pure module: no I/O. Dispatch by `toolName` (case-insensitive); falls
11
- * back to a generic short-line summary for unknown tools.
12
- */
13
- import type { RecentMessage } from "./context-aggregator.js";
14
- export declare const DEFAULT_TOOL_MAX = 3;
15
- export interface ToolSummary {
16
- text: string;
17
- }
18
- /**
19
- * Summarize a single tool entry. Returns a new `RecentMessage` with the
20
- * compact summary as `text`; preserves `role` and `toolName`.
21
- *
22
- * Note: PRD §M6c specs this as `summarizeToolResult(entry): ToolSummary`
23
- * — we deviate by returning a `RecentMessage` so callers can preserve
24
- * `role`/`toolName` for downstream prompt formatting in `truncate.ts` and
25
- * `openai-compat-provider.ts`. The internal `ToolSummary` type is the
26
- * dispatcher return; it carries the rewritten `text` only.
27
- */
28
- export declare function summarizeToolEntry(entry: RecentMessage): RecentMessage;
29
- /**
30
- * Apply summarization across an array, optionally capping the number of
31
- * tool entries retained (PRD §M6c: cap 3 by default). Non-tool entries
32
- * pass through unchanged.
33
- */
34
- export declare function summarizeAndCapTools(entries: RecentMessage[], maxTools?: number): RecentMessage[];
35
- /**
36
- * Parse `PI_GHOST_CONTEXT_TOOL_MAX`. Returns fallback on bad input or
37
- * negative values.
38
- */
39
- export declare function parseToolMaxEnv(raw: string | undefined): number;
40
- //# sourceMappingURL=tool-summarize.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool-summarize.d.ts","sourceRoot":"","sources":["../src/tool-summarize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAKlC,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAKtE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,aAAa,EAAE,EACxB,QAAQ,GAAE,MAAyB,GACjC,aAAa,EAAE,CAgBjB;AAoLD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAK/D"}