pi-ghost-autocomplete 0.3.2 → 0.4.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.
Files changed (168) hide show
  1. package/LICENSE +561 -0
  2. package/README.md +464 -331
  3. package/dist/bench-cli.js +1 -123
  4. package/dist/bench.d.ts +7 -3
  5. package/dist/bench.js +1 -522
  6. package/dist/config.d.ts +4 -1
  7. package/dist/context-aggregator.d.ts +4 -1
  8. package/dist/cycle-manager.d.ts +2 -21
  9. package/dist/entropy-stop.d.ts +4 -1
  10. package/dist/eval-dataset.d.ts +2 -13
  11. package/dist/fuzzy-matcher.d.ts +4 -1
  12. package/dist/ghost-editor.d.ts +11 -2
  13. package/dist/index.d.ts +4 -1
  14. package/dist/index.js +1 -289
  15. package/dist/intent.d.ts +179 -0
  16. package/dist/metrics.d.ts +4 -1
  17. package/dist/path-index.d.ts +4 -1
  18. package/dist/path-matcher.d.ts +4 -1
  19. package/dist/profile-store.d.ts +4 -1
  20. package/dist/profile.d.ts +2 -20
  21. package/dist/providers/cloud-provider.d.ts +4 -1
  22. package/dist/providers/local-provider.d.ts +4 -1
  23. package/dist/providers/openai-compat-provider.d.ts +24 -1
  24. package/dist/providers/race.d.ts +4 -1
  25. package/dist/providers/types.d.ts +13 -1
  26. package/dist/recent-paths.d.ts +4 -1
  27. package/dist/replay-cli.js +1 -166
  28. package/dist/replay.d.ts +2 -7
  29. package/package.json +90 -80
  30. package/dist/bench-cli.d.ts +0 -3
  31. package/dist/bench-cli.d.ts.map +0 -1
  32. package/dist/bench-cli.js.map +0 -1
  33. package/dist/bench.d.ts.map +0 -1
  34. package/dist/bench.js.map +0 -1
  35. package/dist/cache.d.ts +0 -124
  36. package/dist/cache.d.ts.map +0 -1
  37. package/dist/cache.js +0 -173
  38. package/dist/cache.js.map +0 -1
  39. package/dist/candidate-rerank.d.ts +0 -57
  40. package/dist/candidate-rerank.d.ts.map +0 -1
  41. package/dist/candidate-rerank.js +0 -78
  42. package/dist/candidate-rerank.js.map +0 -1
  43. package/dist/config.d.ts.map +0 -1
  44. package/dist/config.js +0 -317
  45. package/dist/config.js.map +0 -1
  46. package/dist/context-aggregator.d.ts.map +0 -1
  47. package/dist/context-aggregator.js +0 -87
  48. package/dist/context-aggregator.js.map +0 -1
  49. package/dist/context-selector.d.ts +0 -128
  50. package/dist/context-selector.d.ts.map +0 -1
  51. package/dist/context-selector.js +0 -300
  52. package/dist/context-selector.js.map +0 -1
  53. package/dist/cycle-manager.d.ts.map +0 -1
  54. package/dist/cycle-manager.js +0 -168
  55. package/dist/cycle-manager.js.map +0 -1
  56. package/dist/edit-history-ring.d.ts +0 -148
  57. package/dist/edit-history-ring.d.ts.map +0 -1
  58. package/dist/edit-history-ring.js +0 -262
  59. package/dist/edit-history-ring.js.map +0 -1
  60. package/dist/entropy-stop.d.ts.map +0 -1
  61. package/dist/entropy-stop.js +0 -141
  62. package/dist/entropy-stop.js.map +0 -1
  63. package/dist/eval-dataset.d.ts.map +0 -1
  64. package/dist/eval-dataset.js +0 -127
  65. package/dist/eval-dataset.js.map +0 -1
  66. package/dist/fast-path-engine.d.ts +0 -286
  67. package/dist/fast-path-engine.d.ts.map +0 -1
  68. package/dist/fast-path-engine.js +0 -341
  69. package/dist/fast-path-engine.js.map +0 -1
  70. package/dist/fuzzy-matcher.d.ts.map +0 -1
  71. package/dist/fuzzy-matcher.js +0 -162
  72. package/dist/fuzzy-matcher.js.map +0 -1
  73. package/dist/ghost-editor.d.ts.map +0 -1
  74. package/dist/ghost-editor.js +0 -1491
  75. package/dist/ghost-editor.js.map +0 -1
  76. package/dist/index.d.ts.map +0 -1
  77. package/dist/index.js.map +0 -1
  78. package/dist/keystroke-timer.d.ts +0 -59
  79. package/dist/keystroke-timer.d.ts.map +0 -1
  80. package/dist/keystroke-timer.js +0 -94
  81. package/dist/keystroke-timer.js.map +0 -1
  82. package/dist/metrics-builder.d.ts +0 -71
  83. package/dist/metrics-builder.d.ts.map +0 -1
  84. package/dist/metrics-builder.js +0 -71
  85. package/dist/metrics-builder.js.map +0 -1
  86. package/dist/metrics.d.ts.map +0 -1
  87. package/dist/metrics.js +0 -212
  88. package/dist/metrics.js.map +0 -1
  89. package/dist/path-index.d.ts.map +0 -1
  90. package/dist/path-index.js +0 -148
  91. package/dist/path-index.js.map +0 -1
  92. package/dist/path-matcher.d.ts.map +0 -1
  93. package/dist/path-matcher.js +0 -88
  94. package/dist/path-matcher.js.map +0 -1
  95. package/dist/profile-store.d.ts.map +0 -1
  96. package/dist/profile-store.js +0 -199
  97. package/dist/profile-store.js.map +0 -1
  98. package/dist/profile.d.ts.map +0 -1
  99. package/dist/profile.js +0 -434
  100. package/dist/profile.js.map +0 -1
  101. package/dist/providers/cloud-provider.d.ts.map +0 -1
  102. package/dist/providers/cloud-provider.js +0 -109
  103. package/dist/providers/cloud-provider.js.map +0 -1
  104. package/dist/providers/local-provider.d.ts.map +0 -1
  105. package/dist/providers/local-provider.js +0 -48
  106. package/dist/providers/local-provider.js.map +0 -1
  107. package/dist/providers/openai-compat-provider.d.ts.map +0 -1
  108. package/dist/providers/openai-compat-provider.js +0 -215
  109. package/dist/providers/openai-compat-provider.js.map +0 -1
  110. package/dist/providers/openai-completions-runner.d.ts +0 -52
  111. package/dist/providers/openai-completions-runner.d.ts.map +0 -1
  112. package/dist/providers/openai-completions-runner.js +0 -141
  113. package/dist/providers/openai-completions-runner.js.map +0 -1
  114. package/dist/providers/race.d.ts.map +0 -1
  115. package/dist/providers/race.js +0 -441
  116. package/dist/providers/race.js.map +0 -1
  117. package/dist/providers/truncate.d.ts +0 -7
  118. package/dist/providers/truncate.d.ts.map +0 -1
  119. package/dist/providers/truncate.js +0 -57
  120. package/dist/providers/truncate.js.map +0 -1
  121. package/dist/providers/types.d.ts.map +0 -1
  122. package/dist/providers/types.js +0 -60
  123. package/dist/providers/types.js.map +0 -1
  124. package/dist/provisional-manager.d.ts +0 -93
  125. package/dist/provisional-manager.d.ts.map +0 -1
  126. package/dist/provisional-manager.js +0 -98
  127. package/dist/provisional-manager.js.map +0 -1
  128. package/dist/provisional.d.ts +0 -150
  129. package/dist/provisional.d.ts.map +0 -1
  130. package/dist/provisional.js +0 -238
  131. package/dist/provisional.js.map +0 -1
  132. package/dist/recent-paths.d.ts.map +0 -1
  133. package/dist/recent-paths.js +0 -114
  134. package/dist/recent-paths.js.map +0 -1
  135. package/dist/regret-tracker.d.ts +0 -84
  136. package/dist/regret-tracker.d.ts.map +0 -1
  137. package/dist/regret-tracker.js +0 -145
  138. package/dist/regret-tracker.js.map +0 -1
  139. package/dist/replay-cli.d.ts +0 -13
  140. package/dist/replay-cli.d.ts.map +0 -1
  141. package/dist/replay-cli.js.map +0 -1
  142. package/dist/replay.d.ts.map +0 -1
  143. package/dist/replay.js +0 -225
  144. package/dist/replay.js.map +0 -1
  145. package/dist/reranker.d.ts +0 -181
  146. package/dist/reranker.d.ts.map +0 -1
  147. package/dist/reranker.js +0 -324
  148. package/dist/reranker.js.map +0 -1
  149. package/dist/session-trie.d.ts +0 -103
  150. package/dist/session-trie.d.ts.map +0 -1
  151. package/dist/session-trie.js +0 -280
  152. package/dist/session-trie.js.map +0 -1
  153. package/dist/speculative.d.ts +0 -74
  154. package/dist/speculative.d.ts.map +0 -1
  155. package/dist/speculative.js +0 -107
  156. package/dist/speculative.js.map +0 -1
  157. package/dist/tool-summarize.d.ts +0 -40
  158. package/dist/tool-summarize.d.ts.map +0 -1
  159. package/dist/tool-summarize.js +0 -245
  160. package/dist/tool-summarize.js.map +0 -1
  161. package/dist/trie-sanitize.d.ts +0 -22
  162. package/dist/trie-sanitize.d.ts.map +0 -1
  163. package/dist/trie-sanitize.js +0 -142
  164. package/dist/trie-sanitize.js.map +0 -1
  165. package/dist/versions.d.ts +0 -23
  166. package/dist/versions.d.ts.map +0 -1
  167. package/dist/versions.js +0 -31
  168. package/dist/versions.js.map +0 -1
