pi-ghost-autocomplete 0.11.0 → 0.13.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/README.md +88 -0
- package/dist/bench-cli.js +1 -1
- package/dist/bench.js +1 -1
- package/dist/config.d.ts +18 -0
- package/dist/ghost-editor.d.ts +44 -1
- package/dist/index.js +1 -1
- package/dist/intent-classifier.d.ts +90 -0
- package/dist/intent.d.ts +12 -0
- package/dist/replay-cli.js +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-License-Identifier: SSPL-1.0
|
|
3
|
+
* SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
|
|
4
|
+
*/
|
|
5
|
+
import type { CompletionRegister } from "./intent.js";
|
|
6
|
+
export interface IntentClassifierOptions {
|
|
7
|
+
/** Per-consult abort timeout. Default 400 ms (`PI_GHOST_INTENT_CLASSIFIER_TIMEOUT_MS`). */
|
|
8
|
+
timeoutMs: number;
|
|
9
|
+
/** Minimum answer confidence to apply a verdict. Default 0.6 (`PI_GHOST_INTENT_CLASSIFIER_MIN_CONFIDENCE`). */
|
|
10
|
+
minConfidence: number;
|
|
11
|
+
/** Verdict cache TTL. Default 60 s. */
|
|
12
|
+
ttlMs: number;
|
|
13
|
+
/** Verdict cache capacity (insertion-order eviction). Default 64. */
|
|
14
|
+
capacity: number;
|
|
15
|
+
/** Draft-prefix length the cache keys on. Default 32 chars. */
|
|
16
|
+
keyPrefixLen: number;
|
|
17
|
+
/**
|
|
18
|
+
* Debounce for the consult itself — a keystroke burst collapses into one
|
|
19
|
+
* classify call on the latest draft (the pending-set alone can't dedupe:
|
|
20
|
+
* every keystroke changes the cache key). Default 120 ms
|
|
21
|
+
* (`PI_GHOST_INTENT_CLASSIFIER_DEBOUNCE_MS`, clamped [0, 1000]).
|
|
22
|
+
*/
|
|
23
|
+
consultDebounceMs: number;
|
|
24
|
+
now?: () => number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Gate for consulting the classifier. Pure. True only when the heuristic
|
|
28
|
+
* marked the classification low-confidence AND the draft is long enough to
|
|
29
|
+
* classify meaningfully. Uses display width (string-width), matching the
|
|
30
|
+
* editor's completion gate — a 2-char CJK draft at the default `minChars=4`
|
|
31
|
+
* displays 4 columns wide, reaches the LLM, and must also be classifiable.
|
|
32
|
+
*/
|
|
33
|
+
export declare function shouldConsultClassifier(confidence: "high" | "low" | undefined, draft: string, minChars: number): boolean;
|
|
34
|
+
/** Truncated, trimmed draft the verdict cache keys on. Exported for tests. */
|
|
35
|
+
export declare function verdictCacheKey(draft: string, keyPrefixLen: number): string;
|
|
36
|
+
/** The classification question handed to the classifier model. Pure. */
|
|
37
|
+
export declare function buildClassifierContext(draft: string): unknown;
|
|
38
|
+
/** Parse `PI_GHOST_INTENT_CLASSIFIER_TIMEOUT_MS` (clamped to [50, 5000]). */
|
|
39
|
+
export declare function classifierTimeoutFromEnv(raw: string | undefined, fallback: number): number;
|
|
40
|
+
/** Parse `PI_GHOST_INTENT_CLASSIFIER_MIN_CONFIDENCE` (clamped to [0, 1]). */
|
|
41
|
+
export declare function classifierMinConfidenceFromEnv(raw: string | undefined, fallback: number): number;
|
|
42
|
+
/** Parse `PI_GHOST_INTENT_CLASSIFIER_DEBOUNCE_MS` (clamped to [0, 1000]). */
|
|
43
|
+
export declare function classifierConsultDebounceFromEnv(raw: string | undefined, fallback: number): number;
|
|
44
|
+
export declare class IntentClassifier {
|
|
45
|
+
readonly spec: string;
|
|
46
|
+
private readonly registry;
|
|
47
|
+
private readonly opts;
|
|
48
|
+
private readonly classifyFn;
|
|
49
|
+
/** Resolved classifier model (any provider), or null when unresolvable. */
|
|
50
|
+
private modelPromise;
|
|
51
|
+
private readonly verdicts;
|
|
52
|
+
private readonly pending;
|
|
53
|
+
/** Consult debounce: keystroke bursts collapse into one classify call. */
|
|
54
|
+
private consultTimer;
|
|
55
|
+
private consultDraft;
|
|
56
|
+
private constructor();
|
|
57
|
+
/**
|
|
58
|
+
* Build from a config spec. Returns null when disabled (`off`/empty),
|
|
59
|
+
* when the host registry has no `classify` (pi < 0.99), or — for an
|
|
60
|
+
* explicit `provider/model-id` spec — when the typed lookup methods are
|
|
61
|
+
* absent. Model *resolution* stays lazy: `auto` needs the async
|
|
62
|
+
* `getAvailableOfType`, so an unavailable model degrades per-consult
|
|
63
|
+
* (no verdict) rather than disabling the feature at startup.
|
|
64
|
+
*/
|
|
65
|
+
static create(spec: string, registry: unknown, opts?: Partial<IntentClassifierOptions>): IntentClassifier | null;
|
|
66
|
+
/** Resolve (once) the classifier model the spec names or auto-picks. */
|
|
67
|
+
private resolveModel;
|
|
68
|
+
private doResolveModel;
|
|
69
|
+
/**
|
|
70
|
+
* Fire-and-forget consult request. Rapid calls (one per keystroke)
|
|
71
|
+
* collapse into a single classify on the latest draft after
|
|
72
|
+
* {@link IntentClassifierOptions.consultDebounceMs} of quiet — the
|
|
73
|
+
* pending-set alone cannot dedupe because every keystroke changes the
|
|
74
|
+
* cache key. Never blocks, never throws.
|
|
75
|
+
*/
|
|
76
|
+
maybeConsult(draft: string): void;
|
|
77
|
+
private fireConsult;
|
|
78
|
+
private storeVerdict;
|
|
79
|
+
/**
|
|
80
|
+
* Fresh verdict for the draft's cache key, or null. Prefix-aware: a
|
|
81
|
+
* verdict consulted on an earlier prefix of the same line applies as
|
|
82
|
+
* the line grows (and, symmetrically, after backspacing into it), so
|
|
83
|
+
* the classification of a line's opening sticks without re-consulting
|
|
84
|
+
* per keystroke. Strong-classification gating in the editor bounds any
|
|
85
|
+
* stale-prefix reuse.
|
|
86
|
+
*/
|
|
87
|
+
verdictFor(draft: string): CompletionRegister | null;
|
|
88
|
+
/** Number of live verdicts — surfaced in `/ghost` diagnostics. */
|
|
89
|
+
get verdictCount(): number;
|
|
90
|
+
}
|
package/dist/intent.d.ts
CHANGED
|
@@ -221,6 +221,18 @@ export interface IntentClassification {
|
|
|
221
221
|
intent: PromptIntent;
|
|
222
222
|
register: CompletionRegister;
|
|
223
223
|
proseReason?: ProseReason;
|
|
224
|
+
/**
|
|
225
|
+
* Heuristic signal strength (track C). `"low"` marks the two weak spots
|
|
226
|
+
* of the regex pipeline — single-line prose (persona split between
|
|
227
|
+
* `general-prose` and `agent-message` is guesswork below 4 lines of
|
|
228
|
+
* context) and the final fallback `instruction` (no verb, marker, or
|
|
229
|
+
* question shape matched — the draft could equally be code like
|
|
230
|
+
* `npm install`). The editor consults the optional intent classifier
|
|
231
|
+
* (pi ≥ 0.99 `registry.classify`, e.g. Jev or a llama.cpp classifier)
|
|
232
|
+
* only for `"low"` classifications, so strong signals never pay the
|
|
233
|
+
* round-trip. Absent means `"high"` (pre-track-C callers).
|
|
234
|
+
*/
|
|
235
|
+
confidence?: "high" | "low";
|
|
224
236
|
}
|
|
225
237
|
/**
|
|
226
238
|
* Detailed variant of `classifyPromptIntent`. Same classification order,
|