pi-ghost-autocomplete 0.3.1 → 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 (83) hide show
  1. package/LICENSE +561 -0
  2. package/README.md +464 -236
  3. package/dist/bench-cli.js +1 -47
  4. package/dist/bench.d.ts +137 -5
  5. package/dist/bench.js +1 -241
  6. package/dist/config.d.ts +47 -1
  7. package/dist/context-aggregator.d.ts +18 -6
  8. package/dist/cycle-manager.d.ts +83 -0
  9. package/dist/entropy-stop.d.ts +105 -0
  10. package/dist/eval-dataset.d.ts +55 -0
  11. package/dist/fuzzy-matcher.d.ts +12 -1
  12. package/dist/ghost-editor.d.ts +332 -6
  13. package/dist/index.d.ts +21 -1
  14. package/dist/index.js +1 -210
  15. package/dist/intent.d.ts +179 -0
  16. package/dist/metrics.d.ts +103 -3
  17. package/dist/path-index.d.ts +4 -1
  18. package/dist/path-matcher.d.ts +13 -1
  19. package/dist/profile-store.d.ts +85 -0
  20. package/dist/profile.d.ts +167 -0
  21. package/dist/providers/cloud-provider.d.ts +14 -2
  22. package/dist/providers/local-provider.d.ts +12 -2
  23. package/dist/providers/openai-compat-provider.d.ts +35 -2
  24. package/dist/providers/race.d.ts +62 -2
  25. package/dist/providers/types.d.ts +109 -2
  26. package/dist/recent-paths.d.ts +4 -1
  27. package/dist/replay-cli.js +2 -0
  28. package/dist/replay.d.ts +102 -0
  29. package/package.json +90 -79
  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/config.d.ts.map +0 -1
  36. package/dist/config.js +0 -187
  37. package/dist/config.js.map +0 -1
  38. package/dist/context-aggregator.d.ts.map +0 -1
  39. package/dist/context-aggregator.js +0 -58
  40. package/dist/context-aggregator.js.map +0 -1
  41. package/dist/fuzzy-matcher.d.ts.map +0 -1
  42. package/dist/fuzzy-matcher.js +0 -160
  43. package/dist/fuzzy-matcher.js.map +0 -1
  44. package/dist/ghost-editor.d.ts.map +0 -1
  45. package/dist/ghost-editor.js +0 -445
  46. package/dist/ghost-editor.js.map +0 -1
  47. package/dist/index.d.ts.map +0 -1
  48. package/dist/index.js.map +0 -1
  49. package/dist/metrics.d.ts.map +0 -1
  50. package/dist/metrics.js +0 -98
  51. package/dist/metrics.js.map +0 -1
  52. package/dist/path-index.d.ts.map +0 -1
  53. package/dist/path-index.js +0 -148
  54. package/dist/path-index.js.map +0 -1
  55. package/dist/path-matcher.d.ts.map +0 -1
  56. package/dist/path-matcher.js +0 -85
  57. package/dist/path-matcher.js.map +0 -1
  58. package/dist/providers/cloud-provider.d.ts.map +0 -1
  59. package/dist/providers/cloud-provider.js +0 -52
  60. package/dist/providers/cloud-provider.js.map +0 -1
  61. package/dist/providers/local-provider.d.ts.map +0 -1
  62. package/dist/providers/local-provider.js +0 -36
  63. package/dist/providers/local-provider.js.map +0 -1
  64. package/dist/providers/openai-compat-provider.d.ts.map +0 -1
  65. package/dist/providers/openai-compat-provider.js +0 -128
  66. package/dist/providers/openai-compat-provider.js.map +0 -1
  67. package/dist/providers/openai-completions-runner.d.ts +0 -28
  68. package/dist/providers/openai-completions-runner.d.ts.map +0 -1
  69. package/dist/providers/openai-completions-runner.js +0 -46
  70. package/dist/providers/openai-completions-runner.js.map +0 -1
  71. package/dist/providers/race.d.ts.map +0 -1
  72. package/dist/providers/race.js +0 -128
  73. package/dist/providers/race.js.map +0 -1
  74. package/dist/providers/truncate.d.ts +0 -7
  75. package/dist/providers/truncate.d.ts.map +0 -1
  76. package/dist/providers/truncate.js +0 -39
  77. package/dist/providers/truncate.js.map +0 -1
  78. package/dist/providers/types.d.ts.map +0 -1
  79. package/dist/providers/types.js +0 -2
  80. package/dist/providers/types.js.map +0 -1
  81. package/dist/recent-paths.d.ts.map +0 -1
  82. package/dist/recent-paths.js +0 -114
  83. package/dist/recent-paths.js.map +0 -1
