pi-ghost-autocomplete 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +561 -0
- package/README.md +186 -4
- package/dist/bench-cli.js +1 -123
- package/dist/bench.d.ts +7 -3
- package/dist/bench.js +1 -522
- package/dist/config.d.ts +46 -3
- package/dist/context-aggregator.d.ts +4 -1
- package/dist/cycle-manager.d.ts +2 -21
- package/dist/entropy-stop.d.ts +4 -1
- package/dist/eval-dataset.d.ts +2 -13
- package/dist/fuzzy-matcher.d.ts +4 -1
- package/dist/ghost-editor.d.ts +11 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +1 -289
- package/dist/intent.d.ts +179 -0
- package/dist/metrics.d.ts +4 -1
- package/dist/path-index.d.ts +4 -1
- package/dist/path-matcher.d.ts +4 -1
- package/dist/profile-store.d.ts +4 -1
- package/dist/profile.d.ts +2 -20
- package/dist/providers/cloud-provider.d.ts +4 -1
- package/dist/providers/local-provider.d.ts +4 -1
- package/dist/providers/openai-compat-chat-provider.d.ts +31 -0
- package/dist/providers/openai-compat-provider.d.ts +24 -1
- package/dist/providers/race.d.ts +4 -1
- package/dist/providers/router.d.ts +59 -0
- package/dist/providers/types.d.ts +13 -1
- package/dist/recent-paths.d.ts +4 -1
- package/dist/replay-cli.js +1 -166
- package/dist/replay.d.ts +2 -7
- package/package.json +10 -6
- package/dist/bench-cli.d.ts +0 -3
- package/dist/bench-cli.d.ts.map +0 -1
- package/dist/bench-cli.js.map +0 -1
- package/dist/bench.d.ts.map +0 -1
- package/dist/bench.js.map +0 -1
- package/dist/cache.d.ts +0 -124
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js +0 -173
- package/dist/cache.js.map +0 -1
- package/dist/candidate-rerank.d.ts +0 -57
- package/dist/candidate-rerank.d.ts.map +0 -1
- package/dist/candidate-rerank.js +0 -78
- package/dist/candidate-rerank.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -317
- package/dist/config.js.map +0 -1
- package/dist/context-aggregator.d.ts.map +0 -1
- package/dist/context-aggregator.js +0 -87
- package/dist/context-aggregator.js.map +0 -1
- package/dist/context-selector.d.ts +0 -128
- package/dist/context-selector.d.ts.map +0 -1
- package/dist/context-selector.js +0 -300
- package/dist/context-selector.js.map +0 -1
- package/dist/cycle-manager.d.ts.map +0 -1
- package/dist/cycle-manager.js +0 -168
- package/dist/cycle-manager.js.map +0 -1
- package/dist/edit-history-ring.d.ts +0 -148
- package/dist/edit-history-ring.d.ts.map +0 -1
- package/dist/edit-history-ring.js +0 -262
- package/dist/edit-history-ring.js.map +0 -1
- package/dist/entropy-stop.d.ts.map +0 -1
- package/dist/entropy-stop.js +0 -141
- package/dist/entropy-stop.js.map +0 -1
- package/dist/eval-dataset.d.ts.map +0 -1
- package/dist/eval-dataset.js +0 -127
- package/dist/eval-dataset.js.map +0 -1
- package/dist/fast-path-engine.d.ts +0 -286
- package/dist/fast-path-engine.d.ts.map +0 -1
- package/dist/fast-path-engine.js +0 -341
- package/dist/fast-path-engine.js.map +0 -1
- package/dist/fuzzy-matcher.d.ts.map +0 -1
- package/dist/fuzzy-matcher.js +0 -162
- package/dist/fuzzy-matcher.js.map +0 -1
- package/dist/ghost-editor.d.ts.map +0 -1
- package/dist/ghost-editor.js +0 -1491
- package/dist/ghost-editor.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/keystroke-timer.d.ts +0 -59
- package/dist/keystroke-timer.d.ts.map +0 -1
- package/dist/keystroke-timer.js +0 -94
- package/dist/keystroke-timer.js.map +0 -1
- package/dist/metrics-builder.d.ts +0 -71
- package/dist/metrics-builder.d.ts.map +0 -1
- package/dist/metrics-builder.js +0 -71
- package/dist/metrics-builder.js.map +0 -1
- package/dist/metrics.d.ts.map +0 -1
- package/dist/metrics.js +0 -212
- package/dist/metrics.js.map +0 -1
- package/dist/path-index.d.ts.map +0 -1
- package/dist/path-index.js +0 -148
- package/dist/path-index.js.map +0 -1
- package/dist/path-matcher.d.ts.map +0 -1
- package/dist/path-matcher.js +0 -88
- package/dist/path-matcher.js.map +0 -1
- package/dist/profile-store.d.ts.map +0 -1
- package/dist/profile-store.js +0 -199
- package/dist/profile-store.js.map +0 -1
- package/dist/profile.d.ts.map +0 -1
- package/dist/profile.js +0 -434
- package/dist/profile.js.map +0 -1
- package/dist/providers/cloud-provider.d.ts.map +0 -1
- package/dist/providers/cloud-provider.js +0 -109
- package/dist/providers/cloud-provider.js.map +0 -1
- package/dist/providers/local-provider.d.ts.map +0 -1
- package/dist/providers/local-provider.js +0 -48
- package/dist/providers/local-provider.js.map +0 -1
- package/dist/providers/openai-compat-provider.d.ts.map +0 -1
- package/dist/providers/openai-compat-provider.js +0 -215
- package/dist/providers/openai-compat-provider.js.map +0 -1
- package/dist/providers/openai-completions-runner.d.ts +0 -52
- package/dist/providers/openai-completions-runner.d.ts.map +0 -1
- package/dist/providers/openai-completions-runner.js +0 -141
- package/dist/providers/openai-completions-runner.js.map +0 -1
- package/dist/providers/race.d.ts.map +0 -1
- package/dist/providers/race.js +0 -441
- package/dist/providers/race.js.map +0 -1
- package/dist/providers/truncate.d.ts +0 -7
- package/dist/providers/truncate.d.ts.map +0 -1
- package/dist/providers/truncate.js +0 -57
- package/dist/providers/truncate.js.map +0 -1
- package/dist/providers/types.d.ts.map +0 -1
- package/dist/providers/types.js +0 -60
- package/dist/providers/types.js.map +0 -1
- package/dist/provisional-manager.d.ts +0 -93
- package/dist/provisional-manager.d.ts.map +0 -1
- package/dist/provisional-manager.js +0 -98
- package/dist/provisional-manager.js.map +0 -1
- package/dist/provisional.d.ts +0 -150
- package/dist/provisional.d.ts.map +0 -1
- package/dist/provisional.js +0 -238
- package/dist/provisional.js.map +0 -1
- package/dist/recent-paths.d.ts.map +0 -1
- package/dist/recent-paths.js +0 -114
- package/dist/recent-paths.js.map +0 -1
- package/dist/regret-tracker.d.ts +0 -84
- package/dist/regret-tracker.d.ts.map +0 -1
- package/dist/regret-tracker.js +0 -145
- package/dist/regret-tracker.js.map +0 -1
- package/dist/replay-cli.d.ts +0 -13
- package/dist/replay-cli.d.ts.map +0 -1
- package/dist/replay-cli.js.map +0 -1
- package/dist/replay.d.ts.map +0 -1
- package/dist/replay.js +0 -225
- package/dist/replay.js.map +0 -1
- package/dist/reranker.d.ts +0 -181
- package/dist/reranker.d.ts.map +0 -1
- package/dist/reranker.js +0 -324
- package/dist/reranker.js.map +0 -1
- package/dist/session-trie.d.ts +0 -103
- package/dist/session-trie.d.ts.map +0 -1
- package/dist/session-trie.js +0 -280
- package/dist/session-trie.js.map +0 -1
- package/dist/speculative.d.ts +0 -74
- package/dist/speculative.d.ts.map +0 -1
- package/dist/speculative.js +0 -107
- package/dist/speculative.js.map +0 -1
- package/dist/tool-summarize.d.ts +0 -40
- package/dist/tool-summarize.d.ts.map +0 -1
- package/dist/tool-summarize.js +0 -245
- package/dist/tool-summarize.js.map +0 -1
- package/dist/trie-sanitize.d.ts +0 -22
- package/dist/trie-sanitize.d.ts.map +0 -1
- package/dist/trie-sanitize.js +0 -142
- package/dist/trie-sanitize.js.map +0 -1
- package/dist/versions.d.ts +0 -23
- package/dist/versions.d.ts.map +0 -1
- package/dist/versions.js +0 -31
- package/dist/versions.js.map +0 -1
package/dist/tool-summarize.js
DELETED
|
@@ -1,245 +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
|
-
export const DEFAULT_TOOL_MAX = 3;
|
|
14
|
-
const UNKNOWN_CAP = 120;
|
|
15
|
-
const BASH_LINE_CAP = 200;
|
|
16
|
-
const READ_LINE_CAP = 200;
|
|
17
|
-
/**
|
|
18
|
-
* Summarize a single tool entry. Returns a new `RecentMessage` with the
|
|
19
|
-
* compact summary as `text`; preserves `role` and `toolName`.
|
|
20
|
-
*
|
|
21
|
-
* Note: PRD §M6c specs this as `summarizeToolResult(entry): ToolSummary`
|
|
22
|
-
* — we deviate by returning a `RecentMessage` so callers can preserve
|
|
23
|
-
* `role`/`toolName` for downstream prompt formatting in `truncate.ts` and
|
|
24
|
-
* `openai-compat-provider.ts`. The internal `ToolSummary` type is the
|
|
25
|
-
* dispatcher return; it carries the rewritten `text` only.
|
|
26
|
-
*/
|
|
27
|
-
export function summarizeToolEntry(entry) {
|
|
28
|
-
if (entry.role !== "tool")
|
|
29
|
-
return entry;
|
|
30
|
-
const name = (entry.toolName ?? "").toLowerCase();
|
|
31
|
-
const summary = pickSummarizer(name)(entry.text);
|
|
32
|
-
return { ...entry, text: summary.text };
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Apply summarization across an array, optionally capping the number of
|
|
36
|
-
* tool entries retained (PRD §M6c: cap 3 by default). Non-tool entries
|
|
37
|
-
* pass through unchanged.
|
|
38
|
-
*/
|
|
39
|
-
export function summarizeAndCapTools(entries, maxTools = DEFAULT_TOOL_MAX) {
|
|
40
|
-
let toolsKept = 0;
|
|
41
|
-
const out = [];
|
|
42
|
-
// Walk newest-first so the most-recent tool entries are kept when the
|
|
43
|
-
// cap is reached; flip back to original order at the end.
|
|
44
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
45
|
-
const e = entries[i];
|
|
46
|
-
if (e.role === "tool") {
|
|
47
|
-
if (toolsKept >= maxTools)
|
|
48
|
-
continue;
|
|
49
|
-
toolsKept++;
|
|
50
|
-
out.push(summarizeToolEntry(e));
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
out.push(e);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return out.reverse();
|
|
57
|
-
}
|
|
58
|
-
function pickSummarizer(name) {
|
|
59
|
-
if (name === "read")
|
|
60
|
-
return summarizeRead;
|
|
61
|
-
if (name === "bash" || name === "shell")
|
|
62
|
-
return summarizeBash;
|
|
63
|
-
if (name === "edit" || name === "write")
|
|
64
|
-
return summarizeEdit;
|
|
65
|
-
if (name === "analyze_image")
|
|
66
|
-
return summarizeAnalyzeImage;
|
|
67
|
-
if (name.includes("codebase") || name.includes("retrieval")) {
|
|
68
|
-
return summarizeCodebaseRetrieval;
|
|
69
|
-
}
|
|
70
|
-
return summarizeUnknown;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Summarize a file read. Format: `read PATH — FIRST_SIGNATURE_OR_HEADING`.
|
|
74
|
-
* The signature line is the first non-empty line that looks like a
|
|
75
|
-
* declaration (function/class/export) or a heading (#-prefixed).
|
|
76
|
-
*/
|
|
77
|
-
function summarizeRead(text) {
|
|
78
|
-
const path = extractFirstPath(text);
|
|
79
|
-
const sig = firstSignatureLine(text, path);
|
|
80
|
-
const left = path ? `read ${path}` : "read";
|
|
81
|
-
if (!sig)
|
|
82
|
-
return { text: left };
|
|
83
|
-
return { text: `${left} — ${truncateLine(sig, READ_LINE_CAP)}` };
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Summarize a bash run. Format: `bash $ COMMAND — exit=N LAST_LINE`.
|
|
87
|
-
* When no obvious command/exit can be parsed, fall back to first +
|
|
88
|
-
* last non-empty line.
|
|
89
|
-
*/
|
|
90
|
-
function summarizeBash(text) {
|
|
91
|
-
const lines = nonEmptyLines(text);
|
|
92
|
-
if (lines.length === 0)
|
|
93
|
-
return { text: "bash" };
|
|
94
|
-
const command = extractBashCommand(text) ?? lines[0];
|
|
95
|
-
const exit = extractExitCode(text);
|
|
96
|
-
const last = lines[lines.length - 1];
|
|
97
|
-
const exitPart = exit !== undefined ? `exit=${exit}` : "";
|
|
98
|
-
const tailPart = last && last !== command ? truncateLine(last, BASH_LINE_CAP) : "";
|
|
99
|
-
const parts = [`bash $ ${truncateLine(command, 100)}`];
|
|
100
|
-
if (exitPart || tailPart) {
|
|
101
|
-
parts.push("—", [exitPart, tailPart].filter((s) => s.length > 0).join(" "));
|
|
102
|
-
}
|
|
103
|
-
return { text: parts.join(" ").trim() };
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Summarize an edit/write. Format: `edit PATH (N changes)` if change
|
|
107
|
-
* count is detectable; otherwise just `edit PATH`.
|
|
108
|
-
*/
|
|
109
|
-
function summarizeEdit(text) {
|
|
110
|
-
const path = extractFirstPath(text);
|
|
111
|
-
if (!path)
|
|
112
|
-
return { text: "edit" };
|
|
113
|
-
const changes = extractChangeCount(text);
|
|
114
|
-
return { text: changes !== undefined ? `edit ${path} (${changes} change${changes === 1 ? "" : "s"})` : `edit ${path}` };
|
|
115
|
-
}
|
|
116
|
-
function summarizeAnalyzeImage(text) {
|
|
117
|
-
const filename = extractFirstPath(text);
|
|
118
|
-
// Skip the filename line when picking the summary; otherwise the summary
|
|
119
|
-
// equals the filename itself.
|
|
120
|
-
const summary = firstNonEmptyLineSkipping(text, filename);
|
|
121
|
-
const left = filename ? `analyze_image ${filename}` : "analyze_image";
|
|
122
|
-
if (!summary)
|
|
123
|
-
return { text: left };
|
|
124
|
-
return { text: `${left} — ${truncateLine(summary, UNKNOWN_CAP)}` };
|
|
125
|
-
}
|
|
126
|
-
function firstNonEmptyLineSkipping(text, skip) {
|
|
127
|
-
for (const l of text.split(/\r?\n/)) {
|
|
128
|
-
const t = l.trim();
|
|
129
|
-
if (!t)
|
|
130
|
-
continue;
|
|
131
|
-
if (skip && t === skip)
|
|
132
|
-
continue;
|
|
133
|
-
return t;
|
|
134
|
-
}
|
|
135
|
-
return undefined;
|
|
136
|
-
}
|
|
137
|
-
function summarizeCodebaseRetrieval(text) {
|
|
138
|
-
const paths = extractAllPaths(text).slice(0, 3);
|
|
139
|
-
if (paths.length === 0) {
|
|
140
|
-
return { text: `retrieval — ${truncateLine(firstNonEmptyLine(text) ?? "", UNKNOWN_CAP)}` };
|
|
141
|
-
}
|
|
142
|
-
return { text: `retrieval: ${paths.join(", ")}` };
|
|
143
|
-
}
|
|
144
|
-
function summarizeUnknown(text) {
|
|
145
|
-
const line = firstNonEmptyLine(text) ?? "";
|
|
146
|
-
return { text: truncateLine(line, UNKNOWN_CAP) };
|
|
147
|
-
}
|
|
148
|
-
// ---- helpers ----
|
|
149
|
-
function nonEmptyLines(text) {
|
|
150
|
-
return text
|
|
151
|
-
.split(/\r?\n/)
|
|
152
|
-
.map((l) => l.trim())
|
|
153
|
-
.filter((l) => l.length > 0);
|
|
154
|
-
}
|
|
155
|
-
function firstNonEmptyLine(text) {
|
|
156
|
-
for (const l of text.split(/\r?\n/)) {
|
|
157
|
-
const t = l.trim();
|
|
158
|
-
if (t.length > 0)
|
|
159
|
-
return t;
|
|
160
|
-
}
|
|
161
|
-
return undefined;
|
|
162
|
-
}
|
|
163
|
-
function firstSignatureLine(text, skipPath) {
|
|
164
|
-
for (const l of text.split(/\r?\n/)) {
|
|
165
|
-
const t = l.trim();
|
|
166
|
-
if (!t)
|
|
167
|
-
continue;
|
|
168
|
-
if (skipPath && t === skipPath)
|
|
169
|
-
continue;
|
|
170
|
-
if (/^(#+\s|export\s|function\s|class\s|interface\s|type\s|const\s|def\s|public\s|private\s|fn\s)/.test(t)) {
|
|
171
|
-
return t;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return firstNonEmptyLineSkipping(text, skipPath);
|
|
175
|
-
}
|
|
176
|
-
function truncateLine(s, n) {
|
|
177
|
-
if (s.length <= n)
|
|
178
|
-
return s;
|
|
179
|
-
return `${s.slice(0, n - 1)}…`;
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Best-effort path extraction. Matches relative paths (`src/foo.ts`),
|
|
183
|
-
* dotted paths (`./foo.ts`), and Windows-style paths (`C:\foo.ts`). The
|
|
184
|
-
* leading char must be a word/dot — this avoids capturing a stray
|
|
185
|
-
* leading `/` (which would chop `src/` off `src/foo.ts`).
|
|
186
|
-
*
|
|
187
|
-
* The regex has the `g` flag because `extractAllPaths` uses `matchAll`.
|
|
188
|
-
* `extractFirstPath` resets `lastIndex` before calling `exec` so the
|
|
189
|
-
* shared regex object stays well-behaved across both call sites — the
|
|
190
|
-
* JS engine is single-threaded so there's no interleaving to worry about.
|
|
191
|
-
*/
|
|
192
|
-
const PATH_RE = /(?:[A-Za-z]:[\\/]|\.{1,2}[\\/])?[A-Za-z0-9_.-][\w./\\-]*\.[A-Za-z0-9]{1,8}/g;
|
|
193
|
-
function extractFirstPath(text) {
|
|
194
|
-
PATH_RE.lastIndex = 0;
|
|
195
|
-
const m = PATH_RE.exec(text);
|
|
196
|
-
return m?.[0];
|
|
197
|
-
}
|
|
198
|
-
function extractAllPaths(text) {
|
|
199
|
-
const out = [];
|
|
200
|
-
const seen = new Set();
|
|
201
|
-
// `matchAll` uses the source regex's `lastIndex` as the starting offset
|
|
202
|
-
// — if a prior `extractFirstPath` call left it non-zero, matchAll would
|
|
203
|
-
// skip the head of the string. Reset explicitly.
|
|
204
|
-
PATH_RE.lastIndex = 0;
|
|
205
|
-
for (const m of text.matchAll(PATH_RE)) {
|
|
206
|
-
const p = m[0];
|
|
207
|
-
if (!seen.has(p)) {
|
|
208
|
-
seen.add(p);
|
|
209
|
-
out.push(p);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return out;
|
|
213
|
-
}
|
|
214
|
-
function extractBashCommand(text) {
|
|
215
|
-
// Match common "$ cmd" or "command:" prefixes; otherwise first line.
|
|
216
|
-
const m = text.match(/(?:^|\n)\s*\$\s*([^\n]+)/);
|
|
217
|
-
return m?.[1]?.trim();
|
|
218
|
-
}
|
|
219
|
-
function extractExitCode(text) {
|
|
220
|
-
const m = text.match(/\bexit(?:\s+code)?[:= ]+(-?\d+)/i);
|
|
221
|
-
if (!m?.[1])
|
|
222
|
-
return undefined;
|
|
223
|
-
const n = Number(m[1]);
|
|
224
|
-
return Number.isFinite(n) ? n : undefined;
|
|
225
|
-
}
|
|
226
|
-
function extractChangeCount(text) {
|
|
227
|
-
const m = text.match(/(\d+)\s+(?:change|edit|insert|delet|line)/i);
|
|
228
|
-
if (!m?.[1])
|
|
229
|
-
return undefined;
|
|
230
|
-
const n = Number(m[1]);
|
|
231
|
-
return Number.isFinite(n) ? n : undefined;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Parse `PI_GHOST_CONTEXT_TOOL_MAX`. Returns fallback on bad input or
|
|
235
|
-
* negative values.
|
|
236
|
-
*/
|
|
237
|
-
export function parseToolMaxEnv(raw) {
|
|
238
|
-
if (raw === undefined)
|
|
239
|
-
return DEFAULT_TOOL_MAX;
|
|
240
|
-
const v = Number(raw);
|
|
241
|
-
if (!Number.isFinite(v) || v < 0)
|
|
242
|
-
return DEFAULT_TOOL_MAX;
|
|
243
|
-
return Math.floor(v);
|
|
244
|
-
}
|
|
245
|
-
//# sourceMappingURL=tool-summarize.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-summarize.js","sourceRoot":"","sources":["../src/tool-summarize.ts"],"names":[],"mappings":"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"}
|
package/dist/trie-sanitize.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shannon entropy in bits per character. A uniformly-random 20-char hex
|
|
3
|
-
* string scores ~4.0; a 20-char base64 string scores ~5.0; a typical English
|
|
4
|
-
* word scores ~3.0–3.5.
|
|
5
|
-
*/
|
|
6
|
-
export declare function shannonEntropy(s: string): number;
|
|
7
|
-
export declare function looksLikeKey(token: string): boolean;
|
|
8
|
-
export declare function isHighEntropy(token: string): boolean;
|
|
9
|
-
/**
|
|
10
|
-
* Return true if any individual token in `text` matches a sensitive pattern.
|
|
11
|
-
* Used by the trie to drop entire messages defensively rather than splice in
|
|
12
|
-
* `<redacted>` markers that would produce nonsensical ghost text.
|
|
13
|
-
*/
|
|
14
|
-
export declare function containsSensitive(text: string): boolean;
|
|
15
|
-
/**
|
|
16
|
-
* Return `text` with sensitive substrings replaced by a single space. Useful
|
|
17
|
-
* when the caller would rather keep most of a message than drop it entirely.
|
|
18
|
-
* For the session trie we prefer dropping the whole message (see
|
|
19
|
-
* `containsSensitive`); kept here for future M4 profile partial-keep flows.
|
|
20
|
-
*/
|
|
21
|
-
export declare function redactSensitive(text: string): string;
|
|
22
|
-
//# sourceMappingURL=trie-sanitize.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trie-sanitize.d.ts","sourceRoot":"","sources":["../src/trie-sanitize.ts"],"names":[],"mappings":"AAyEA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAUhD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAMnD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYvD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWpD"}
|
package/dist/trie-sanitize.js
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Privacy sanitization for session-trie + (future) profile data. See PRD §M2
|
|
3
|
-
* "Privacy" and §M4 "Sanitization".
|
|
4
|
-
*
|
|
5
|
-
* Sensitive tokens are removed before any text reaches a persistent or
|
|
6
|
-
* shared-across-sessions structure. The sanitizer is **best-effort**, not a
|
|
7
|
-
* guarantee:
|
|
8
|
-
* - false negatives: any secret shorter than 20 chars, in a format we
|
|
9
|
-
* don't recognize, or below the entropy threshold can pass through;
|
|
10
|
-
* - false positives: high-entropy code identifiers (e.g. hashes embedded
|
|
11
|
-
* in source) can be flagged and dropped, degrading completion quality.
|
|
12
|
-
*
|
|
13
|
-
* When in doubt, the sanitizer drops the token. False negatives can leak
|
|
14
|
-
* secrets — false positives only reduce ghost quality. New key-prefix
|
|
15
|
-
* patterns should be added here as providers emerge; SEC-21 tracks the
|
|
16
|
-
* widening cadence in the status doc.
|
|
17
|
-
*
|
|
18
|
-
* The current rules:
|
|
19
|
-
* - high Shannon entropy: > HIGH_ENTROPY_THRESHOLD bits/char over a ≥20-char
|
|
20
|
-
* run. PRD specified 4.5 bits/char. Per-character Shannon entropy depends on
|
|
21
|
-
* the symbol alphabet (e.g., base64 has log₂(64)=6.0 bits/char, hex has
|
|
22
|
-
* log₂(16)=4.0 bits/char); log₂(20)≈4.32 is unrelated (bits to index 20 values).
|
|
23
|
-
* We use 4.0 as a pragmatic heuristic. The key-prefix list is the primary
|
|
24
|
-
* defense — entropy is the backup.
|
|
25
|
-
* - base64/JWT-shaped strings ≥20 chars (with optional `=` padding). The
|
|
26
|
-
* char class excludes `/` to avoid flagging file paths.
|
|
27
|
-
* - known key prefixes: OpenAI/Anthropic (`sk-…`, `sk-ant-…`),
|
|
28
|
-
* GitHub (`ghp_/gho_/ghu_/ghs_/ghr_`), Slack (`xoxb-/xoxa-/xoxp-/xoxr-/xoxs-`),
|
|
29
|
-
* AWS access keys (`AKIA[16-base32]`), AWS session tokens (`ASIA[16-base32]`),
|
|
30
|
-
* Google API keys (`AIza[35]`), Stripe (`sk_live_…`, `sk_test_…`,
|
|
31
|
-
* `rk_live_…`), Twilio (`SK[32]`, `AC[32]`), SendGrid (`SG.[…].[…]`),
|
|
32
|
-
* * Mailgun (`key-[…]`), JWT 3-part shape (`eyJ…\.…\.…`). Stripe also
|
|
33
|
-
* matches `rk_test_…`; the regex is `(?:sk|rk)_(?:live|test)_…`.
|
|
34
|
-
*/
|
|
35
|
-
const HIGH_ENTROPY_THRESHOLD = 4.0;
|
|
36
|
-
const MIN_ENTROPY_LEN = 20;
|
|
37
|
-
const KEY_PREFIX_PATTERNS = [
|
|
38
|
-
// OpenAI / Anthropic / generic "sk-" tokens.
|
|
39
|
-
/\bsk-[A-Za-z0-9_-]{20,}\b/g,
|
|
40
|
-
// Anthropic explicit prefix (covered above but keep for self-doc).
|
|
41
|
-
/\bsk-ant-[A-Za-z0-9_-]{20,}\b/g,
|
|
42
|
-
// GitHub personal access / OAuth tokens.
|
|
43
|
-
/\bghp_[A-Za-z0-9]{20,}\b/g,
|
|
44
|
-
/\bgho_[A-Za-z0-9]{20,}\b/g,
|
|
45
|
-
/\bghu_[A-Za-z0-9]{20,}\b/g,
|
|
46
|
-
/\bghs_[A-Za-z0-9]{20,}\b/g,
|
|
47
|
-
/\bghr_[A-Za-z0-9]{20,}\b/g,
|
|
48
|
-
// Slack bot / user / refresh / signing / verification tokens.1.1
|
|
49
|
-
/\bxox[baprs]-[A-Za-z0-9-]{20,}\b/g,
|
|
50
|
-
// AWS access key + session token prefixes.
|
|
51
|
-
/\bAKIA[0-9A-Z]{16}\b/g,
|
|
52
|
-
/\bASIA[0-9A-Z]{16}\b/g,
|
|
53
|
-
// Google API key (always 39 chars, starts AIza).
|
|
54
|
-
/\bAIza[A-Za-z0-9_-]{35}\b/g,
|
|
55
|
-
// Stripe live/test secret + restricted keys.
|
|
56
|
-
/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{20,}\b/g,
|
|
57
|
-
// Twilio account / API SIDs (34 chars including prefix). Twilio SIDs
|
|
58
|
-
// are alphanumeric, not strictly hex.
|
|
59
|
-
/\b(?:AC|SK)[0-9A-Za-z]{32}\b/g,
|
|
60
|
-
// SendGrid (3-part).
|
|
61
|
-
/\bSG\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/g,
|
|
62
|
-
// Mailgun.
|
|
63
|
-
/\bkey-[A-Za-z0-9]{20,}\b/g,
|
|
64
|
-
// JWT: three base64url segments joined by dots, header always starts `eyJ`.
|
|
65
|
-
/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g,
|
|
66
|
-
];
|
|
67
|
-
// Matches both standard base64 and base64url strings ≥20 chars.
|
|
68
|
-
// Includes standard base64 chars (A-Za-z0-9+) and base64url chars (A-Za-z0-9_-).
|
|
69
|
-
// Explicitly excludes `/` to avoid false positives on file paths.
|
|
70
|
-
const BASE64_LIKE = /\b[A-Za-z0-9+_-]{20,}={0,2}\b/g;
|
|
71
|
-
/**
|
|
72
|
-
* Shannon entropy in bits per character. A uniformly-random 20-char hex
|
|
73
|
-
* string scores ~4.0; a 20-char base64 string scores ~5.0; a typical English
|
|
74
|
-
* word scores ~3.0–3.5.
|
|
75
|
-
*/
|
|
76
|
-
export function shannonEntropy(s) {
|
|
77
|
-
if (s.length === 0)
|
|
78
|
-
return 0;
|
|
79
|
-
const counts = new Map();
|
|
80
|
-
for (const ch of s)
|
|
81
|
-
counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
82
|
-
let h = 0;
|
|
83
|
-
for (const c of counts.values()) {
|
|
84
|
-
const p = c / s.length;
|
|
85
|
-
h -= p * Math.log2(p);
|
|
86
|
-
}
|
|
87
|
-
return h;
|
|
88
|
-
}
|
|
89
|
-
export function looksLikeKey(token) {
|
|
90
|
-
for (const re of KEY_PREFIX_PATTERNS) {
|
|
91
|
-
re.lastIndex = 0;
|
|
92
|
-
if (re.test(token))
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
export function isHighEntropy(token) {
|
|
98
|
-
if (token.length < MIN_ENTROPY_LEN)
|
|
99
|
-
return false;
|
|
100
|
-
return shannonEntropy(token) > HIGH_ENTROPY_THRESHOLD;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Return true if any individual token in `text` matches a sensitive pattern.
|
|
104
|
-
* Used by the trie to drop entire messages defensively rather than splice in
|
|
105
|
-
* `<redacted>` markers that would produce nonsensical ghost text.
|
|
106
|
-
*/
|
|
107
|
-
export function containsSensitive(text) {
|
|
108
|
-
for (const re of KEY_PREFIX_PATTERNS) {
|
|
109
|
-
re.lastIndex = 0;
|
|
110
|
-
if (re.test(text))
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
BASE64_LIKE.lastIndex = 0;
|
|
114
|
-
if (BASE64_LIKE.test(text))
|
|
115
|
-
return true;
|
|
116
|
-
for (const token of text.split(/\s+/)) {
|
|
117
|
-
if (token.length === 0)
|
|
118
|
-
continue;
|
|
119
|
-
if (isHighEntropy(token))
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Return `text` with sensitive substrings replaced by a single space. Useful
|
|
126
|
-
* when the caller would rather keep most of a message than drop it entirely.
|
|
127
|
-
* For the session trie we prefer dropping the whole message (see
|
|
128
|
-
* `containsSensitive`); kept here for future M4 profile partial-keep flows.
|
|
129
|
-
*/
|
|
130
|
-
export function redactSensitive(text) {
|
|
131
|
-
let out = text;
|
|
132
|
-
for (const re of KEY_PREFIX_PATTERNS) {
|
|
133
|
-
out = out.replace(re, " ");
|
|
134
|
-
}
|
|
135
|
-
out = out.replace(BASE64_LIKE, " ");
|
|
136
|
-
out = out
|
|
137
|
-
.split(/(\s+)/)
|
|
138
|
-
.map((piece) => (/^\s+$/.test(piece) ? piece : isHighEntropy(piece) ? " " : piece))
|
|
139
|
-
.join("");
|
|
140
|
-
return out.replace(/\s+/g, " ").trim();
|
|
141
|
-
}
|
|
142
|
-
//# sourceMappingURL=trie-sanitize.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trie-sanitize.js","sourceRoot":"","sources":["../src/trie-sanitize.ts"],"names":[],"mappings":"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"}
|
package/dist/versions.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Behavior-affecting version fingerprints.
|
|
3
|
-
*
|
|
4
|
-
* These constants feed cache keys, metrics records, and replay reports so a
|
|
5
|
-
* stale cache entry can never be served after the underlying behavior
|
|
6
|
-
* (prompt template, sanitization rules, context aggregation, reranking,
|
|
7
|
-
* profile-hint emission) changes.
|
|
8
|
-
*
|
|
9
|
-
* Bump the relevant version whenever a change would make an old cache hit
|
|
10
|
-
* or an old metrics comparison misleading. The numeric values are opaque
|
|
11
|
-
* and never user-visible.
|
|
12
|
-
*/
|
|
13
|
-
export declare const PROMPT_TEMPLATE_VERSION = 1;
|
|
14
|
-
export declare const SANITIZER_VERSION = 1;
|
|
15
|
-
export declare const CONTEXT_AGGREGATOR_VERSION = 1;
|
|
16
|
-
export declare const RERANKER_VERSION = 1;
|
|
17
|
-
export declare const PROFILE_HINT_VERSION = 1;
|
|
18
|
-
/**
|
|
19
|
-
* Combined version string used in cache keys and `lastGhosts` entries.
|
|
20
|
-
* Order is fixed so the string is stable across runs.
|
|
21
|
-
*/
|
|
22
|
-
export declare function combinedVersionFingerprint(): string;
|
|
23
|
-
//# sourceMappingURL=versions.d.ts.map
|
package/dist/versions.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAQnD"}
|
package/dist/versions.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Behavior-affecting version fingerprints.
|
|
3
|
-
*
|
|
4
|
-
* These constants feed cache keys, metrics records, and replay reports so a
|
|
5
|
-
* stale cache entry can never be served after the underlying behavior
|
|
6
|
-
* (prompt template, sanitization rules, context aggregation, reranking,
|
|
7
|
-
* profile-hint emission) changes.
|
|
8
|
-
*
|
|
9
|
-
* Bump the relevant version whenever a change would make an old cache hit
|
|
10
|
-
* or an old metrics comparison misleading. The numeric values are opaque
|
|
11
|
-
* and never user-visible.
|
|
12
|
-
*/
|
|
13
|
-
export const PROMPT_TEMPLATE_VERSION = 1;
|
|
14
|
-
export const SANITIZER_VERSION = 1;
|
|
15
|
-
export const CONTEXT_AGGREGATOR_VERSION = 1;
|
|
16
|
-
export const RERANKER_VERSION = 1;
|
|
17
|
-
export const PROFILE_HINT_VERSION = 1;
|
|
18
|
-
/**
|
|
19
|
-
* Combined version string used in cache keys and `lastGhosts` entries.
|
|
20
|
-
* Order is fixed so the string is stable across runs.
|
|
21
|
-
*/
|
|
22
|
-
export function combinedVersionFingerprint() {
|
|
23
|
-
return [
|
|
24
|
-
PROMPT_TEMPLATE_VERSION,
|
|
25
|
-
SANITIZER_VERSION,
|
|
26
|
-
CONTEXT_AGGREGATOR_VERSION,
|
|
27
|
-
RERANKER_VERSION,
|
|
28
|
-
PROFILE_HINT_VERSION,
|
|
29
|
-
].join(".");
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=versions.js.map
|
package/dist/versions.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"versions.js","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC;;;GAGG;AACH,MAAM,UAAU,0BAA0B;IACzC,OAAO;QACN,uBAAuB;QACvB,iBAAiB;QACjB,0BAA0B;QAC1B,gBAAgB;QAChB,oBAAoB;KACpB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,CAAC"}
|