@@ -0,0 +1,179 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
5
+ /**
6
+ * Intent detection for ghost autocompletion.
7
+ *
8
+ * Centralises all prose / path / filename heuristics so they can be shared
9
+ * between the deterministic fast-path engine and the LLM provider layer
10
+ * without circular dependencies.
11
+ *
12
+ * This module is the single source of truth for:
13
+ * - `PromptIntent` — discriminated union for intent classification
14
+ * - `classifyPromptIntent()` — regex-based intent classifier
15
+ * - `ACTION_VERBS` — canonical action-verb list (used by isPathContext,
16
+ * draftLooksLikePathContext, and fuzzy-matcher)
17
+ * - `looksLikeProse()` — single-line prose detection
18
+ * - `looksLikeProseContext()` — multi-line prose detection
19
+ * - `isPathContext()` — path-prefix context validation
20
+ * - `looksLikeFilename()` — completion output shape detection
21
+ * - `draftLooksLikePathContext()` — draft context shape detection
22
+ *
23
+ * Consumers import from here; legacy re-exports live in `fast-path-engine.ts`
24
+ * and `providers/truncate.ts` for backward compatibility with existing tests.
25
+ */
26
+ /**
27
+ * Coarse-grained intent of the current prompt line. Used to route the
28
+ * autocompletion pipeline:
29
+ *
30
+ * - `command` — shell-like command (starts with `/`, `$`, `!`, `@`)
31
+ * → deterministic + LLM
32
+ * - `question` — user asks a question (starts with how/what/why/...)
33
+ * → LLM only (skip deterministic)
34
+ * - `instruction` — imperative sentence (starts with a verb)
35
+ * → deterministic + LLM
36
+ * - `path-ref` — user is typing a file path or referencing files
37
+ * → deterministic only
38
+ * - `prose` — natural-language sentence (none of the above)
39
+ * → LLM only (skip deterministic)
40
+ */
41
+ export type PromptIntent = "command" | "question" | "instruction" | "path-ref" | "prose";
42
+ /**
43
+ * Action verbs that strongly signal the user is about to reference a file
44
+ * path. Used by `isPathContext`, `draftLooksLikePathContext`, and the
45
+ * fuzzy matcher's `hasActionTrigger` gate.
46
+ *
47
+ * Single canonical source — do NOT duplicate elsewhere.
48
+ * Covers: file manipulation (open/edit/read/write/save), navigation (cd/ls),
49
+ * search (find/check/look), shell commands (cat/less/head/tail/touch/mkdir/
50
+ * rm/cp/mv), loading (load/import/include), and general (show/view/see/run/add).
51
+ */
52
+ export declare const ACTION_VERBS: Set<string>;
53
+ /** Alternation group for use in regex character classes. Kept in sync
54
+ * with `ACTION_VERBS` — rebuild with `[...ACTION_VERBS].join("|")`.
55
+ * Exported so consumers (fast-path-engine, etc.) can build verb-aware
56
+ * regexes without duplicating the list. */
57
+ export declare const ACTION_VERBS_ALT: string;
58
+ /**
59
+ * Heuristic: does the text before the cursor look like natural-language prose
60
+ * rather than a command / path context? Returns true when there are 4+ word
61
+ * tokens (\w{2,}) — a strong signal the user is writing a sentence, not a
62
+ * filename.
63
+ *
64
+ * This prevents the fuzzy matcher from proposing `config.ts` when the user
65
+ * types "please add a con|" ("con" fuzzy-matches config.ts at score ~75).
66
+ */
67
+ export declare function looksLikeProse(lineBeforeCursor: string): boolean;
68
+ /** Reason a multi-line prose context fired. Used for observability so
69
+ * callers can log *why* the deterministic path was suppressed. */
70
+ export type ProseContextReason = "density" | "cohesion" | "punctuation";
71
+ /** Detailed result of multi-line prose detection. `reason` is set iff
72
+ * `isProse` is true, naming the rule that triggered. */
73
+ export interface ProseContextResult {
74
+ isProse: boolean;
75
+ reason?: ProseContextReason;
76
+ }
77
+ /**
78
+ * Heuristic: do the surrounding lines indicate a prose context (the user
79
+ * is writing natural-language text across multiple lines)? Returns the
80
+ * verdict together with the matching reason for observability.
81
+ *
82
+ * Rules (first match wins):
83
+ *
84
+ * 1. **High word density**: the previous lines contain 8+ word tokens total
85
+ * (\w{2,}) — strong signal of paragraph-level prose.
86
+ * 2. **Lexical cohesion**: the previous lines share ≥2 word tokens with the
87
+ * current line — inspired by Hearst's TextTiling algorithm for
88
+ * detecting topic continuity.
89
+ * 3. **Sentence punctuation**: the previous non-empty line ends with a
90
+ * period or comma AND carries at least PUNCTUATION_MIN_PREV_TOKENS
91
+ * alpha word tokens. The token-count guard kills shell one-liners
92
+ * like `echo hello,` that would otherwise be misrouted.
93
+ * Semicolons are excluded (common in code).
94
+ */
95
+ export declare function classifyProseContext(previousLines: string[], currentLineBeforeCursor: string): ProseContextResult;
96
+ /**
97
+ * Boolean wrapper kept for back-compat with existing tests / call sites
98
+ * that don't need the reason. Prefer `classifyProseContext` when the
99
+ * caller wants to log why prose mode triggered.
100
+ *
101
+ * @param previousLines — lines before the current line
102
+ * @param currentLineBeforeCursor — text on the current line before the cursor
103
+ */
104
+ export declare function looksLikeProseContext(previousLines: string[], currentLineBeforeCursor: string): boolean;
105
+ /**
106
+ * Heuristic: is the path-prefix token in a context that suggests the user
107
+ * intends to type a filename? Returns true when:
108
+ * - The token is inside quotes
109
+ * - The token is preceded by an action verb + whitespace ("read src/|")
110
+ * - The token starts at column 0 or after only whitespace
111
+ * - The preceding character is a non-letter boundary (`=`, `:`, `,`, etc.)
112
+ *
113
+ * Returns false when the token is embedded in prose (e.g. "and then src/|").
114
+ */
115
+ export declare function isPathContext(lineBeforeCursor: string, _token: {
116
+ token: string;
117
+ insideQuote: boolean;
118
+ }): boolean;
119
+ /**
120
+ * Short human-readable description for each intent, suitable for injection
121
+ * into LLM system prompts or FIM comment headers. Single canonical source —
122
+ * both chat-style (`truncate.ts`) and FIM (`openai-compat-provider.ts`)
123
+ * providers use these so the wording stays consistent.
124
+ */
125
+ export declare const INTENT_DESCRIPTION: Record<PromptIntent, string>;
126
+ /**
127
+ * Classify the user's current prompt intent. Uses simple regex / keyword
128
+ * heuristics to decide which completion pipeline to activate.
129
+ *
130
+ * The classifier examines only the current line before the cursor (fast)
131
+ * plus optional previous lines for multi-line prose detection.
132
+ *
133
+ * Returns one of: `command`, `question`, `instruction`, `path-ref`, `prose`.
134
+ *
135
+ * Classification order (first match wins):
136
+ * 1. `command` — line starts with `/`, `!`, `$`, `@`
137
+ * 2. `path-ref` — line ends with a path-like prefix (contains `/`) or is
138
+ * inside quotes after an action verb
139
+ * 3. `question` — line starts with a question word (how/what/why/...)
140
+ * 4. `instruction` — line starts with an action verb
141
+ * 5. `prose` — multi-line prose context detected, or single-line prose
142
+ * (4+ word tokens)
143
+ */
144
+ export declare function classifyPromptIntent(lineBeforeCursor: string, previousLines?: string[]): PromptIntent;
145
+ /** Reason a prompt was classified as prose. `single-line` corresponds to
146
+ * `looksLikeProse` (4+ word tokens on the current line); the others
147
+ * mirror `ProseContextReason`. */
148
+ export type ProseReason = ProseContextReason | "single-line";
149
+ /** Detailed intent classification including the prose-rule reason when
150
+ * applicable. Lets the editor log *why* the deterministic path was
151
+ * suppressed without re-running the heuristic. */
152
+ export interface IntentClassification {
153
+ intent: PromptIntent;
154
+ proseReason?: ProseReason;
155
+ }
156
+ /**
157
+ * Detailed variant of `classifyPromptIntent`. Same classification order,
158
+ * but returns the prose-rule reason when intent === "prose" so callers
159
+ * can emit observability records.
160
+ */
161
+ export declare function classifyPromptIntentDetailed(lineBeforeCursor: string, previousLines?: string[]): IntentClassification;
162
+ /**
163
+ * Heuristic: does the completion text look like a raw filename or path?
164
+ * Matches patterns like "src/foo/bar.ts", "config.json", "./path/to/file",
165
+ * and extensions like .ts, .js, .py, .json, .md, etc.
166
+ *
167
+ * Intentionally conservative: requires at least a 2-char extension with
168
+ * no trailing dot, and rejects common false positives like "hello.there"
169
+ * by requiring the extension part to look like a real file extension
170
+ * (starts with a letter, contains only letters/digits).
171
+ */
172
+ export declare function looksLikeFilename(text: string): boolean;
173
+ /**
174
+ * Heuristic: does the user's draft text look like they're in a path-typing
175
+ * context? Returns true when the draft ends with a path-like prefix
176
+ * (contains `/`, optionally preceded by `./` or `~/`) or when the last
177
+ * few words include an action verb ("read", "open", "edit", etc.).
178
+ */
179
+ export declare function draftLooksLikePathContext(draft: string): boolean;
package/dist/metrics.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  /**
2
6
  * Source of truth for all completion modes. Both the type union (compile-time)
3
7
  * and the parser whitelist (runtime, in `bench.ts`) derive from this array so
@@ -150,4 +154,3 @@ export declare class MetricsLogger {
150
154
  * sees that *something* was there, without leaking content. SEC-27.
151
155
  */