@@ -1,148 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- const DEFAULT_CAP = 20_000;
3
- /**
4
- * Build a deterministic path index rooted at the Git toplevel of `cwd`.
5
- *
6
- * Returns null when Git is unavailable, `cwd` is outside any repo, or the
7
- * underlying commands fail. Callers should treat null as "no deterministic
8
- * path completion this session".
9
- */
10
- export async function buildPathIndex(cwd, opts = {}) {
11
- const cap = opts.cap ?? DEFAULT_CAP;
12
- const root = await gitToplevel(cwd, opts.signal);
13
- if (!root)
14
- return null;
15
- const all = await gitLsFiles(root, opts.signal);
16
- if (!all)
17
- return null;
18
- let files;
19
- let capExceeded = false;
20
- if (all.length > cap) {
21
- capExceeded = true;
22
- const rel = relPosix(root, cwd);
23
- const subtreePrefix = rel === "" ? "" : `${rel}/`;
24
- files = all.filter((f) => subtreePrefix === "" || f.startsWith(subtreePrefix));
25
- if (files.length > cap)
26
- files = files.slice(0, cap);
27
- }
28
- else {
29
- files = all;
30
- }
31
- files.sort();
32
- return new PathIndexImpl(root, cwd, files, capExceeded);
33
- }
34
- class PathIndexImpl {
35
- root;
36
- cwd;
37
- files;
38
- capExceeded;
39
- constructor(root, cwd, files, capExceeded) {
40
- this.root = root;
41
- this.cwd = cwd;
42
- this.files = files;
43
- this.capExceeded = capExceeded;
44
- }
45
- prefixMatches(token, limit) {
46
- if (!token || limit <= 0)
47
- return [];
48
- const start = lowerBound(this.files, token);
49
- const out = [];
50
- for (let i = start; i < this.files.length && out.length < limit; i++) {
51
- const f = this.files[i];
52
- if (!f || !f.startsWith(token))
53
- break;
54
- out.push(f);
55
- }
56
- return out;
57
- }
58
- }
59
- function lowerBound(arr, target) {
60
- let lo = 0;
61
- let hi = arr.length;
62
- while (lo < hi) {
63
- const mid = (lo + hi) >>> 1;
64
- const v = arr[mid];
65
- if (v !== undefined && v < target)
66
- lo = mid + 1;
67
- else
68
- hi = mid;
69
- }
70
- return lo;
71
- }
72
- function relPosix(root, cwd) {
73
- const r = normSlashes(root);
74
- const c = normSlashes(cwd);
75
- if (c === r)
76
- return "";
77
- const prefix = r.endsWith("/") ? r : `${r}/`;
78
- if (c.startsWith(prefix))
79
- return c.slice(prefix.length);
80
- return "";
81
- }
82
- function normSlashes(p) {
83
- return p.replace(/\\/g, "/").replace(/\/+$/, "");
84
- }
85
- async function gitToplevel(cwd, signal) {
86
- const res = await runGit(["rev-parse", "--show-toplevel"], cwd, signal);
87
- if (!res)
88
- return null;
89
- const line = res.split(/\r?\n/)[0]?.trim();
90
- if (!line)
91
- return null;
92
- return normSlashes(line);
93
- }
94
- async function gitLsFiles(root, signal) {
95
- const res = await runGit(["ls-files", "-z"], root, signal);
96
- if (res === null)
97
- return null;
98
- if (res === "")
99
- return [];
100
- return res.split("\0").filter((s) => s.length > 0);
101
- }
102
- function runGit(args, cwd, signal) {
103
- return new Promise((resolve) => {
104
- let proc;
105
- try {
106
- proc = spawn("git", args, { cwd, windowsHide: true });
107
- }
108
- catch {
109
- resolve(null);
110
- return;
111
- }
112
- let out = "";
113
- let err = false;
114
- const onAbort = () => {
115
- try {
116
- proc.kill();
117
- }
118
- catch {
119
- // proc may already be dead
120
- }
121
- };
122
- if (signal) {
123
- if (signal.aborted)
124
- onAbort();
125
- else
126
- signal.addEventListener("abort", onAbort, { once: true });
127
- }
128
- proc.stdout?.on("data", (chunk) => {
129
- out += chunk.toString("utf8");
130
- });
131
- proc.on("error", () => {
132
- err = true;
133
- resolve(null);
134
- });
135
- proc.on("close", (code) => {
136
- if (signal)
137
- signal.removeEventListener("abort", onAbort);
138
- if (err)
139
- return;
140
- if (code !== 0) {
141
- resolve(null);
142
- return;
143
- }
144
- resolve(out);
145
- });
146
- });
147
- }
148
- //# sourceMappingURL=path-index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"path-index.js","sourceRoot":"","sources":["../src/path-index.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
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;CACjC;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,CA+BxB"}
@@ -1,85 +0,0 @@
1
- import { recentBoost } from "./recent-paths.js";
2
- const PATH_CHAR = /[A-Za-z0-9_./@\-]/;
3
- const QUOTE_CHARS = new Set(['"', "'", "`"]);
4
- /**
5
- * Extract a path-like token from the end of `before` (text before the cursor).
6
- * Returns null when no path-prefix mode is applicable: a token is only
7
- * eligible when it contains a `/` (path-prefix mode is structural, not fuzzy).
8
- *
9
- * `insideQuote` is true when the character immediately preceding the token is
10
- * a quote or backtick; callers can still trust the token in that case.
11
- */
12
- export function extractPathPrefixToken(before) {
13
- if (!before)
14
- return null;
15
- let end = before.length;
16
- let start = end;
17
- while (start > 0) {
18
- const ch = before[start - 1];
19
- if (!ch || !PATH_CHAR.test(ch))
20
- break;
21
- start--;
22
- }
23
- if (start === end)
24
- return null;
25
- const token = before.slice(start, end);
26
- if (!token.includes("/"))
27
- return null;
28
- const prev = start > 0 ? before[start - 1] : undefined;
29
- const insideQuote = prev !== undefined && QUOTE_CHARS.has(prev);
30
- return { token, insideQuote };
31
- }
32
- /**
33
- * Pick the best path-prefix match for `token`. Strategy: enumerate matches
34
- * (capped), prefer files inside `cwdRel` subtree, then shorter paths.
35
- *
36
- * Returns null when the token has no matches or matches itself exactly
37
- * (nothing to insert).
38
- */
39
- export function findPathPrefix(index, token, opts = {}) {
40
- // Back-compat: legacy callers pass a numeric `limit`.
41
- const o = typeof opts === "number" ? { limit: opts } : opts;
42
- const limit = o.limit ?? 64;
43
- const recent = o.recentPaths ?? null;
44
- // Normalize a leading `./` — extractPathPrefixToken preserves it from the
45
- // user's text (e.g. "./src/con") but git ls-files entries never start with
46
- // `./`, so the prefix lookup would otherwise miss every cwd-relative entry.
47
- const lookupToken = token.startsWith("./") ? token.slice(2) : token;
48
- if (!lookupToken)
49
- return null;
50
- const matches = index.prefixMatches(lookupToken, limit);
51
- if (matches.length === 0)
52
- return null;
53
- const cwdRel = relSubtree(index.root, index.cwd);
54
- let best = null;
55
- let bestScore = -Infinity;
56
- let bestBoost = 0;
57
- for (const m of matches) {
58
- const inSub = cwdRel === "" || m.startsWith(cwdRel);
59
- const rb = recentBoost(m, recent);
60
- // Lex-rank: subtree dominates, then recent-mention boost, then short.
61
- const score = (inSub ? 1_000_000_000 : 0) + rb * 1_000_000 - m.length;
62
- if (score > bestScore) {
63
- bestScore = score;
64
- best = m;
65
- bestBoost = rb;
66
- }
67
- }
68
- if (!best)
69
- return null;
70
- const suffix = best.slice(lookupToken.length);
71
- if (!suffix)
72
- return null;
73
- return { match: best, suffix, score: 100 + bestBoost };
74
- }
75
- function relSubtree(root, cwd) {
76
- const r = root.replace(/\\/g, "/").replace(/\/+$/, "");
77
- const c = cwd.replace(/\\/g, "/").replace(/\/+$/, "");
78
- if (c === r)
79
- return "";
80
- const prefix = `${r}/`;
81
- if (c.startsWith(prefix))
82
- return `${c.slice(prefix.length)}/`;
83
- return "";
84
- }
85
- //# sourceMappingURL=path-matcher.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"path-matcher.js","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-provider.d.ts","sourceRoot":"","sources":["../../src/providers/cloud-provider.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,qBAAa,aAAc,YAAW,aAAa;IAGtC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,IAAI,iBAAiB;gBAED,MAAM,EAAE,mBAAmB;IAExD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAEK,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAyBxD"}
@@ -1,52 +0,0 @@
1
- import { complete, getEnvApiKey, getModels, } from "@earendil-works/pi-ai";
2
- import { buildPromptMessages, sanitizeCompletion } from "./truncate.js";
3
- export class CloudProvider {
4
- config;
5
- name = "ghost-cloud";
6
- constructor(config) {
7
- this.config = config;
8
- }
9
- get debounceMs() {
10
- return this.config.debounceMs;
11
- }
12
- async predict(req) {
13
- const apiKey = this.config.apiKey ?? getEnvApiKey(this.config.provider);
14
- if (!apiKey)
15
- return null;
16
- const model = resolveModel(this.config.provider, this.config.modelId);
17
- if (!model)
18
- return null;
19
- const { systemPrompt, user } = buildPromptMessages(req, this.config.maxRecentMessages);
20
- const messages = [{ role: "user", content: user, timestamp: Date.now() }];
21
- const ctx = { systemPrompt, messages };
22
- const result = await complete(model, ctx, {
23
- signal: req.signal,
24
- temperature: 0.2,
25
- maxTokens: this.config.maxTokens,
26
- apiKey,
27
- });
28
- if (result.stopReason === "error" || result.stopReason === "aborted")
29
- return null;
30
- const text = result.content
31
- .filter((c) => c.type === "text")
32
- .map((c) => c.text)
33
- .join("");
34
- return sanitizeCompletion(text, req.editorTextBeforeCursor, 200);
35
- }
36
- }
37
- /**
38
- * Look up a model by id from pi-ai's registry. Returns null if the provider
39
- * has no model with that id; the caller drops the prediction silently.
40
- *
41
- * Avoids `getModel(provider, id as never)` — the registry's typed lookup
42
- * requires a literal id and would otherwise need an unsafe cast.
43
- */
44
- function resolveModel(provider, modelId) {
45
- const models = getModels(provider);
46
- for (const m of models) {
47
- if (m.id === modelId)
48
- return m;
49
- }
50
- return null;
51
- }
52
- //# sourceMappingURL=cloud-provider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-provider.js","sourceRoot":"","sources":["../../src/providers/cloud-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,QAAQ,EACR,YAAY,EACZ,SAAS,GAMT,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxE,MAAM,OAAO,aAAa;IAGI;IAFpB,IAAI,GAAG,aAAa,CAAC;IAE9B,YAA6B,MAA2B;QAA3B,WAAM,GAAN,MAAM,CAAqB;IAAG,CAAC;IAE5D,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAiB;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtE,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAExB,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACvF,MAAM,QAAQ,GAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACrF,MAAM,GAAG,GAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;QAEhD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE;YACzC,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,WAAW,EAAE,GAAG;YAChB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;YAChC,MAAM;SACN,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QAClF,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO;aACzB,MAAM,CAAC,CAAC,CAAC,EAAuC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;aACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,IAAI,CAAC,EAAE,CAAC,CAAC;QACX,OAAO,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;IAClE,CAAC;CACD;AAED;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,QAAuB,EAAE,OAAe;IAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO;YAAE,OAAO,CAAe,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"local-provider.d.ts","sourceRoot":"","sources":["../../src/providers/local-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI9D,qBAAa,aAAc,YAAW,aAAa;IAGtC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,IAAI,iBAAiB;gBAED,MAAM,EAAE,mBAAmB;IAExD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAEK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAY7B,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAWxD"}
@@ -1,36 +0,0 @@
1
- import { runOpenAICompletion, trimSlash } from "./openai-completions-runner.js";
2
- const DEFAULT_CONTEXT_WINDOW = 8192;
3
- export class LocalProvider {
4
- config;
5
- name = "ghost-local";
6
- constructor(config) {
7
- this.config = config;
8
- }
9
- get debounceMs() {
10
- return this.config.debounceMs;
11
- }
12
- async preflight() {
13
- try {
14
- const ctrl = new AbortController();
15
- const timeout = setTimeout(() => ctrl.abort(), 750);
16
- const res = await fetch(`${trimSlash(this.config.baseUrl)}/api/tags`, { signal: ctrl.signal });
17
- clearTimeout(timeout);
18
- return res.ok;
19
- }
20
- catch {
21
- return false;
22
- }
23
- }
24
- async predict(req) {
25
- return runOpenAICompletion(req, {
26
- baseUrl: `${trimSlash(this.config.baseUrl)}/v1`,
27
- apiKey: "ollama",
28
- modelId: this.config.modelId,
29
- providerTag: "ollama",
30
- maxTokens: this.config.maxTokens,
31
- maxRecentMessages: this.config.maxRecentMessages,
32
- contextWindow: this.config.contextWindow ?? DEFAULT_CONTEXT_WINDOW,
33
- });
34
- }
35
- }
36
- //# sourceMappingURL=local-provider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"local-provider.js","sourceRoot":"","sources":["../../src/providers/local-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAGhF,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAEpC,MAAM,OAAO,aAAa;IAGI;IAFpB,IAAI,GAAG,aAAa,CAAC;IAE9B,YAA6B,MAA2B;QAA3B,WAAM,GAAN,MAAM,CAAqB;IAAG,CAAC;IAE5D,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,SAAS;QACd,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;YACpD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/F,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,OAAO,GAAG,CAAC,EAAE,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAiB;QAC9B,OAAO,mBAAmB,CAAC,GAAG,EAAE;YAC/B,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK;YAC/C,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;YAC5B,WAAW,EAAE,QAAQ;YACrB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;YAChC,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC,iBAAiB;YAChD,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,sBAAsB;SAClE,CAAC,CAAC;IACJ,CAAC;CACD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"openai-compat-provider.d.ts","sourceRoot":"","sources":["../../src/providers/openai-compat-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI9D,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,YAAW,aAAa;IAG7C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEO,MAAM,EAAE,0BAA0B;IAI/D,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC;IA+BrC,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAgCxD"}
@@ -1,128 +0,0 @@
1
- import { sanitizeCompletion } from "./truncate.js";
2
- const PREFLIGHT_TIMEOUT_MS = 5_000;
3
- /**
4
- * Provider for FIM-completions backends (e.g. Mercury Edit 2 by Inception
5
- * Labs). Calls `/fim/completions` with `prompt`/`suffix` and returns the
6
- * raw text completion.
7
- *
8
- * A {@link preflight} method validates the API key at startup so the host
9
- * can surface configuration errors early instead of silently dropping
10
- * every prediction.
11
- */
12
- export class OpenAICompatProvider {
13
- config;
14
- name;
15
- constructor(config) {
16
- this.config = config;
17
- this.name = `ghost-${config.providerName}`;
18
- }
19
- get debounceMs() {
20
- return this.config.debounceMs;
21
- }
22
- /**
23
- * Validate the API key with a minimal FIM request. A successful
24
- * response (even an empty completion) proves auth + connectivity.
25
- */
26
- async preflight() {
27
- const apiKey = this.config.apiKey;
28
- if (!apiKey)
29
- return { ok: false, message: "no API key configured" };
30
- const ctrl = new AbortController();
31
- const timeout = setTimeout(() => ctrl.abort(), PREFLIGHT_TIMEOUT_MS);
32
- try {
33
- const res = await fetch(`${trimSlash(this.config.baseUrl)}/fim/completions`, {
34
- method: "POST",
35
- headers: {
36
- "Content-Type": "application/json",
37
- Authorization: `Bearer ${apiKey}`,
38
- },
39
- body: JSON.stringify({
40
- model: this.config.modelId,
41
- prompt: " ",
42
- max_tokens: 1,
43
- }),
44
- signal: ctrl.signal,
45
- });
46
- clearTimeout(timeout);
47
- if (res.ok)
48
- return { ok: true, status: res.status, message: "ok" };
49
- return { ok: false, status: res.status, message: describeHttpError(res.status) };
50
- }
51
- catch (err) {
52
- clearTimeout(timeout);
53
- const aborted = err?.name === "AbortError";
54
- if (aborted)
55
- return { ok: false, message: "endpoint timed out" };
56
- return { ok: false, message: "endpoint unreachable" };
57
- }
58
- }
59
- async predict(req) {
60
- const apiKey = this.config.apiKey;
61
- if (!apiKey)
62
- return null;
63
- const { prompt, suffix } = buildFIMPrompt(req, this.config.maxRecentMessages);
64
- try {
65
- const res = await fetch(`${trimSlash(this.config.baseUrl)}/fim/completions`, {
66
- method: "POST",
67
- headers: {
68
- "Content-Type": "application/json",
69
- Authorization: `Bearer ${apiKey}`,
70
- },
71
- body: JSON.stringify({
72
- model: this.config.modelId,
73
- prompt,
74
- suffix,
75
- max_tokens: this.config.maxTokens,
76
- temperature: 0.2,
77
- }),
78
- signal: req.signal,
79
- });
80
- if (!res.ok)
81
- return null;
82
- const data = (await res.json());
83
- const text = data.choices?.[0]?.text ?? "";
84
- return sanitizeCompletion(text, req.editorTextBeforeCursor, 200);
85
- }
86
- catch {
87
- return null;
88
- }
89
- }
90
- }
91
- /**
92
- * Build the FIM prompt/suffix pair from the ghost request.
93
- *
94
- * Recent conversation messages are prepended as comments in the prompt
95
- * so the model has context about what the user is working on.
96
- */
97
- function buildFIMPrompt(req, maxRecent) {
98
- const recent = req.recentMessages
99
- .slice(-maxRecent)
100
- .map((m) => `# ${m.role}: ${truncate(m.text, 280)}`)
101
- .join("\n");
102
- const ctx = recent ? `${recent}\n\n` : "";
103
- // Split the editor text at cursor to form prompt (before) / suffix (after).
104
- // Ghost autocomplete only fires when cursor is at end, so suffix is empty
105
- // in the common case — but we handle the general case for correctness.
106
- const before = req.editorTextBeforeCursor;
107
- const after = req.editorText.slice(req.editorTextBeforeCursor.length);
108
- return {
109
- prompt: `${ctx}${before}`,
110
- suffix: after,
111
- };
112
- }
113
- function truncate(s, n) {
114
- return s.length > n ? `${s.slice(0, n)}…` : s;
115
- }
116
- function trimSlash(url) {
117
- return url.endsWith("/") ? url.slice(0, -1) : url;
118
- }
119
- function describeHttpError(status) {
120
- switch (status) {
121
- case 401: return "invalid API key (401 Unauthorized)";
122
- case 402: return "API key has no credits — please top up (402 Payment Required)";
123
- case 403: return "API key not permitted (403 Forbidden)";
124
- case 429: return "rate limited (429 Too Many Requests)";
125
- default: return `HTTP ${status}`;
126
- }
127
- }
128
- //# sourceMappingURL=openai-compat-provider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openai-compat-provider.js","sourceRoot":"","sources":["../../src/providers/openai-compat-provider.ts"],"names":[],"mappings":"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"}
@@ -1,28 +0,0 @@
1
- import type { GhostRequest } from "./types.js";
2
- export interface OpenAICompletionsCallOpts {
3
- baseUrl: string;
4
- apiKey: string;
5
- modelId: string;
6
- /**
7
- * Metadata tag for pi-ai's `Model.provider`. Cosmetic for logs — the
8
- * actual endpoint is driven by `baseUrl`. Accepts any string; cast to
9
- * `KnownProvider` at the call site since the field is purely descriptive.
10
- */
11
- providerTag: string;
12
- maxTokens: number;
13
- maxRecentMessages: number;
14
- contextWindow: number;
15
- }
16
- /**
17
- * Shared OpenAI-completions request path used by both {@link LocalProvider}
18
- * and {@link OpenAICompatProvider}. Builds the pi-ai model record, sends one
19
- * `complete()` call with the user's abort signal, and returns a sanitized
20
- * completion string (or null when the call aborts/errors/produces nothing
21
- * usable).
22
- *
23
- * Kept as a free function rather than a base class to avoid one-method
24
- * inheritance.
25
- */
26
- export declare function runOpenAICompletion(req: GhostRequest, opts: OpenAICompletionsCallOpts): Promise<string | null>;
27
- export declare function trimSlash(url: string): string;
28
- //# sourceMappingURL=openai-completions-runner.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openai-completions-runner.d.ts","sourceRoot":"","sources":["../../src/providers/openai-completions-runner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,yBAAyB;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACxC,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,yBAAyB,GAC7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+BxB;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C"}
@@ -1,46 +0,0 @@
1
- import { complete } from "@earendil-works/pi-ai";
2
- import { buildPromptMessages, sanitizeCompletion } from "./truncate.js";
3
- /**
4
- * Shared OpenAI-completions request path used by both {@link LocalProvider}
5
- * and {@link OpenAICompatProvider}. Builds the pi-ai model record, sends one
6
- * `complete()` call with the user's abort signal, and returns a sanitized
7
- * completion string (or null when the call aborts/errors/produces nothing
8
- * usable).
9
- *
10
- * Kept as a free function rather than a base class to avoid one-method
11
- * inheritance.
12
- */
13
- export async function runOpenAICompletion(req, opts) {
14
- const model = {
15
- id: opts.modelId,
16
- name: opts.modelId,
17
- api: "openai-completions",
18
- provider: opts.providerTag,
19
- baseUrl: trimSlash(opts.baseUrl),
20
- reasoning: false,
21
- input: ["text"],
22
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
23
- contextWindow: opts.contextWindow,
24
- maxTokens: opts.maxTokens,
25
- };
26
- const { systemPrompt, user } = buildPromptMessages(req, opts.maxRecentMessages);
27
- const messages = [{ role: "user", content: user, timestamp: Date.now() }];
28
- const ctx = { systemPrompt, messages };
29
- const result = await complete(model, ctx, {
30
- signal: req.signal,
31
- temperature: 0.2,
32
- maxTokens: opts.maxTokens,
33
- apiKey: opts.apiKey,
34
- });
35
- if (result.stopReason === "error" || result.stopReason === "aborted")
36
- return null;
37
- const text = result.content
38
- .filter((c) => c.type === "text")
39
- .map((c) => c.text)
40
- .join("");
41
- return sanitizeCompletion(text, req.editorTextBeforeCursor, 200);
42
- }
43
- export function trimSlash(url) {
44
- return url.endsWith("/") ? url.slice(0, -1) : url;
45
- }
46
- //# sourceMappingURL=openai-completions-runner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openai-completions-runner.js","sourceRoot":"","sources":["../../src/providers/openai-completions-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA8D,MAAM,uBAAuB,CAAC;AAC7G,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAkBxE;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,GAAiB,EACjB,IAA+B;IAE/B,MAAM,KAAK,GAAgC;QAC1C,EAAE,EAAE,IAAI,CAAC,OAAO;QAChB,IAAI,EAAE,IAAI,CAAC,OAAO;QAClB,GAAG,EAAE,oBAAoB;QACzB,QAAQ,EAAE,IAAI,CAAC,WAA4B;QAC3C,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;QAChC,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;QAC1D,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,SAAS,EAAE,IAAI,CAAC,SAAS;KACzB,CAAC;IAEF,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAChF,MAAM,QAAQ,GAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrF,MAAM,GAAG,GAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;IAEhD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE;QACzC,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,WAAW,EAAE,GAAG;QAChB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;KACnB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAClF,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO;SACzB,MAAM,CAAC,CAAC,CAAC,EAAuC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,OAAO,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACpC,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACnD,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"race.d.ts","sourceRoot":"","sources":["../../src/providers/race.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,UAAU;IAC1B,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACzB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,qBAAa,YAAa,YAAW,aAAa;IAMhD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IANrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,SAAS,CAA0B;gBAGzB,OAAO,EAAE,aAAa,EAAE,EACxB,GAAG,EAAE,UAAU;IAKjC,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,gBAAgB,IAAI,SAAS,GAAG,IAAI;IAM9B,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;YA6C1C,SAAS;CA8BvB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAyBrF"}