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.
- package/README.md +101 -6
- package/dist/bench-cli.js +81 -5
- package/dist/bench-cli.js.map +1 -1
- package/dist/bench.d.ts +130 -2
- package/dist/bench.d.ts.map +1 -1
- package/dist/bench.js +285 -4
- package/dist/bench.js.map +1 -1
- package/dist/cache.d.ts +124 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +173 -0
- package/dist/cache.js.map +1 -0
- package/dist/candidate-rerank.d.ts +57 -0
- package/dist/candidate-rerank.d.ts.map +1 -0
- package/dist/candidate-rerank.js +78 -0
- package/dist/candidate-rerank.js.map +1 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +148 -18
- package/dist/config.js.map +1 -1
- package/dist/context-aggregator.d.ts +14 -5
- package/dist/context-aggregator.d.ts.map +1 -1
- package/dist/context-aggregator.js +38 -9
- package/dist/context-aggregator.js.map +1 -1
- package/dist/context-selector.d.ts +128 -0
- package/dist/context-selector.d.ts.map +1 -0
- package/dist/context-selector.js +300 -0
- package/dist/context-selector.js.map +1 -0
- package/dist/cycle-manager.d.ts +102 -0
- package/dist/cycle-manager.d.ts.map +1 -0
- package/dist/cycle-manager.js +168 -0
- package/dist/cycle-manager.js.map +1 -0
- package/dist/edit-history-ring.d.ts +148 -0
- package/dist/edit-history-ring.d.ts.map +1 -0
- package/dist/edit-history-ring.js +262 -0
- package/dist/edit-history-ring.js.map +1 -0
- package/dist/entropy-stop.d.ts +102 -0
- package/dist/entropy-stop.d.ts.map +1 -0
- package/dist/entropy-stop.js +141 -0
- package/dist/entropy-stop.js.map +1 -0
- package/dist/eval-dataset.d.ts +66 -0
- package/dist/eval-dataset.d.ts.map +1 -0
- package/dist/eval-dataset.js +127 -0
- package/dist/eval-dataset.js.map +1 -0
- package/dist/fast-path-engine.d.ts +286 -0
- package/dist/fast-path-engine.d.ts.map +1 -0
- package/dist/fast-path-engine.js +341 -0
- package/dist/fast-path-engine.js.map +1 -0
- package/dist/fuzzy-matcher.d.ts +8 -0
- package/dist/fuzzy-matcher.d.ts.map +1 -1
- package/dist/fuzzy-matcher.js +5 -3
- package/dist/fuzzy-matcher.js.map +1 -1
- package/dist/ghost-editor.d.ts +321 -4
- package/dist/ghost-editor.d.ts.map +1 -1
- package/dist/ghost-editor.js +1190 -144
- package/dist/ghost-editor.js.map +1 -1
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +81 -2
- package/dist/index.js.map +1 -1
- package/dist/keystroke-timer.d.ts +59 -0
- package/dist/keystroke-timer.d.ts.map +1 -0
- package/dist/keystroke-timer.js +94 -0
- package/dist/keystroke-timer.js.map +1 -0
- package/dist/metrics-builder.d.ts +71 -0
- package/dist/metrics-builder.d.ts.map +1 -0
- package/dist/metrics-builder.js +71 -0
- package/dist/metrics-builder.js.map +1 -0
- package/dist/metrics.d.ts +99 -2
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +131 -17
- package/dist/metrics.js.map +1 -1
- package/dist/path-matcher.d.ts +9 -0
- package/dist/path-matcher.d.ts.map +1 -1
- package/dist/path-matcher.js +5 -2
- package/dist/path-matcher.js.map +1 -1
- package/dist/profile-store.d.ts +82 -0
- package/dist/profile-store.d.ts.map +1 -0
- package/dist/profile-store.js +199 -0
- package/dist/profile-store.js.map +1 -0
- package/dist/profile.d.ts +185 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +434 -0
- package/dist/profile.js.map +1 -0
- package/dist/providers/cloud-provider.d.ts +10 -1
- package/dist/providers/cloud-provider.d.ts.map +1 -1
- package/dist/providers/cloud-provider.js +71 -14
- package/dist/providers/cloud-provider.js.map +1 -1
- package/dist/providers/local-provider.d.ts +8 -1
- package/dist/providers/local-provider.d.ts.map +1 -1
- package/dist/providers/local-provider.js +15 -3
- package/dist/providers/local-provider.js.map +1 -1
- package/dist/providers/openai-compat-provider.d.ts +11 -1
- package/dist/providers/openai-compat-provider.d.ts.map +1 -1
- package/dist/providers/openai-compat-provider.js +93 -6
- package/dist/providers/openai-compat-provider.js.map +1 -1
- package/dist/providers/openai-completions-runner.d.ts +25 -1
- package/dist/providers/openai-completions-runner.d.ts.map +1 -1
- package/dist/providers/openai-completions-runner.js +109 -14
- package/dist/providers/openai-completions-runner.js.map +1 -1
- package/dist/providers/race.d.ts +58 -1
- package/dist/providers/race.d.ts.map +1 -1
- package/dist/providers/race.js +317 -4
- package/dist/providers/race.js.map +1 -1
- package/dist/providers/truncate.d.ts.map +1 -1
- package/dist/providers/truncate.js +20 -2
- package/dist/providers/truncate.js.map +1 -1
- package/dist/providers/types.d.ts +96 -1
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js +59 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/provisional-manager.d.ts +93 -0
- package/dist/provisional-manager.d.ts.map +1 -0
- package/dist/provisional-manager.js +98 -0
- package/dist/provisional-manager.js.map +1 -0
- package/dist/provisional.d.ts +150 -0
- package/dist/provisional.d.ts.map +1 -0
- package/dist/provisional.js +238 -0
- package/dist/provisional.js.map +1 -0
- package/dist/regret-tracker.d.ts +84 -0
- package/dist/regret-tracker.d.ts.map +1 -0
- package/dist/regret-tracker.js +145 -0
- package/dist/regret-tracker.js.map +1 -0
- package/dist/replay-cli.d.ts +13 -0
- package/dist/replay-cli.d.ts.map +1 -0
- package/dist/replay-cli.js +167 -0
- package/dist/replay-cli.js.map +1 -0
- package/dist/replay.d.ts +107 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +225 -0
- package/dist/replay.js.map +1 -0
- package/dist/reranker.d.ts +181 -0
- package/dist/reranker.d.ts.map +1 -0
- package/dist/reranker.js +324 -0
- package/dist/reranker.js.map +1 -0
- package/dist/session-trie.d.ts +103 -0
- package/dist/session-trie.d.ts.map +1 -0
- package/dist/session-trie.js +280 -0
- package/dist/session-trie.js.map +1 -0
- package/dist/speculative.d.ts +74 -0
- package/dist/speculative.d.ts.map +1 -0
- package/dist/speculative.js +107 -0
- package/dist/speculative.js.map +1 -0
- package/dist/tool-summarize.d.ts +40 -0
- package/dist/tool-summarize.d.ts.map +1 -0
- package/dist/tool-summarize.js +245 -0
- package/dist/tool-summarize.js.map +1 -0
- package/dist/trie-sanitize.d.ts +22 -0
- package/dist/trie-sanitize.d.ts.map +1 -0
- package/dist/trie-sanitize.js +142 -0
- package/dist/trie-sanitize.js.map +1 -0
- package/dist/versions.d.ts +23 -0
- package/dist/versions.d.ts.map +1 -0
- package/dist/versions.js +31 -0
- package/dist/versions.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stateful wrapper around `profile.ts` for the editor. Holds the in-memory
|
|
3
|
+
* `ProfileIndex`, serializes writes, triggers periodic compaction, and
|
|
4
|
+
* exposes a synchronous lookup surface for the editor's hot path.
|
|
5
|
+
*
|
|
6
|
+
* Lifecycle:
|
|
7
|
+
* 1. `create(cwd)` — loads + indexes the JSONL once. Returns a disabled
|
|
8
|
+
* store if `PI_GHOST_PROFILE=off`. Errors during load yield an empty
|
|
9
|
+
* index (best-effort).
|
|
10
|
+
* 2. `captureCommit(text)` / `captureAccept(prefix, completion, weight)`
|
|
11
|
+
* — append to disk (async, fire-and-forget) and merge into the
|
|
12
|
+
* in-memory index so the next lookup sees them immediately.
|
|
13
|
+
* 3. Every `COMPACT_CHECK_EVERY` writes the store runs `compactIfNeeded`
|
|
14
|
+
* in the background. Compaction reloads the index after rewrite.
|
|
15
|
+
*
|
|
16
|
+
* `disabled` is a public boolean so callers can short-circuit lookups
|
|
17
|
+
* without an extra function call on the keystroke path.
|
|
18
|
+
*/
|
|
19
|
+
import { appendRecords, bestSlashMatch, buildIndex, compactIfNeeded, DEFAULT_DECAY_DAYS, emptyIndex, loadRecords, parseDecayDaysEnv, prefixHash, profileBias, profilePathBoost, recordsFromCommit, recordFromAccept, } from "./profile.js";
|
|
20
|
+
// `loadRecords` referenced only inside the `create` static; `buildIndex`
|
|
21
|
+
// likewise. Both retained in imports. Keep this import block fixed so
|
|
22
|
+
// future additions don't bring in unused symbols silently.
|
|
23
|
+
const COMPACT_CHECK_EVERY = 100;
|
|
24
|
+
export class ProfileStore {
|
|
25
|
+
cwd;
|
|
26
|
+
disabled;
|
|
27
|
+
index = emptyIndex();
|
|
28
|
+
writeQueue = Promise.resolve();
|
|
29
|
+
writesSinceCompact = 0;
|
|
30
|
+
decayDays;
|
|
31
|
+
constructor(cwd, opts) {
|
|
32
|
+
this.cwd = cwd;
|
|
33
|
+
this.disabled = opts.disabled;
|
|
34
|
+
this.decayDays = opts.decayDays;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a store and load the JSONL into memory. Caller awaits before
|
|
38
|
+
* exposing the store to the editor so the index is hot on first
|
|
39
|
+
* keystroke. Disabled stores short-circuit load entirely.
|
|
40
|
+
*/
|
|
41
|
+
static async create(cwd, env = process.env) {
|
|
42
|
+
const disabled = env.PI_GHOST_PROFILE === "off";
|
|
43
|
+
const decayDays = parseDecayDaysEnv(env.PI_GHOST_PROFILE_DECAY_DAYS);
|
|
44
|
+
const store = new ProfileStore(cwd, { disabled, decayDays });
|
|
45
|
+
if (!disabled) {
|
|
46
|
+
try {
|
|
47
|
+
const records = await loadRecords(cwd);
|
|
48
|
+
store.index = buildIndex(records, { decayDays });
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// best-effort
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return store;
|
|
55
|
+
}
|
|
56
|
+
getIndex() {
|
|
57
|
+
return this.index;
|
|
58
|
+
}
|
|
59
|
+
get decayDaysSetting() {
|
|
60
|
+
return this.decayDays;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Capture user-committed text. Extracts paths + slash + trigrams, drops
|
|
64
|
+
* sensitive messages entirely. Returns the count of records emitted —
|
|
65
|
+
* useful for tests/diagnostics.
|
|
66
|
+
*/
|
|
67
|
+
captureCommit(text, ts = Date.now()) {
|
|
68
|
+
if (this.disabled)
|
|
69
|
+
return 0;
|
|
70
|
+
const recs = recordsFromCommit(text, ts);
|
|
71
|
+
if (recs.length === 0)
|
|
72
|
+
return 0;
|
|
73
|
+
this.mergeAndPersist(recs);
|
|
74
|
+
return recs.length;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Capture an accept (full or partial). `weight` defaults to 3 to match
|
|
78
|
+
* PRD §M2 trie weights. Returns true when a record was emitted.
|
|
79
|
+
*/
|
|
80
|
+
captureAccept(prefix, completion, weight = 3, ts = Date.now()) {
|
|
81
|
+
if (this.disabled)
|
|
82
|
+
return false;
|
|
83
|
+
const rec = recordFromAccept(prefix, completion, weight, ts);
|
|
84
|
+
if (!rec)
|
|
85
|
+
return false;
|
|
86
|
+
this.mergeAndPersist([rec]);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
/** Public lookup surfaces — thin wrappers around `profile.ts`. */
|
|
90
|
+
bestSlashMatch(prefix) {
|
|
91
|
+
if (this.disabled)
|
|
92
|
+
return null;
|
|
93
|
+
return bestSlashMatch(this.index, prefix);
|
|
94
|
+
}
|
|
95
|
+
profileBias(text) {
|
|
96
|
+
if (this.disabled)
|
|
97
|
+
return 0;
|
|
98
|
+
return profileBias(this.index, text);
|
|
99
|
+
}
|
|
100
|
+
profilePathBoost(path) {
|
|
101
|
+
if (this.disabled)
|
|
102
|
+
return 0;
|
|
103
|
+
return profilePathBoost(this.index, path);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Provisional fallback (PRD §M3.5b) — look up an exact-prefix accept
|
|
107
|
+
* record. Returns the completion tokens + summed weight, or null when
|
|
108
|
+
* the prefix has never been the exact key of a captured accept.
|
|
109
|
+
* `prefix` is hashed in-process; the raw string never leaves memory.
|
|
110
|
+
*/
|
|
111
|
+
lookupAcceptByPrefix(prefix) {
|
|
112
|
+
if (this.disabled || !prefix)
|
|
113
|
+
return null;
|
|
114
|
+
const hit = this.index.acceptByPrefix.get(prefixHash(prefix));
|
|
115
|
+
return hit ? { completionTokens: hit.completionTokens, weight: hit.weight } : null;
|
|
116
|
+
}
|
|
117
|
+
/** Flush any pending writes — call before process exit. */
|
|
118
|
+
async flush() {
|
|
119
|
+
await this.writeQueue;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Append records both in-memory and to disk. In-memory merge happens
|
|
123
|
+
* synchronously so the very next lookup sees the new weight; the disk
|
|
124
|
+
* write is queued through `writeQueue` to serialize concurrent commits.
|
|
125
|
+
*/
|
|
126
|
+
mergeAndPersist(recs) {
|
|
127
|
+
// Merge into in-memory index. Rebuilding from scratch is wasteful
|
|
128
|
+
// for one record; instead apply the same buildIndex rules inline.
|
|
129
|
+
this.applyToIndex(recs);
|
|
130
|
+
this.writesSinceCompact += recs.length;
|
|
131
|
+
const shouldCompact = this.writesSinceCompact >= COMPACT_CHECK_EVERY;
|
|
132
|
+
if (shouldCompact)
|
|
133
|
+
this.writesSinceCompact = 0;
|
|
134
|
+
this.writeQueue = this.writeQueue
|
|
135
|
+
.then(() => appendRecords(this.cwd, recs))
|
|
136
|
+
.then(async () => {
|
|
137
|
+
if (!shouldCompact)
|
|
138
|
+
return;
|
|
139
|
+
// Background compaction rewrites the file. The in-memory
|
|
140
|
+
// index is NOT reloaded afterward: between the loadRecords
|
|
141
|
+
// step inside `compactIfNeeded` and our reload, additional
|
|
142
|
+
// `applyToIndex` calls would have mutated `this.index` —
|
|
143
|
+
// reloading would lose them. The in-memory index is the
|
|
144
|
+
// authoritative session view; compaction's purpose is
|
|
145
|
+
// disk-size reduction. Next session start re-reads the
|
|
146
|
+
// compacted file via `ProfileStore.create`.
|
|
147
|
+
await compactIfNeeded(this.cwd, { decayDays: this.decayDays });
|
|
148
|
+
})
|
|
149
|
+
.catch(() => {
|
|
150
|
+
/* logging must never break completions */
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Inline equivalent of `buildIndex` for a small record batch. The
|
|
155
|
+
* fresh-record path skips decay since we just wrote `ts`. Keeping this
|
|
156
|
+
* separate from `profile.buildIndex` avoids reindexing the whole store
|
|
157
|
+
* on every keystroke.
|
|
158
|
+
*/
|
|
159
|
+
applyToIndex(recs) {
|
|
160
|
+
for (const r of recs) {
|
|
161
|
+
const w = r.weight;
|
|
162
|
+
switch (r.kind) {
|
|
163
|
+
case "ngram":
|
|
164
|
+
if (r.tokens && r.tokens.length > 0) {
|
|
165
|
+
const key = r.tokens.join(" ");
|
|
166
|
+
this.index.ngram.set(key, (this.index.ngram.get(key) ?? 0) + w);
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
case "path":
|
|
170
|
+
if (r.value)
|
|
171
|
+
this.index.path.set(r.value, (this.index.path.get(r.value) ?? 0) + w);
|
|
172
|
+
break;
|
|
173
|
+
case "slash":
|
|
174
|
+
if (r.value)
|
|
175
|
+
this.index.slash.set(r.value, (this.index.slash.get(r.value) ?? 0) + w);
|
|
176
|
+
break;
|
|
177
|
+
case "accept":
|
|
178
|
+
if (r.prefixHash && r.completionTokens) {
|
|
179
|
+
const existing = this.index.acceptByPrefix.get(r.prefixHash);
|
|
180
|
+
if (existing) {
|
|
181
|
+
existing.weight += w;
|
|
182
|
+
existing.completionTokens = r.completionTokens;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
this.index.acceptByPrefix.set(r.prefixHash, {
|
|
186
|
+
completionTokens: r.completionTokens,
|
|
187
|
+
weight: w,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
this.index.totalAcceptRecords += 1;
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Exported for tests — surface compactor knob without re-exporting `profile.ts`. */
|
|
198
|
+
export { DEFAULT_DECAY_DAYS };
|
|
199
|
+
//# sourceMappingURL=profile-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-store.js","sourceRoot":"","sources":["../src/profile-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User profile — long-lived, cross-session frequency store. PRD §M4.
|
|
3
|
+
*
|
|
4
|
+
* Storage: `.pi/ghost-autocomplete/profile.jsonl` (append-only). One JSON
|
|
5
|
+
* record per line, written via the in-process writer.
|
|
6
|
+
*
|
|
7
|
+
* The profile feeds three local-only signals:
|
|
8
|
+
* - ngram trigrams → reranker `profileBias` (PRD §M3c hook)
|
|
9
|
+
* - path frequency → bounded boost to deterministic path/fuzzy ranking
|
|
10
|
+
* - slash-command frequency → editor fast-path for `/cmd…` prefixes
|
|
11
|
+
*
|
|
12
|
+
* Privacy: raw full prefixes and full completions are NEVER persisted. We
|
|
13
|
+
* store sanitized n-grams (≤4), absolute paths, slash commands, and SHA-256
|
|
14
|
+
* hashes of prefix keys (`prefixHash`) for exact-prefix lookup without
|
|
15
|
+
* writing prompt text. The sanitizer is shared with `trie-sanitize.ts` so
|
|
16
|
+
* the entropy + key-prefix rules drop the same tokens.
|
|
17
|
+
*
|
|
18
|
+
* The on-disk format is intentionally append-only + line-delimited so a
|
|
19
|
+
* crash mid-write never corrupts the existing index; partial trailing lines
|
|
20
|
+
* are skipped on load. Rotation compacts when the file exceeds 2 MB.
|
|
21
|
+
*/
|
|
22
|
+
export declare const PROFILE_REL = ".pi/ghost-autocomplete/profile.jsonl";
|
|
23
|
+
export declare const DEFAULT_MAX_BYTES: number;
|
|
24
|
+
export declare const DEFAULT_DECAY_DAYS = 90;
|
|
25
|
+
export declare const DROP_BELOW_WEIGHT = 0.1;
|
|
26
|
+
export declare const MAX_NGRAM_N = 4;
|
|
27
|
+
export declare const TRIGRAM_N = 3;
|
|
28
|
+
export type ProfileKind = "ngram" | "path" | "slash" | "accept";
|
|
29
|
+
/**
|
|
30
|
+
* One on-disk record. `weight` accumulates across captures and decays over
|
|
31
|
+
* time. `accept` records carry both `prefixHash` (for exact-prefix learning)
|
|
32
|
+
* and `prefixTailTokens` + `completionTokens` (already tokenized).
|
|
33
|
+
*/
|
|
34
|
+
export interface ProfileRecord {
|
|
35
|
+
ts: number;
|
|
36
|
+
kind: ProfileKind;
|
|
37
|
+
weight: number;
|
|
38
|
+
/** `kind=ngram`: ordered token tuple. */
|
|
39
|
+
tokens?: string[];
|
|
40
|
+
/** Trigram length when `kind=ngram`. */
|
|
41
|
+
n?: number;
|
|
42
|
+
/** `kind=path` / `kind=slash`: literal value. */
|
|
43
|
+
value?: string;
|
|
44
|
+
/** `kind=accept`: SHA-256 hex digest of the prefix at accept time. */
|
|
45
|
+
prefixHash?: string;
|
|
46
|
+
/** `kind=accept`: trailing tokens of the prefix (cap 4). */
|
|
47
|
+
prefixTailTokens?: string[];
|
|
48
|
+
/** `kind=accept`: tokens of the completion (cap 8). */
|
|
49
|
+
completionTokens?: string[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* In-memory aggregated view of the profile. The maps are weight-sums per
|
|
53
|
+
* key. `acceptByPrefix` is keyed by `prefixHash` so exact-prefix history is
|
|
54
|
+
* available without storing the raw prefix.
|
|
55
|
+
*/
|
|
56
|
+
export interface ProfileIndex {
|
|
57
|
+
ngram: Map<string, number>;
|
|
58
|
+
path: Map<string, number>;
|
|
59
|
+
slash: Map<string, number>;
|
|
60
|
+
acceptByPrefix: Map<string, {
|
|
61
|
+
completionTokens: string[];
|
|
62
|
+
weight: number;
|
|
63
|
+
}>;
|
|
64
|
+
totalAcceptRecords: number;
|
|
65
|
+
}
|
|
66
|
+
export declare function emptyIndex(): ProfileIndex;
|
|
67
|
+
/**
|
|
68
|
+
* Tokenize a string into the same word-token form the profile stores. Drops
|
|
69
|
+
* the empty string, deduplicates whitespace, and lowercases nothing — code
|
|
70
|
+
* identifiers are case-sensitive.
|
|
71
|
+
*/
|
|
72
|
+
export declare function tokenize(text: string): string[];
|
|
73
|
+
/**
|
|
74
|
+
* Generate n-grams of size `n` from `tokens`. Returns empty when there are
|
|
75
|
+
* fewer than `n` tokens.
|
|
76
|
+
*/
|
|
77
|
+
export declare function ngrams(tokens: string[], n: number): string[][];
|
|
78
|
+
/**
|
|
79
|
+
* SHA-256 hex of a prefix string. The hash is the disk-storable surrogate
|
|
80
|
+
* for the prefix — same prefix always maps to the same key, but the raw
|
|
81
|
+
* prefix never leaves the process.
|
|
82
|
+
*/
|
|
83
|
+
export declare function prefixHash(prefix: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* Extract candidate paths from free text. Same shape used by `recent-paths.ts`
|
|
86
|
+
* but kept independent so changes to recent-paths semantics don't drift
|
|
87
|
+
* the profile schema. Matches `foo/bar.ts`, `src/a/b.tsx`, etc.
|
|
88
|
+
*/
|
|
89
|
+
export declare function extractPaths(text: string): string[];
|
|
90
|
+
/**
|
|
91
|
+
* Extract `/slash-command` tokens from free text. Limited to a-z prefix
|
|
92
|
+
* plus alphanumerics/hyphen/underscore to avoid false matches on URLs
|
|
93
|
+
* (`https://…`) or expressions (`x/y`).
|
|
94
|
+
*/
|
|
95
|
+
export declare function extractSlash(text: string): string[];
|
|
96
|
+
/**
|
|
97
|
+
* Build profile records from a committed user message. Capture path +
|
|
98
|
+
* slash + trigram ngrams. Sanitize check runs FIRST: messages with
|
|
99
|
+
* sensitive content are dropped entirely (consistent with session trie).
|
|
100
|
+
*/
|
|
101
|
+
export declare function recordsFromCommit(text: string, ts?: number): ProfileRecord[];
|
|
102
|
+
/**
|
|
103
|
+
* Build an `accept` record for a full or partial acceptance. `prefix` is
|
|
104
|
+
* hashed; `completion` is tokenized. The raw prefix never appears in the
|
|
105
|
+
* returned record. Drops the whole record if either side fails sanitize.
|
|
106
|
+
*/
|
|
107
|
+
export declare function recordFromAccept(prefix: string, completion: string, weight?: number, ts?: number): ProfileRecord | null;
|
|
108
|
+
/**
|
|
109
|
+
* Append one or more records to the JSONL file. Returns silently on write
|
|
110
|
+
* failure — profile logging must never break ghost completion.
|
|
111
|
+
*/
|
|
112
|
+
export declare function appendRecords(cwd: string, recs: ProfileRecord[]): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Parse the JSONL file into an array of records. Silently skips malformed
|
|
115
|
+
* lines (partial trailing write) and records missing required fields.
|
|
116
|
+
* Returns an empty array when the file does not exist.
|
|
117
|
+
*/
|
|
118
|
+
export declare function loadRecords(cwd: string): Promise<ProfileRecord[]>;
|
|
119
|
+
export declare function parseRecords(body: string): ProfileRecord[];
|
|
120
|
+
/**
|
|
121
|
+
* Build the in-memory aggregated index from a record list. Decays records
|
|
122
|
+
* older than `decayDays` by halving their weight; drops weights below
|
|
123
|
+
* `DROP_BELOW_WEIGHT` (0.1). `now` defaults to `Date.now()`; expose for
|
|
124
|
+
* deterministic tests.
|
|
125
|
+
*/
|
|
126
|
+
export declare function buildIndex(records: ProfileRecord[], opts?: {
|
|
127
|
+
decayDays?: number;
|
|
128
|
+
now?: number;
|
|
129
|
+
}): ProfileIndex;
|
|
130
|
+
/**
|
|
131
|
+
* Look up the weight of a trigram (already tokenized + joined). Returns 0
|
|
132
|
+
* when missing. Callers should also tokenize the candidate text the same
|
|
133
|
+
* way the writer did.
|
|
134
|
+
*/
|
|
135
|
+
export declare function ngramWeight(idx: ProfileIndex, tokens: string[]): number;
|
|
136
|
+
/**
|
|
137
|
+
* Profile-bias score for a candidate completion. PRD §M4
|
|
138
|
+
* "Ranking-from-prior": `α·log(1 + ngramWeight) + β·pathWeight + γ·slashWeight`.
|
|
139
|
+
* Returns 0 when the index is empty or the candidate has no signal —
|
|
140
|
+
* neutral input to the reranker.
|
|
141
|
+
*/
|
|
142
|
+
export declare function profileBias(idx: ProfileIndex, text: string, weights?: {
|
|
143
|
+
alpha?: number;
|
|
144
|
+
beta?: number;
|
|
145
|
+
gamma?: number;
|
|
146
|
+
}): number;
|
|
147
|
+
/**
|
|
148
|
+
* Bounded boost for deterministic path matches. Capped so persistent
|
|
149
|
+
* frequency cannot beat a fresh exact-prefix path-prefix match (PRD §M4
|
|
150
|
+
* "Deterministic path/fuzzy ranking"). The cap is a constant 0.2 — tune
|
|
151
|
+
* once we have replay data.
|
|
152
|
+
*/
|
|
153
|
+
export declare const MAX_PATH_BOOST = 0.2;
|
|
154
|
+
export declare function profilePathBoost(idx: ProfileIndex, path: string): number;
|
|
155
|
+
/**
|
|
156
|
+
* Slash-command frequency score. Used by the editor's slash fast-path:
|
|
157
|
+
* given a `/cmd-prefix`, return the best-matching full command by weight.
|
|
158
|
+
* Returns null when nothing in the index extends `prefix`.
|
|
159
|
+
*/
|
|
160
|
+
export declare function bestSlashMatch(idx: ProfileIndex, prefix: string): {
|
|
161
|
+
cmd: string;
|
|
162
|
+
weight: number;
|
|
163
|
+
} | null;
|
|
164
|
+
/**
|
|
165
|
+
* Rotate + compact when the file exceeds `maxBytes`. Strategy: load all
|
|
166
|
+
* records, decay them, sum weights per (kind, key), drop sub-threshold
|
|
167
|
+
* entries, write the compacted file back. Returns true when a rotation
|
|
168
|
+
* happened. Best-effort — swallows errors.
|
|
169
|
+
*/
|
|
170
|
+
export declare function compactIfNeeded(cwd: string, opts?: {
|
|
171
|
+
maxBytes?: number;
|
|
172
|
+
decayDays?: number;
|
|
173
|
+
now?: number;
|
|
174
|
+
}): Promise<boolean>;
|
|
175
|
+
/**
|
|
176
|
+
* Compact a record list in memory: decay aged weights, sum per (kind,key),
|
|
177
|
+
* drop sub-threshold. Pure function — exposed for unit tests.
|
|
178
|
+
*/
|
|
179
|
+
export declare function compactRecords(records: ProfileRecord[], opts?: {
|
|
180
|
+
decayDays?: number;
|
|
181
|
+
now?: number;
|
|
182
|
+
}): ProfileRecord[];
|
|
183
|
+
/** Parse `PI_GHOST_PROFILE_DECAY_DAYS`. Falls back to default when invalid. */
|
|
184
|
+
export declare function parseDecayDaysEnv(raw: string | undefined): number;
|
|
185
|
+
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"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"}
|