152
156
  export declare function redactDebug(rec: DebugRecord): DebugRecord;
153
- //# sourceMappingURL=metrics.d.ts.map
@@ -1,3 +1,7 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  export interface PathIndexOptions {
2
6
  cap?: number;
3
7
  signal?: AbortSignal;
@@ -17,4 +21,3 @@ export interface PathIndex {
17
21
  * path completion this session".
18
22
  */
19
23
  export declare function buildPathIndex(cwd: string, opts?: PathIndexOptions): Promise<PathIndex | null>;
20
- //# sourceMappingURL=path-index.d.ts.map
@@ -1,3 +1,7 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  import type { PathIndex } from "./path-index.js";
2
6
  export interface PathToken {
3
7
  token: string;
@@ -38,4 +42,3 @@ export declare function extractPathPrefixToken(before: string): PathToken | null
38
42
  * (nothing to insert).
39
43
  */
40
44
  export declare function findPathPrefix(index: PathIndex, token: string, opts?: FindPathPrefixOptions | number): PathPrefixMatch | null;
41
- //# sourceMappingURL=path-matcher.d.ts.map
@@ -1,3 +1,7 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  /**
2
6
  * Stateful wrapper around `profile.ts` for the editor. Holds the in-memory
3
7
  * `ProfileIndex`, serializes writes, triggers periodic compaction, and
@@ -79,4 +83,3 @@ export declare class ProfileStore {
79
83
  }
80
84
  /** Exported for tests — surface compactor knob without re-exporting `profile.ts`. */
81
85
  export { DEFAULT_DECAY_DAYS };
82
- //# sourceMappingURL=profile-store.d.ts.map
package/dist/profile.d.ts CHANGED
@@ -1,23 +1,6 @@
1
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.
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
21
4
  */
22
5
  export declare const PROFILE_REL = ".pi/ghost-autocomplete/profile.jsonl";
23
6
  export declare const DEFAULT_MAX_BYTES: number;
@@ -182,4 +165,3 @@ export declare function compactRecords(records: ProfileRecord[], opts?: {
182
165
  }): ProfileRecord[];
183
166
  /** Parse `PI_GHOST_PROFILE_DECAY_DAYS`. Falls back to default when invalid. */
184
167
  export declare function parseDecayDaysEnv(raw: string | undefined): number;
185
- //# sourceMappingURL=profile.d.ts.map
@@ -1,3 +1,7 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  import type { CloudProviderConfig } from "../config.js";
2
6
  import type { GhostProvider, GhostRequest, StreamDelta } from "./types.js";
3
7
  export declare class CloudProvider implements GhostProvider {
@@ -16,4 +20,3 @@ export declare class CloudProvider implements GhostProvider {
16
20
  */
17
21
  predictStream(req: GhostRequest): AsyncIterable<StreamDelta>;
18
22
  }
19
- //# sourceMappingURL=cloud-provider.d.ts.map
@@ -1,3 +1,7 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  import type { LocalProviderConfig } from "../config.js";
2
6
  import type { GhostProvider, GhostRequest, StreamDelta } from "./types.js";
3
7
  export declare class LocalProvider implements GhostProvider {
@@ -15,4 +19,3 @@ export declare class LocalProvider implements GhostProvider {
15
19
  predictStream(req: GhostRequest): AsyncIterable<StreamDelta>;
16
20
  private callOpts;
17
21
  }
18
- //# sourceMappingURL=local-provider.d.ts.map
@@ -1,5 +1,10 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  import type { OpenAICompatProviderConfig } from "../config.js";
2
6
  import type { CandidateSet, GhostProvider, GhostRequest } from "./types.js";
7
+ import { type PromptIntent } from "../intent.js";
3
8
  export interface PreflightResult {
4
9
  ok: boolean;
5
10
  status?: number;
@@ -36,4 +41,22 @@ export declare class OpenAICompatProvider implements GhostProvider {
36
41
  private effectiveParallelN;
37
42
  private fireOne;
38
43
  }
39
- //# sourceMappingURL=openai-compat-provider.d.ts.map
44
+ /**
45
+ * Whether the conversation context should be included in the FIM prompt for a
46
+ * given intent. Pure + exported for direct testing. Set
47
+ * `PI_GHOST_FIM_CONTEXT_ALL_INTENTS=1` to force-include context for every
48
+ * intent (A/B against the empty-rate fix).
49
+ */
50
+ export declare function fimContextIncluded(intent: PromptIntent | undefined, allIntentsRaw: string | undefined): boolean;
51
+ /**
52
+ * Build the FIM prompt/suffix pair from the ghost request.
53
+ *
54
+ * Recent conversation messages are prepended as comments in the prompt so the
55
+ * model has context about what the user is working on — except for `prose` /
56
+ * `question` intents, where the context is dropped to avoid the empty-rate
57
+ * spike described on {@link FIM_CONTEXT_SUPPRESSED_INTENTS}.
58
+ */
59
+ export declare function buildFIMPrompt(req: GhostRequest, maxRecent: number): {
60
+ prompt: string;
61
+ suffix: string;
62
+ };
@@ -1,3 +1,7 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  import type { ProviderLatency } from "../metrics.js";
2
6
  import { type GhostProvider, type GhostRequest, type StreamDelta } from "./types.js";
3
7
  export interface RaceConfig {
@@ -94,4 +98,3 @@ export declare class RaceProvider implements GhostProvider {
94
98
  * all promises produce null (or throw). Never rejects.
95
99
  */
96
100
  export declare function firstNonNull<T>(promises: Array<Promise<T | null>>): Promise<T | null>;
97
- //# sourceMappingURL=race.d.ts.map
@@ -1,4 +1,9 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  import type { PreflightResult } from "./openai-compat-provider.js";
6
+ import type { PromptIntent } from "../intent.js";
2
7
  export interface GhostRequest {
3
8
  editorText: string;
4
9
  editorTextBeforeCursor: string;
@@ -15,6 +20,14 @@ export interface GhostRequest {
15
20
  }>;
16
21
  cwd: string;
17
22
  signal: AbortSignal;
23
+ /**
24
+ * Classified intent of the current prompt line. When set, providers use
25
+ * it to tailor the system prompt / FIM prompt so the model receives
26
+ * explicit signals about what kind of completion to produce.
27
+ * Undefined for backward compatibility (providers built before intent
28
+ * classification was added).
29
+ */
30
+ intent?: PromptIntent;
18
31
  }
19
32
  /**
20
33
  * One candidate completion. `avgLogprob` is the average per-token logprob if
@@ -110,4 +123,3 @@ export declare function wrapAsStream(provider: GhostProvider, req: GhostRequest)
110
123
  export declare function streamToText(stream: AsyncIterable<StreamDelta>, startedAt: number, out?: {
111
124
  ttftMs?: number;
112
125
  }): Promise<string | null>;
113
- //# sourceMappingURL=types.d.ts.map
@@ -1,3 +1,7 @@
1
+ /**
2
+ * SPDX-License-Identifier: SSPL-1.0
3
+ * SPDX-FileCopyrightText: 2025 Alessandro Pungitore <alessandro@pungitore.ch>
4
+ */
1
5
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
6
  import { type RecentMessage } from "./context-aggregator.js";
3
7
  /**
@@ -22,4 +26,3 @@ export declare function recentBoost(matchPath: string, recent: Set<string> | nul
22
26
  * assistant messages. Oldest-first.
23
27
  */
24
28
  export declare function getRoleWeightedRecent(ctx: ExtensionContext, userMax: number, assistantMax: number): RecentMessage[];
25
- //# sourceMappingURL=recent-paths.d.ts.map