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,71 @@
|
|
|
1
|
+
import { estimateTimeSavedMs } from "./keystroke-timer.js";
|
|
2
|
+
import { SWAP_FLICKER_WINDOW_MS } from "./provisional.js";
|
|
3
|
+
/**
|
|
4
|
+
* Build the metrics record for a ghost that was shown and is now being
|
|
5
|
+
* finalized. Pure — no I/O, no `Date.now()`, no env reads (caller resolves
|
|
6
|
+
* `now` and `shortHoverThresholdMs`).
|
|
7
|
+
*/
|
|
8
|
+
export function buildShownMetricsRecord(input) {
|
|
9
|
+
const { pending: m, outcome, now } = input;
|
|
10
|
+
const isAccept = outcome === "accepted" || outcome === "accepted-partial";
|
|
11
|
+
const shouldEvictCache = !!(m.cacheKey && !isAccept);
|
|
12
|
+
const providers = m.trace
|
|
13
|
+
? m.trace.providers
|
|
14
|
+
: [
|
|
15
|
+
{
|
|
16
|
+
provider: m.providerName,
|
|
17
|
+
latencyMs: m.latencyMs ?? 0,
|
|
18
|
+
result: "produced",
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
const multi = input.candidateCount > 1;
|
|
22
|
+
const isNonAcceptOutcome = outcome === "dismissed" || outcome === "stale" || outcome === "expired";
|
|
23
|
+
const flicker = m.swapRenderedAt !== undefined &&
|
|
24
|
+
isNonAcceptOutcome &&
|
|
25
|
+
now - m.swapRenderedAt < SWAP_FLICKER_WINDOW_MS;
|
|
26
|
+
const hoverMs = m.shownAt !== undefined ? Math.max(0, now - m.shownAt) : undefined;
|
|
27
|
+
const shortHoverDismiss = outcome === "dismissed" &&
|
|
28
|
+
hoverMs !== undefined &&
|
|
29
|
+
hoverMs < input.shortHoverThresholdMs;
|
|
30
|
+
let shortHoverPenalty = null;
|
|
31
|
+
if (shortHoverDismiss && m.prefixAtShown && m.completion && m.completion.length > 0) {
|
|
32
|
+
const lastLine = m.prefixAtShown.split("\n").pop() ?? "";
|
|
33
|
+
if (lastLine)
|
|
34
|
+
shortHoverPenalty = { lastLine, completion: m.completion };
|
|
35
|
+
}
|
|
36
|
+
const acceptedChars = isAccept && m.completion ? m.completion.length : undefined;
|
|
37
|
+
const perceivedLatencyMs = m.ttftMs ?? m.latencyMs ?? 0;
|
|
38
|
+
const estimatedTimeSavedMs = acceptedChars !== undefined
|
|
39
|
+
? estimateTimeSavedMs(acceptedChars, input.msPerChar, perceivedLatencyMs)
|
|
40
|
+
: undefined;
|
|
41
|
+
const record = {
|
|
42
|
+
ts: now,
|
|
43
|
+
requestId: m.requestId,
|
|
44
|
+
mode: m.mode,
|
|
45
|
+
providers,
|
|
46
|
+
winner: m.trace?.winner ?? m.providerName,
|
|
47
|
+
result: "produced",
|
|
48
|
+
completionLength: m.completion?.length,
|
|
49
|
+
shown: true,
|
|
50
|
+
acceptance: outcome,
|
|
51
|
+
matchedPath: m.matchedPath,
|
|
52
|
+
...(acceptedChars !== undefined ? { acceptedChars } : {}),
|
|
53
|
+
...(estimatedTimeSavedMs !== undefined ? { estimatedTimeSavedMs } : {}),
|
|
54
|
+
...(multi
|
|
55
|
+
? { candidateCount: input.candidateCount, candidateRank: input.candidateIdx + 1 }
|
|
56
|
+
: {}),
|
|
57
|
+
...(input.cycledCount > 0 ? { cycledCount: input.cycledCount } : {}),
|
|
58
|
+
...(input.partialAccepts > 0 ? { partialAccepts: input.partialAccepts } : {}),
|
|
59
|
+
...(m.provisionalSwapMs !== undefined ? { provisionalSwapMs: m.provisionalSwapMs } : {}),
|
|
60
|
+
...(m.provisionalWasCorrect !== undefined ? { provisionalWasCorrect: m.provisionalWasCorrect } : {}),
|
|
61
|
+
...(flicker ? { provisionalSwapFlicker: true } : {}),
|
|
62
|
+
...(shortHoverDismiss ? { shortHoverDismiss: true } : {}),
|
|
63
|
+
...(m.typedPastDivergent ? { typedPastDivergent: true } : {}),
|
|
64
|
+
...(hoverMs !== undefined ? { displayDurationMs: hoverMs } : {}),
|
|
65
|
+
...(m.ttftMs !== undefined ? { ttftMs: m.ttftMs } : {}),
|
|
66
|
+
...(m.editProximityScore !== undefined ? { editProximityScore: m.editProximityScore } : {}),
|
|
67
|
+
...(m.editHistorySize !== undefined ? { editHistorySize: m.editHistorySize } : {}),
|
|
68
|
+
};
|
|
69
|
+
return { record, isAccept, shouldEvictCache, shortHoverPenalty };
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=metrics-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-builder.js","sourceRoot":"","sources":["../src/metrics-builder.ts"],"names":[],"mappings":"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"}
|
package/dist/metrics.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Source of truth for all completion modes. Both the type union (compile-time)
|
|
3
|
+
* and the parser whitelist (runtime, in `bench.ts`) derive from this array so
|
|
4
|
+
* adding a mode means updating one place.
|
|
5
|
+
*/
|
|
6
|
+
export declare const COMPLETION_MODES: readonly ["deterministic", "llm", "cache", "trie", "speculative-warm", "provisional", "profile-slash"];
|
|
7
|
+
export type CompletionMode = (typeof COMPLETION_MODES)[number];
|
|
2
8
|
export type RequestResult = "produced" | "empty" | "rejected" | "aborted" | "error";
|
|
3
|
-
export type AcceptanceOutcome = "accepted" | "dismissed" | "stale" | "expired";
|
|
9
|
+
export type AcceptanceOutcome = "accepted" | "accepted-partial" | "dismissed" | "stale" | "expired";
|
|
10
|
+
export type QualityAttribution = "accepted" | "dismissed-attributed" | "unknown";
|
|
4
11
|
export type RejectionReason = "stale-text" | "newline" | "too-long" | "assistant-phrasing" | "duplicate-suffix" | "markdown" | "empty" | "echo-token";
|
|
5
12
|
export interface ProviderLatency {
|
|
6
13
|
provider: string;
|
|
@@ -25,7 +32,91 @@ export interface MetricsRecord {
|
|
|
25
32
|
* Never set for LLM mode (would risk leaking output text).
|
|
26
33
|
*/
|
|
27
34
|
matchedPath?: string;
|
|
35
|
+
/** Characters of the ghost the user accepted (full or partial). */
|
|
36
|
+
acceptedChars?: number;
|
|
37
|
+
/** Chars from suggestion that matched the user's eventual committed text. */
|
|
38
|
+
prefixMatchLen?: number;
|
|
39
|
+
/** Levenshtein distance between top-1 candidate and committed line. */
|
|
40
|
+
editDistance?: number;
|
|
41
|
+
/** Count of Ctrl+Right partial accepts on this candidate. */
|
|
42
|
+
partialAccepts?: number;
|
|
43
|
+
/** 1-based rank accepted at time of accept (M3 candidate sets). */
|
|
44
|
+
candidateRank?: number;
|
|
45
|
+
/** Number of candidates considered. */
|
|
46
|
+
candidateCount?: number;
|
|
47
|
+
/** Number of Alt+]/Alt+[ cycles before acceptance. */
|
|
48
|
+
cycledCount?: number;
|
|
49
|
+
/** Prefix-match length per rank — numeric only. */
|
|
50
|
+
prefixMatchLenByRank?: number[];
|
|
51
|
+
/** saved@k by k. */
|
|
52
|
+
savedAt?: {
|
|
53
|
+
"1"?: number;
|
|
54
|
+
"3"?: number;
|
|
55
|
+
"5"?: number;
|
|
56
|
+
};
|
|
57
|
+
/** Time the ghost was visible to the user, in ms. */
|
|
58
|
+
displayDurationMs?: number;
|
|
59
|
+
/** Whether quality fields above are reliable for this record. */
|
|
60
|
+
qualityAttribution?: QualityAttribution;
|
|
61
|
+
/** Provider time-to-first-token in ms (streaming providers only). */
|
|
62
|
+
ttftMs?: number;
|
|
63
|
+
/** Time from provisional ghost render to LLM swap, in ms. */
|
|
64
|
+
provisionalSwapMs?: number;
|
|
65
|
+
/** True iff provisional matched LLM within prefix-match >= 0.8. */
|
|
66
|
+
provisionalWasCorrect?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* True iff a provisional→LLM swap was rendered and the user dismissed or
|
|
69
|
+
* aborted within `SWAP_FLICKER_WINDOW_MS`. Tracks the perceived flicker
|
|
70
|
+
* cost of swaps — the `PI_GHOST_PROVISIONAL_PREFER=1` knob trades raw
|
|
71
|
+
* recall for a lower value of this rate.
|
|
72
|
+
*/
|
|
73
|
+
provisionalSwapFlicker?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* True iff the ghost was visible for less than `SHORT_HOVER_DISMISS_MS`
|
|
76
|
+
* before the user dismissed it. Mild negative signal — emitted on the
|
|
77
|
+
* non-accept record so M8 / future weighting can read it without joining
|
|
78
|
+
* separate streams. The actual hover duration is in `displayDurationMs`.
|
|
79
|
+
*/
|
|
80
|
+
shortHoverDismiss?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* True iff the user typed at least `TYPED_PAST_DIVERGENT_THRESHOLD`
|
|
83
|
+
* consecutive characters that diverged from the served ghost without
|
|
84
|
+
* accepting it (#5). The detection runs across consecutive stale
|
|
85
|
+
* finalizations on the same line, so a single keystroke doesn't trip
|
|
86
|
+
* it — the run resets on any accept. When set, the editor also applies
|
|
87
|
+
* a session-trie penalty against the (prefix, ghost) pair so future
|
|
88
|
+
* suggestions on the same prefix are de-prioritised.
|
|
89
|
+
*/
|
|
90
|
+
typedPastDivergent?: boolean;
|
|
91
|
+
/** Heuristic: acceptedChars * userAvgMsPerChar - perceivedLatencyMs. */
|
|
92
|
+
estimatedTimeSavedMs?: number;
|
|
93
|
+
/**
|
|
94
|
+
* True when the user deleted >50% of inserted text within the regret
|
|
95
|
+
* window after acceptance. See PRD §6 M5a.
|
|
96
|
+
*/
|
|
97
|
+
acceptRegret?: boolean;
|
|
98
|
+
/** Inserted characters subsequently deleted within the regret window. */
|
|
99
|
+
regretDeletedChars?: number;
|
|
100
|
+
/** Combined behavior fingerprint at the time this record was logged. */
|
|
101
|
+
versionFingerprint?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Top candidate's raw `editProximityScore` (un-normalized output of the
|
|
104
|
+
* scorer the reranker received). Pure observability — bench/replay
|
|
105
|
+
* correlate it with `acceptance` to validate the feature weight. Set
|
|
106
|
+
* only when reranker actually ran and edit-history was enabled.
|
|
107
|
+
*/
|
|
108
|
+
editProximityScore?: number;
|
|
109
|
+
/**
|
|
110
|
+
* Size of the `EditHistoryRing` snapshot at predict time. Useful for
|
|
111
|
+
* filtering out records where the ring was still warming up.
|
|
112
|
+
*/
|
|
113
|
+
editHistorySize?: number;
|
|
28
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Debug records have a loose payload by necessity (different kinds carry
|
|
117
|
+
* different shapes). The redactor below scrubs any field that looks like
|
|
118
|
+
* raw prompt/completion content before serialization — see `redactDebug`.
|
|
119
|
+
*/
|
|
29
120
|
export interface DebugRecord {
|
|
30
121
|
ts: number;
|
|
31
122
|
requestId: string;
|
|
@@ -53,4 +144,10 @@ export declare class MetricsLogger {
|
|
|
53
144
|
flush(): Promise<void>;
|
|
54
145
|
private enqueue;
|
|
55
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Strip any debug-record field not on the pass-through whitelist. Replaces
|
|
149
|
+
* the value with a `[redacted: type=T len=N]` placeholder so debugging still
|
|
150
|
+
* sees that *something* was there, without leaking content. SEC-27.
|
|
151
|
+
*/
|
|
152
|
+
export declare function redactDebug(rec: DebugRecord): DebugRecord;
|
|
56
153
|
//# sourceMappingURL=metrics.d.ts.map
|
package/dist/metrics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,cAAc,GAAG,
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
|
package/dist/metrics.js
CHANGED
|
@@ -3,6 +3,46 @@ import { dirname, join } from "node:path";
|
|
|
3
3
|
const MAX_BYTES = 10 * 1024 * 1024;
|
|
4
4
|
const METRICS_REL = ".pi/ghost-autocomplete/metrics.jsonl";
|
|
5
5
|
const DEBUG_REL = ".pi/ghost-autocomplete/debug.jsonl";
|
|
6
|
+
/**
|
|
7
|
+
* Source of truth for all completion modes. Both the type union (compile-time)
|
|
8
|
+
* and the parser whitelist (runtime, in `bench.ts`) derive from this array so
|
|
9
|
+
* adding a mode means updating one place.
|
|
10
|
+
*/
|
|
11
|
+
export const COMPLETION_MODES = [
|
|
12
|
+
"deterministic",
|
|
13
|
+
"llm",
|
|
14
|
+
"cache",
|
|
15
|
+
"trie",
|
|
16
|
+
"speculative-warm",
|
|
17
|
+
"provisional",
|
|
18
|
+
"profile-slash",
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Fields callers may safely pass through to debug records. Anything outside
|
|
22
|
+
* this set is JSON-quoted but with its value replaced by a `[redacted-N]`
|
|
23
|
+
* placeholder showing only its length and type. SEC-27.
|
|
24
|
+
*
|
|
25
|
+
* To allow a new field type-safely, add it here and add a test in
|
|
26
|
+
* `metrics.test.ts`.
|
|
27
|
+
*/
|
|
28
|
+
const DEBUG_PASS_THROUGH_KEYS = new Set([
|
|
29
|
+
"ts",
|
|
30
|
+
"requestId",
|
|
31
|
+
"kind",
|
|
32
|
+
"provider",
|
|
33
|
+
"providerName",
|
|
34
|
+
"mode",
|
|
35
|
+
"latencyMs",
|
|
36
|
+
"durationMs",
|
|
37
|
+
"length",
|
|
38
|
+
"count",
|
|
39
|
+
"status",
|
|
40
|
+
"errorName",
|
|
41
|
+
"reason",
|
|
42
|
+
"phase",
|
|
43
|
+
"branch",
|
|
44
|
+
"matchedPath",
|
|
45
|
+
]);
|
|
6
46
|
export function readMetricsConfigFromEnv() {
|
|
7
47
|
return {
|
|
8
48
|
metricsEnabled: process.env.PI_GHOST_METRICS === "1",
|
|
@@ -39,7 +79,7 @@ export class MetricsLogger {
|
|
|
39
79
|
logDebug(record) {
|
|
40
80
|
if (!this.cfg.debugEnabled)
|
|
41
81
|
return;
|
|
42
|
-
this.enqueue(() => writeLine(this.debugPath, record));
|
|
82
|
+
this.enqueue(() => writeLine(this.debugPath, redactDebug(record)));
|
|
43
83
|
}
|
|
44
84
|
async flush() {
|
|
45
85
|
await this.writeQueue;
|
|
@@ -49,22 +89,96 @@ export class MetricsLogger {
|
|
|
49
89
|
}
|
|
50
90
|
}
|
|
51
91
|
function redactMetric(rec) {
|
|
52
|
-
const { ts, requestId, mode
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
92
|
+
const out = { ts: rec.ts, requestId: rec.requestId, mode: rec.mode, result: rec.result };
|
|
93
|
+
if (rec.providers && rec.providers.length > 0)
|
|
94
|
+
out.providers = rec.providers;
|
|
95
|
+
if (rec.winner !== undefined)
|
|
96
|
+
out.winner = rec.winner;
|
|
97
|
+
if (rec.rejectionReason !== undefined)
|
|
98
|
+
out.rejectionReason = rec.rejectionReason;
|
|
99
|
+
if (rec.completionLength !== undefined)
|
|
100
|
+
out.completionLength = rec.completionLength;
|
|
101
|
+
if (rec.shown !== undefined)
|
|
102
|
+
out.shown = rec.shown;
|
|
103
|
+
if (rec.acceptance !== undefined)
|
|
104
|
+
out.acceptance = rec.acceptance;
|
|
105
|
+
if (rec.mode === "deterministic" && rec.matchedPath !== undefined)
|
|
106
|
+
out.matchedPath = rec.matchedPath;
|
|
107
|
+
// M5a — numeric/boolean fields only; no raw completion text.
|
|
108
|
+
if (rec.acceptedChars !== undefined)
|
|
109
|
+
out.acceptedChars = rec.acceptedChars;
|
|
110
|
+
if (rec.prefixMatchLen !== undefined)
|
|
111
|
+
out.prefixMatchLen = rec.prefixMatchLen;
|
|
112
|
+
if (rec.editDistance !== undefined)
|
|
113
|
+
out.editDistance = rec.editDistance;
|
|
114
|
+
if (rec.partialAccepts !== undefined)
|
|
115
|
+
out.partialAccepts = rec.partialAccepts;
|
|
116
|
+
if (rec.candidateRank !== undefined)
|
|
117
|
+
out.candidateRank = rec.candidateRank;
|
|
118
|
+
if (rec.candidateCount !== undefined)
|
|
119
|
+
out.candidateCount = rec.candidateCount;
|
|
120
|
+
if (rec.cycledCount !== undefined)
|
|
121
|
+
out.cycledCount = rec.cycledCount;
|
|
122
|
+
if (rec.prefixMatchLenByRank !== undefined)
|
|
123
|
+
out.prefixMatchLenByRank = rec.prefixMatchLenByRank;
|
|
124
|
+
if (rec.savedAt !== undefined)
|
|
125
|
+
out.savedAt = rec.savedAt;
|
|
126
|
+
if (rec.displayDurationMs !== undefined)
|
|
127
|
+
out.displayDurationMs = rec.displayDurationMs;
|
|
128
|
+
if (rec.qualityAttribution !== undefined)
|
|
129
|
+
out.qualityAttribution = rec.qualityAttribution;
|
|
130
|
+
if (rec.ttftMs !== undefined)
|
|
131
|
+
out.ttftMs = rec.ttftMs;
|
|
132
|
+
if (rec.provisionalSwapMs !== undefined)
|
|
133
|
+
out.provisionalSwapMs = rec.provisionalSwapMs;
|
|
134
|
+
if (rec.provisionalWasCorrect !== undefined)
|
|
135
|
+
out.provisionalWasCorrect = rec.provisionalWasCorrect;
|
|
136
|
+
if (rec.provisionalSwapFlicker !== undefined)
|
|
137
|
+
out.provisionalSwapFlicker = rec.provisionalSwapFlicker;
|
|
138
|
+
if (rec.shortHoverDismiss !== undefined)
|
|
139
|
+
out.shortHoverDismiss = rec.shortHoverDismiss;
|
|
140
|
+
if (rec.typedPastDivergent !== undefined)
|
|
141
|
+
out.typedPastDivergent = rec.typedPastDivergent;
|
|
142
|
+
if (rec.estimatedTimeSavedMs !== undefined)
|
|
143
|
+
out.estimatedTimeSavedMs = rec.estimatedTimeSavedMs;
|
|
144
|
+
if (rec.acceptRegret !== undefined)
|
|
145
|
+
out.acceptRegret = rec.acceptRegret;
|
|
146
|
+
if (rec.regretDeletedChars !== undefined)
|
|
147
|
+
out.regretDeletedChars = rec.regretDeletedChars;
|
|
148
|
+
if (rec.versionFingerprint !== undefined)
|
|
149
|
+
out.versionFingerprint = rec.versionFingerprint;
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Strip any debug-record field not on the pass-through whitelist. Replaces
|
|
154
|
+
* the value with a `[redacted: type=T len=N]` placeholder so debugging still
|
|
155
|
+
* sees that *something* was there, without leaking content. SEC-27.
|
|
156
|
+
*/
|
|
157
|
+
export function redactDebug(rec) {
|
|
158
|
+
const out = { ts: rec.ts, requestId: rec.requestId, kind: rec.kind };
|
|
159
|
+
for (const [k, v] of Object.entries(rec)) {
|
|
160
|
+
if (k === "ts" || k === "requestId" || k === "kind")
|
|
161
|
+
continue;
|
|
162
|
+
if (DEBUG_PASS_THROUGH_KEYS.has(k)) {
|
|
163
|
+
// Permit primitives and shallow arrays of primitives only.
|
|
164
|
+
if (v === null ||
|
|
165
|
+
typeof v === "boolean" ||
|
|
166
|
+
typeof v === "number" ||
|
|
167
|
+
typeof v === "string") {
|
|
168
|
+
out[k] = v;
|
|
169
|
+
}
|
|
170
|
+
else if (Array.isArray(v) && v.every((e) => typeof e === "number" || typeof e === "string")) {
|
|
171
|
+
out[k] = v;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
out[k] = `[redacted: type=${typeof v}]`;
|
|
175
|
+
}
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const type = typeof v;
|
|
179
|
+
const len = typeof v === "string" ? v.length : Array.isArray(v) ? v.length : undefined;
|
|
180
|
+
out[k] = len !== undefined ? `[redacted: type=${type} len=${len}]` : `[redacted: type=${type}]`;
|
|
181
|
+
}
|
|
68
182
|
return out;
|
|
69
183
|
}
|
|
70
184
|
async function writeLine(path, payload) {
|
package/dist/metrics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AACnC,MAAM,WAAW,GAAG,sCAAsC,CAAC;AAC3D,MAAM,SAAS,GAAG,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
|
package/dist/path-matcher.d.ts
CHANGED
|
@@ -11,6 +11,15 @@ export interface PathPrefixMatch {
|
|
|
11
11
|
export interface FindPathPrefixOptions {
|
|
12
12
|
limit?: number;
|
|
13
13
|
recentPaths?: Set<string> | null;
|
|
14
|
+
/**
|
|
15
|
+
* PRD §M4 — bounded boost from persistent path frequency. Caller passes
|
|
16
|
+
* `(path) => profileStore.profilePathBoost(path)` which returns a value
|
|
17
|
+
* in `[0, MAX_PATH_BOOST]` (0.2). Multiplied by 1e3 in the score formula
|
|
18
|
+
* so it ranks below recent-mention (1e6) but above path length, breaking
|
|
19
|
+
* ties between equally-fresh matches in favor of historically-frequent
|
|
20
|
+
* paths. Cannot beat subtree (1e9) — exact session matches still win.
|
|
21
|
+
*/
|
|
22
|
+
profileBoost?: ((path: string) => number) | null;
|
|
14
23
|
}
|
|
15
24
|
/**
|
|
16
25
|
* Extract a path-like token from the end of `before` (text before the cursor).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-matcher.d.ts","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"path-matcher.d.ts","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACjC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC;CACjD;AAKD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAevE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,qBAAqB,GAAG,MAAW,GACvC,eAAe,GAAG,IAAI,CAmCxB"}
|
package/dist/path-matcher.js
CHANGED
|
@@ -41,6 +41,7 @@ export function findPathPrefix(index, token, opts = {}) {
|
|
|
41
41
|
const o = typeof opts === "number" ? { limit: opts } : opts;
|
|
42
42
|
const limit = o.limit ?? 64;
|
|
43
43
|
const recent = o.recentPaths ?? null;
|
|
44
|
+
const profileBoost = o.profileBoost ?? null;
|
|
44
45
|
// Normalize a leading `./` — extractPathPrefixToken preserves it from the
|
|
45
46
|
// user's text (e.g. "./src/con") but git ls-files entries never start with
|
|
46
47
|
// `./`, so the prefix lookup would otherwise miss every cwd-relative entry.
|
|
@@ -57,8 +58,10 @@ export function findPathPrefix(index, token, opts = {}) {
|
|
|
57
58
|
for (const m of matches) {
|
|
58
59
|
const inSub = cwdRel === "" || m.startsWith(cwdRel);
|
|
59
60
|
const rb = recentBoost(m, recent);
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
const pb = profileBoost ? profileBoost(m) : 0;
|
|
62
|
+
// Lex-rank: subtree dominates, then recent-mention, then profile
|
|
63
|
+
// frequency (tie-breaker), then short.
|
|
64
|
+
const score = (inSub ? 1_000_000_000 : 0) + rb * 1_000_000 + pb * 1_000 - m.length;
|
|
62
65
|
if (score > bestScore) {
|
|
63
66
|
bestScore = score;
|
|
64
67
|
best = m;
|
package/dist/path-matcher.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-matcher.js","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"path-matcher.js","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
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 { DEFAULT_DECAY_DAYS, type ProfileIndex } from "./profile.js";
|
|
20
|
+
export declare class ProfileStore {
|
|
21
|
+
private readonly cwd;
|
|
22
|
+
readonly disabled: boolean;
|
|
23
|
+
private index;
|
|
24
|
+
private writeQueue;
|
|
25
|
+
private writesSinceCompact;
|
|
26
|
+
private decayDays;
|
|
27
|
+
private constructor();
|
|
28
|
+
/**
|
|
29
|
+
* Build a store and load the JSONL into memory. Caller awaits before
|
|
30
|
+
* exposing the store to the editor so the index is hot on first
|
|
31
|
+
* keystroke. Disabled stores short-circuit load entirely.
|
|
32
|
+
*/
|
|
33
|
+
static create(cwd: string, env?: NodeJS.ProcessEnv): Promise<ProfileStore>;
|
|
34
|
+
getIndex(): ProfileIndex;
|
|
35
|
+
get decayDaysSetting(): number;
|
|
36
|
+
/**
|
|
37
|
+
* Capture user-committed text. Extracts paths + slash + trigrams, drops
|
|
38
|
+
* sensitive messages entirely. Returns the count of records emitted —
|
|
39
|
+
* useful for tests/diagnostics.
|
|
40
|
+
*/
|
|
41
|
+
captureCommit(text: string, ts?: number): number;
|
|
42
|
+
/**
|
|
43
|
+
* Capture an accept (full or partial). `weight` defaults to 3 to match
|
|
44
|
+
* PRD §M2 trie weights. Returns true when a record was emitted.
|
|
45
|
+
*/
|
|
46
|
+
captureAccept(prefix: string, completion: string, weight?: number, ts?: number): boolean;
|
|
47
|
+
/** Public lookup surfaces — thin wrappers around `profile.ts`. */
|
|
48
|
+
bestSlashMatch(prefix: string): {
|
|
49
|
+
cmd: string;
|
|
50
|
+
weight: number;
|
|
51
|
+
} | null;
|
|
52
|
+
profileBias(text: string): number;
|
|
53
|
+
profilePathBoost(path: string): number;
|
|
54
|
+
/**
|
|
55
|
+
* Provisional fallback (PRD §M3.5b) — look up an exact-prefix accept
|
|
56
|
+
* record. Returns the completion tokens + summed weight, or null when
|
|
57
|
+
* the prefix has never been the exact key of a captured accept.
|
|
58
|
+
* `prefix` is hashed in-process; the raw string never leaves memory.
|
|
59
|
+
*/
|
|
60
|
+
lookupAcceptByPrefix(prefix: string): {
|
|
61
|
+
completionTokens: string[];
|
|
62
|
+
weight: number;
|
|
63
|
+
} | null;
|
|
64
|
+
/** Flush any pending writes — call before process exit. */
|
|
65
|
+
flush(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Append records both in-memory and to disk. In-memory merge happens
|
|
68
|
+
* synchronously so the very next lookup sees the new weight; the disk
|
|
69
|
+
* write is queued through `writeQueue` to serialize concurrent commits.
|
|
70
|
+
*/
|
|
71
|
+
private mergeAndPersist;
|
|
72
|
+
/**
|
|
73
|
+
* Inline equivalent of `buildIndex` for a small record batch. The
|
|
74
|
+
* fresh-record path skips decay since we just wrote `ts`. Keeping this
|
|
75
|
+
* separate from `profile.buildIndex` avoids reindexing the whole store
|
|
76
|
+
* on every keystroke.
|
|
77
|
+
*/
|
|
78
|
+
private applyToIndex;
|
|
79
|
+
}
|
|
80
|
+
/** Exported for tests — surface compactor knob without re-exporting `profile.ts`. */
|
|
81
|
+
export { DEFAULT_DECAY_DAYS };
|
|
82
|
+
//# sourceMappingURL=profile-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-store.d.ts","sourceRoot":"","sources":["../src/profile-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAKN,kBAAkB,EASlB,KAAK,YAAY,EAEjB,MAAM,cAAc,CAAC;AAQtB,qBAAa,YAAY;IAQvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPrB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO;IAQP;;;;OAIG;WACU,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,YAAY,CAAC;IAe7F,QAAQ,IAAI,YAAY;IAIxB,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED;;;;OAIG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAE,MAAmB,GAAG,MAAM;IAQ5D;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAI,EAAE,EAAE,GAAE,MAAmB,GAAG,OAAO;IAQ/F,kEAAkE;IAClE,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKtE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKjC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKtC;;;;;OAKG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAM3F,2DAA2D;IACrD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;;OAIG;IACH,OAAO,CAAC,eAAe;IA0BvB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;CAmCpB;AAED,qFAAqF;AACrF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|