pi-ghost-autocomplete 0.9.1 → 0.11.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 +61 -5
- package/dist/bench-cli.js +1 -1
- package/dist/bench.js +1 -1
- package/dist/config.d.ts +27 -3
- package/dist/fuzzy-matcher.d.ts +3 -0
- package/dist/ghost-editor.d.ts +39 -160
- package/dist/ghost-utils.d.ts +150 -0
- package/dist/index.d.ts +17 -5
- package/dist/index.js +1 -1
- package/dist/providers/openai-compat-provider.d.ts +5 -1
- package/dist/providers/pi-model-provider.d.ts +78 -0
- package/dist/providers/race.d.ts +11 -0
- package/dist/providers/router.d.ts +5 -0
- package/dist/recent-paths.d.ts +31 -0
- package/dist/replay-cli.js +1 -1
- package/package.json +9 -9
|
@@ -25,6 +25,10 @@ export declare class OpenAICompatProvider implements GhostProvider {
|
|
|
25
25
|
readonly name: string;
|
|
26
26
|
/** Why the most recent `fireOne` resolved empty; consumed by the editor. */
|
|
27
27
|
private lastEmptyReason;
|
|
28
|
+
/** Snapshot of `PI_GHOST_FIM_CONTEXT_ALL_INTENTS`, read once at construction
|
|
29
|
+
* instead of per `predict` (#3 — `buildFIMPrompt` previously read
|
|
30
|
+
* `process.env` on every prediction). */
|
|
31
|
+
private readonly fimContextAllIntentsRaw;
|
|
28
32
|
constructor(config: OpenAICompatProviderConfig);
|
|
29
33
|
get debounceMs(): number;
|
|
30
34
|
/**
|
|
@@ -66,7 +70,7 @@ export declare function fimContextIncluded(intent: PromptIntent | undefined, all
|
|
|
66
70
|
* `question` intents, where the context is dropped to avoid the empty-rate
|
|
67
71
|
* spike described on {@link FIM_CONTEXT_SUPPRESSED_INTENTS}.
|
|
68
72
|
*/
|
|
69
|
-
export declare function buildFIMPrompt(req: GhostRequest, maxRecent: number): {
|
|
73
|
+
export declare function buildFIMPrompt(req: GhostRequest, maxRecent: number, fimContextAllIntentsRaw?: string): {
|
|
70
74
|
prompt: string;
|
|
71
75
|
suffix: string;
|
|
72
76
|
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-License-Identifier: SSPL-1.0
|
|
3
|
+
* SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
|
|
4
|
+
*/
|
|
5
|
+
import type { ModelRegistry } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import type { EmptyReason } from "../metrics.js";
|
|
7
|
+
import type { PiModelProviderConfig } from "../config.js";
|
|
8
|
+
import { type GhostProvider, type GhostRequest, type StreamDelta } from "./types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Pi-registry backend: complete through the session's own `ModelRegistry`.
|
|
11
|
+
*
|
|
12
|
+
* Unlike {@link CloudProvider} — which can only resolve models from pi-ai's
|
|
13
|
+
* *static builtin* catalog and must hand-resolve auth (skipping registries
|
|
14
|
+
* with a custom `baseUrl`) — this backend delegates both concerns to pi:
|
|
15
|
+
*
|
|
16
|
+
* - **Model resolution** via `registry.find(provider, id)` / first match in
|
|
17
|
+
* `registry.getAvailable()`. Works for dynamic providers (e.g. "radius")
|
|
18
|
+
* and any model registered by other extensions, none of which exist in
|
|
19
|
+
* the static catalog.
|
|
20
|
+
* - **Auth + endpoint** via `registry.complete()`, which resolves
|
|
21
|
+
* request-time auth (models.json keys, stored credentials, OAuth) and the
|
|
22
|
+
* provider's real `baseUrl` exactly as the main agent sees them
|
|
23
|
+
* (`ModelRuntime.prepareRequest`). No ghost API key needed.
|
|
24
|
+
*
|
|
25
|
+
* Available on pi 0.84+; streaming additionally requires 0.99's
|
|
26
|
+
* `registry.stream` (feature-detected, falls back to the pipeline's
|
|
27
|
+
* non-streaming `predict()` path on 0.84).
|
|
28
|
+
*/
|
|
29
|
+
export declare class PiModelProvider implements GhostProvider {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
private readonly registry;
|
|
32
|
+
private readonly config;
|
|
33
|
+
private readonly streamFn;
|
|
34
|
+
private resolved;
|
|
35
|
+
private resolvedSpec;
|
|
36
|
+
private lastEmpty;
|
|
37
|
+
/**
|
|
38
|
+
* Streaming variant — attached in the constructor **only** when the
|
|
39
|
+
* registry exposes `stream()` (pi ≥ 0.99). The request pipeline selects
|
|
40
|
+
* the streaming path whenever `predictStream` is present, so a class
|
|
41
|
+
* method would make every host look streaming-capable and silently starve
|
|
42
|
+
* pi 0.84–0.98 of ghosts instead of falling back to `predict()`.
|
|
43
|
+
*/
|
|
44
|
+
predictStream?: (req: GhostRequest) => AsyncIterable<StreamDelta>;
|
|
45
|
+
constructor(config: PiModelProviderConfig, registry: ModelRegistry);
|
|
46
|
+
get debounceMs(): number;
|
|
47
|
+
consumeLastEmptyReason(): EmptyReason | null;
|
|
48
|
+
/**
|
|
49
|
+
* Resolve `modelSpec` (`"provider/model-id"` or bare `"model-id"`) to a
|
|
50
|
+
* registry model. Successful lookups are cached per spec; failures retry
|
|
51
|
+
* on the next call (the registry may still be loading models.json early
|
|
52
|
+
* in a session, and a failed scan of the model list is cheap).
|
|
53
|
+
*/
|
|
54
|
+
private resolveModel;
|
|
55
|
+
/**
|
|
56
|
+
* One completion through the registry. Auth, headers, and endpoint are
|
|
57
|
+
* resolved by pi at request time; we only supply sampling knobs, the
|
|
58
|
+
* abort signal, and the SEC-3 timeout.
|
|
59
|
+
*/
|
|
60
|
+
predict(req: GhostRequest): Promise<string | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Streaming implementation behind the conditionally-attached
|
|
63
|
+
* {@link predictStream} — only reachable when the registry exposes
|
|
64
|
+
* `stream()` (pi ≥ 0.99; see {@link StreamingRegistry}). Mirrors
|
|
65
|
+
* {@link CloudProvider.predictStream}: sanitize once on the final
|
|
66
|
+
* assembled text, never per delta.
|
|
67
|
+
*/
|
|
68
|
+
private streamPredict;
|
|
69
|
+
/**
|
|
70
|
+
* Preflight for /ghost diagnostics and router chat-leg warnings: resolves
|
|
71
|
+
* the spec and (when the registry supports it) checks that the model's
|
|
72
|
+
* provider has configured auth.
|
|
73
|
+
*/
|
|
74
|
+
preflight(): Promise<{
|
|
75
|
+
ok: boolean;
|
|
76
|
+
message: string;
|
|
77
|
+
}>;
|
|
78
|
+
}
|
package/dist/providers/race.d.ts
CHANGED
|
@@ -41,6 +41,17 @@ export declare class RaceProvider implements GhostProvider {
|
|
|
41
41
|
wins: number;
|
|
42
42
|
skipRemaining: number;
|
|
43
43
|
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Skip-penalty filter (PRD §M8). Drop members still under a skip penalty,
|
|
46
|
+
* decrementing their counter and recording them in `skipped` so metrics can
|
|
47
|
+
* attribute the skip. If ALL members are skipped, fall back to running them
|
|
48
|
+
* anyway so the weighting policy can't permanently starve the user.
|
|
49
|
+
*
|
|
50
|
+
* In the all-skipped fallback the returned array is `this.members`, but
|
|
51
|
+
* `skipRemaining` has already been decremented for everyone — they execute
|
|
52
|
+
* regardless, which prevents starvation when every member is flagged slow.
|
|
53
|
+
*/
|
|
54
|
+
private filterSkippedMembers;
|
|
44
55
|
get debounceMs(): number;
|
|
45
56
|
consumeLastTrace(): RaceTrace | null;
|
|
46
57
|
/**
|
|
@@ -42,6 +42,11 @@ export declare class RouterProvider implements GhostProvider {
|
|
|
42
42
|
/** Leg that served the most recent request — the one to query for the
|
|
43
43
|
* empty-cause diagnostic so it reflects the register that actually ran. */
|
|
44
44
|
private lastLeg;
|
|
45
|
+
/** Register-debounce multipliers snapshotted once at construction instead
|
|
46
|
+
* of re-read per `debounceMsFor` (#3 — `debounceProseMult`/
|
|
47
|
+
* `debounceAgentMult` previously read `process.env` on every dispatch). */
|
|
48
|
+
private readonly proseMult;
|
|
49
|
+
private readonly agentMult;
|
|
45
50
|
constructor(fim: GhostProvider, chat: GhostProvider | null);
|
|
46
51
|
get debounceMs(): number;
|
|
47
52
|
/**
|
package/dist/recent-paths.d.ts
CHANGED
|
@@ -26,3 +26,34 @@ export declare function recentBoost(matchPath: string, recent: Set<string> | nul
|
|
|
26
26
|
* assistant messages. Oldest-first.
|
|
27
27
|
*/
|
|
28
28
|
export declare function getRoleWeightedRecent(ctx: ExtensionContext, userMax: number, assistantMax: number): RecentMessage[];
|
|
29
|
+
/** How long a tool-touched path keeps its ranking boost. */
|
|
30
|
+
export declare const TOOL_PATH_TTL_MS: number;
|
|
31
|
+
/** Bound on live tool paths kept for boosting. */
|
|
32
|
+
export declare const MAX_TOOL_PATHS = 32;
|
|
33
|
+
/**
|
|
34
|
+
* Normalize a `read`/`edit`/`write` tool-input path so it string-matches
|
|
35
|
+
* PathIndex entries (git ls-files output: POSIX separators, root-relative).
|
|
36
|
+
*
|
|
37
|
+
* - Backslashes → forward slashes (Windows tool inputs).
|
|
38
|
+
* - Absolute paths inside `root` → root-relative.
|
|
39
|
+
* - Leading `./` stripped.
|
|
40
|
+
*
|
|
41
|
+
* Paths outside `root` (or when `root` is null) pass through normalized —
|
|
42
|
+
* they simply won't exact-hit an index entry and only degrade the boost.
|
|
43
|
+
*/
|
|
44
|
+
export declare function normalizeToolPath(raw: string, root: string | null): string;
|
|
45
|
+
/**
|
|
46
|
+
* Merge regex-scraped mention paths with live tool-recorded paths.
|
|
47
|
+
* Tool entries survive the scrape TTL (5 s) — they are exact inputs, not
|
|
48
|
+
* text guesses — and are pruned only by their own {@link TOOL_PATH_TTL_MS}.
|
|
49
|
+
*/
|
|
50
|
+
export declare function mergeRecentPathSets(scraped: Set<string>, toolPaths: Map<string, number>, now: number, ttlMs?: number): Set<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Re-key recorded tool paths against a (possibly late-arriving) index
|
|
53
|
+
* root. The PathIndex is built asynchronously after the editor installs;
|
|
54
|
+
* tool results that land before it settles were normalized with
|
|
55
|
+
* `root === null` and may be absolute. Renormalizing against the real
|
|
56
|
+
* root makes them string-match the git ls-files keys. Collisions keep
|
|
57
|
+
* the newest timestamp.
|
|
58
|
+
*/
|
|
59
|
+
export declare function renormalizeToolPaths(toolPaths: Map<string, number>, root: string): Map<string, number>;
|