openlore 2.0.10 → 2.0.12

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 (72) hide show
  1. package/dist/cli/commands/generate.d.ts.map +1 -1
  2. package/dist/cli/commands/generate.js +3 -2
  3. package/dist/cli/commands/generate.js.map +1 -1
  4. package/dist/cli/commands/mcp.d.ts.map +1 -1
  5. package/dist/cli/commands/mcp.js +106 -244
  6. package/dist/cli/commands/mcp.js.map +1 -1
  7. package/dist/cli/commands/serve.d.ts +49 -0
  8. package/dist/cli/commands/serve.d.ts.map +1 -0
  9. package/dist/cli/commands/serve.js +450 -0
  10. package/dist/cli/commands/serve.js.map +1 -0
  11. package/dist/cli/commands/setup.d.ts.map +1 -1
  12. package/dist/cli/commands/setup.js +32 -8
  13. package/dist/cli/commands/setup.js.map +1 -1
  14. package/dist/cli/index.js +2 -0
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/core/analyzer/artifact-generator.d.ts +1 -13
  17. package/dist/core/analyzer/artifact-generator.d.ts.map +1 -1
  18. package/dist/core/analyzer/artifact-generator.js +5 -23
  19. package/dist/core/analyzer/artifact-generator.js.map +1 -1
  20. package/dist/core/analyzer/call-graph.d.ts.map +1 -1
  21. package/dist/core/analyzer/call-graph.js +19 -10
  22. package/dist/core/analyzer/call-graph.js.map +1 -1
  23. package/dist/core/analyzer/file-walker.d.ts.map +1 -1
  24. package/dist/core/analyzer/file-walker.js +9 -1
  25. package/dist/core/analyzer/file-walker.js.map +1 -1
  26. package/dist/core/analyzer/test-file.d.ts +19 -0
  27. package/dist/core/analyzer/test-file.d.ts.map +1 -0
  28. package/dist/core/analyzer/test-file.js +29 -0
  29. package/dist/core/analyzer/test-file.js.map +1 -0
  30. package/dist/core/decisions/consolidator.d.ts.map +1 -1
  31. package/dist/core/decisions/consolidator.js +7 -1
  32. package/dist/core/decisions/consolidator.js.map +1 -1
  33. package/dist/core/decisions/syncer.js +8 -0
  34. package/dist/core/decisions/syncer.js.map +1 -1
  35. package/dist/core/services/edge-store.d.ts.map +1 -1
  36. package/dist/core/services/edge-store.js +3 -0
  37. package/dist/core/services/edge-store.js.map +1 -1
  38. package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -1
  39. package/dist/core/services/mcp-handlers/analysis.js +2 -1
  40. package/dist/core/services/mcp-handlers/analysis.js.map +1 -1
  41. package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -1
  42. package/dist/core/services/mcp-handlers/semantic.js +7 -3
  43. package/dist/core/services/mcp-handlers/semantic.js.map +1 -1
  44. package/dist/core/services/mcp-handlers/utils.d.ts +13 -0
  45. package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -1
  46. package/dist/core/services/mcp-handlers/utils.js +49 -0
  47. package/dist/core/services/mcp-handlers/utils.js.map +1 -1
  48. package/dist/core/services/mcp-watcher.d.ts +9 -0
  49. package/dist/core/services/mcp-watcher.d.ts.map +1 -1
  50. package/dist/core/services/mcp-watcher.js +15 -5
  51. package/dist/core/services/mcp-watcher.js.map +1 -1
  52. package/dist/core/services/serve-client.d.ts +40 -0
  53. package/dist/core/services/serve-client.d.ts.map +1 -0
  54. package/dist/core/services/serve-client.js +115 -0
  55. package/dist/core/services/serve-client.js.map +1 -0
  56. package/dist/core/services/tool-dispatch.d.ts +35 -0
  57. package/dist/core/services/tool-dispatch.d.ts.map +1 -0
  58. package/dist/core/services/tool-dispatch.js +253 -0
  59. package/dist/core/services/tool-dispatch.js.map +1 -0
  60. package/dist/pi/extension.d.ts +62 -0
  61. package/dist/pi/extension.d.ts.map +1 -0
  62. package/dist/pi/extension.js +508 -0
  63. package/dist/pi/extension.js.map +1 -0
  64. package/examples/pi/README.md +98 -0
  65. package/package.json +16 -2
  66. package/skills/openlore-orient/README.md +73 -0
  67. package/skills/openlore-orient/SKILL.md +73 -0
  68. package/skills/openlore-orient/examples/example-orient-output.json +103 -0
  69. package/skills/openlore-orient/examples/example-task-prompt.md +26 -0
  70. package/skills/openlore-orient/scripts/orient-via-mcp.mjs +124 -0
  71. package/skills/openlore-orient/scripts/orient.ps1 +36 -0
  72. package/skills/openlore-orient/scripts/orient.sh +28 -0
@@ -0,0 +1,508 @@
1
+ /**
2
+ * openlore Pi extension — src/pi/extension.ts
3
+ *
4
+ * Compiled to dist/pi/extension.js and declared in package.json "pi" field so
5
+ * `pi install npm:openlore` drops it into the Pi extension registry automatically.
6
+ *
7
+ * Two halves:
8
+ * C — context injection (before_agent_start): model starts grounded with the
9
+ * architecture digest + spec index + task-grounded orient call, so weak
10
+ * tool-callers benefit even without calling a tool.
11
+ * B — native tools (registerTool): navigation surface for on-demand structural
12
+ * queries, each round-tripping to the warm daemon via fetch.
13
+ *
14
+ * Uses ctx.mode (0.78.1+): full injection in tui/rpc (interactive), none in
15
+ * json/print (one-shot). rpc = headless interactive over stdin/stdout (IDE,
16
+ * custom UI) — same injection needs as tui.
17
+ *
18
+ * Config onboarding: runs on first session when .openlore/config.json is absent;
19
+ * also available anytime via the openlore_configure tool.
20
+ */
21
+ import { StringEnum } from '@earendil-works/pi-ai';
22
+ import { Type } from 'typebox';
23
+ import { spawn } from 'node:child_process';
24
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
25
+ import { join } from 'node:path';
26
+ import { homedir } from 'node:os';
27
+ const OPENLORE_DIR = '.openlore';
28
+ /** Treat a config as absent unless it has the minimum viable fields. */
29
+ export function isUsableConfig(raw) {
30
+ return !!raw && typeof raw === 'object' && typeof raw.generation?.provider === 'string';
31
+ }
32
+ export async function readConfig(cwd) {
33
+ try {
34
+ const raw = JSON.parse(await readFile(join(cwd, OPENLORE_DIR, 'config.json'), 'utf-8'));
35
+ return isUsableConfig(raw) ? raw : null;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ async function writeConfig(cwd, config) {
42
+ await mkdir(join(cwd, OPENLORE_DIR), { recursive: true });
43
+ await writeFile(join(cwd, OPENLORE_DIR, 'config.json'), JSON.stringify(config, null, 2) + '\n', 'utf-8');
44
+ }
45
+ const PROVIDERS = [
46
+ 'anthropic', 'openai', 'openai-compat', 'gemini',
47
+ 'copilot', 'claude-code', 'gemini-cli', 'mistral-vibe', 'cursor-agent',
48
+ ];
49
+ const PROVIDER_MODEL_DEFAULTS = {
50
+ anthropic: 'claude-sonnet-4-6',
51
+ openai: 'gpt-4o',
52
+ 'openai-compat': '',
53
+ gemini: 'gemini-2.0-flash',
54
+ copilot: 'gpt-4o',
55
+ 'claude-code': 'claude-sonnet-4-6',
56
+ 'gemini-cli': 'gemini-2.0-flash',
57
+ 'mistral-vibe': 'codestral-latest',
58
+ 'cursor-agent': '',
59
+ };
60
+ const SYSTEM_AUTH_PROVIDERS = new Set(['copilot', 'claude-code', 'gemini-cli', 'mistral-vibe', 'cursor-agent']);
61
+ const PROVIDER_ENV_VARS = {
62
+ anthropic: 'ANTHROPIC_API_KEY',
63
+ openai: 'OPENAI_API_KEY',
64
+ 'openai-compat': 'OPENAI_COMPAT_API_KEY',
65
+ copilot: 'COPILOT_API_KEY',
66
+ };
67
+ /**
68
+ * Build the `/v1/models` URL for a provider base URL, tolerating a trailing
69
+ * slash and an already-present `/v1` segment (e.g. https://api.mistral.ai/v1/).
70
+ */
71
+ export function modelsUrl(baseUrl) {
72
+ const base = baseUrl.replace(/\/+$/, '').replace(/\/v1$/, '');
73
+ return `${base}/v1/models`;
74
+ }
75
+ /** Strip the trailing " *" current-value marker added to select-list entries. */
76
+ export function stripMarker(label) {
77
+ return label.replace(/ \*$/, '');
78
+ }
79
+ async function fetchModels(baseUrl, apiKey) {
80
+ try {
81
+ const res = await fetch(modelsUrl(baseUrl), {
82
+ headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
83
+ signal: AbortSignal.timeout(1500),
84
+ });
85
+ if (!res.ok)
86
+ return null;
87
+ const data = await res.json();
88
+ return data.data?.map((m) => m.id).sort() ?? null;
89
+ }
90
+ catch {
91
+ return null;
92
+ }
93
+ }
94
+ // ── Config wizard ─────────────────────────────────────────────────────────────
95
+ async function configureGeneration(ui, existing) {
96
+ const existingProvider = existing?.provider;
97
+ const providerList = existingProvider
98
+ ? [`${existingProvider} *`, ...PROVIDERS.filter((p) => p !== existingProvider)]
99
+ : PROVIDERS;
100
+ const selectedProvider = await ui.select('LLM provider', providerList) ?? providerList[0];
101
+ const provider = stripMarker(selectedProvider);
102
+ let baseUrl = existing?.openaiCompatBaseUrl;
103
+ let skipSslVerify = existing?.skipSslVerify ?? false;
104
+ let apiKey;
105
+ if (provider === 'openai-compat') {
106
+ const urlTitle = baseUrl ? `Base URL (current: ${baseUrl})` : 'Base URL';
107
+ const rawUrl = await ui.input(urlTitle, 'http://localhost:11434');
108
+ baseUrl = rawUrl || baseUrl || '';
109
+ skipSslVerify = await ui.confirm('Skip SSL verification?', 'Only enable for local servers with self-signed certificates (e.g. Ollama on localhost). Do NOT enable for remote/cloud endpoints.');
110
+ }
111
+ if (!SYSTEM_AUTH_PROVIDERS.has(provider) && PROVIDER_ENV_VARS[provider]) {
112
+ apiKey = process.env[PROVIDER_ENV_VARS[provider]];
113
+ if (!apiKey) {
114
+ ui.notify(`API key: set ${PROVIDER_ENV_VARS[provider]} in your shell environment`, 'warning');
115
+ }
116
+ }
117
+ let model;
118
+ const apiBase = provider === 'openai' ? 'https://api.openai.com' : (baseUrl ?? '');
119
+ const models = apiBase ? await fetchModels(apiBase, apiKey) : null;
120
+ if (models && models.length > 0) {
121
+ const currentModel = existing?.model;
122
+ const modelList = currentModel && models.includes(currentModel)
123
+ ? [`${currentModel} *`, ...models.filter((m) => m !== currentModel)]
124
+ : models;
125
+ const selectedModel = await ui.select('Model', modelList) ?? modelList[0];
126
+ model = stripMarker(selectedModel);
127
+ }
128
+ else {
129
+ const existingModel = existing?.model ?? PROVIDER_MODEL_DEFAULTS[provider] ?? '';
130
+ const modelTitle = existing?.model ? `Model (current: ${existing.model})` : 'Model';
131
+ model = (await ui.input(modelTitle, PROVIDER_MODEL_DEFAULTS[provider] ?? '')) || existingModel;
132
+ }
133
+ return {
134
+ provider,
135
+ model,
136
+ ...(baseUrl ? { openaiCompatBaseUrl: baseUrl } : {}),
137
+ ...(skipSslVerify ? { skipSslVerify: true } : {}),
138
+ };
139
+ }
140
+ async function configureEmbedding(ui, existing) {
141
+ const embedUrl = (await ui.input(existing?.baseUrl ? `Embedding base URL (current: ${existing.baseUrl})` : 'Embedding base URL', existing?.baseUrl ?? 'http://localhost:11434')) || existing?.baseUrl || '';
142
+ if (!embedUrl)
143
+ return undefined;
144
+ const embedSsl = await ui.confirm('Skip SSL verification for embedding?', 'Only enable for local servers with self-signed certificates (e.g. Ollama on localhost). Do NOT enable for remote/cloud endpoints.');
145
+ const embedModels = await fetchModels(embedUrl);
146
+ let embedModel;
147
+ if (embedModels && embedModels.length > 0) {
148
+ const currentEmbedModel = existing?.model;
149
+ const embedModelList = currentEmbedModel && embedModels.includes(currentEmbedModel)
150
+ ? [`${currentEmbedModel} *`, ...embedModels.filter((m) => m !== currentEmbedModel)]
151
+ : embedModels;
152
+ const selectedEmbedModel = await ui.select('Embedding model', embedModelList) ?? embedModelList[0];
153
+ embedModel = stripMarker(selectedEmbedModel);
154
+ }
155
+ else {
156
+ const existingModel = existing?.model ?? '';
157
+ embedModel = (await ui.input(existing?.model ? `Embedding model (current: ${existing.model})` : 'Embedding model', '')) || existingModel;
158
+ }
159
+ const embedApiKey = process.env['OPENLORE_EMBEDDING_API_KEY'];
160
+ if (!embedApiKey) {
161
+ ui.notify('Embedding API key: set OPENLORE_EMBEDDING_API_KEY in your shell environment (leave unset for Ollama/local endpoints)', 'info');
162
+ }
163
+ return {
164
+ baseUrl: embedUrl,
165
+ model: embedModel,
166
+ ...(embedSsl ? { skipSslVerify: true } : {}),
167
+ };
168
+ }
169
+ async function runConfigWizard(ctx, existing) {
170
+ const { ui } = ctx;
171
+ // Mutable working copy — sections update independently until "Save".
172
+ let generation = existing?.generation ?? {};
173
+ let embedding = existing?.embedding;
174
+ let maxFiles = existing?.analysis?.maxFiles ?? 500;
175
+ // Pi never persists API keys (they belong in env vars). If an older config
176
+ // written by the CLI carried an embedding apiKey, drop it on save and tell the
177
+ // user — keeps behaviour consistent whether or not they edit the embedding.
178
+ if (embedding?.apiKey) {
179
+ embedding = { baseUrl: embedding.baseUrl, model: embedding.model, ...(embedding.skipSslVerify ? { skipSslVerify: true } : {}) };
180
+ ui.notify('Removed stored embedding API key from config — set OPENLORE_EMBEDDING_API_KEY in your shell instead.', 'warning');
181
+ }
182
+ // Menu loop — user picks which section to edit, repeats until Done.
183
+ while (true) {
184
+ const genLabel = generation.provider
185
+ ? `Generation ${generation.provider} · ${generation.model ?? '—'}${generation.openaiCompatBaseUrl ? ' · ' + generation.openaiCompatBaseUrl : ''}`
186
+ : 'Generation (not configured)';
187
+ const embedLabel = embedding
188
+ ? `Embedding ${embedding.baseUrl} · ${embedding.model || '—'}`
189
+ : 'Embedding (not configured)';
190
+ const analysisLabel = `Analysis maxFiles=${maxFiles}`;
191
+ const choice = await ui.select('openlore config — what to change?', [
192
+ genLabel,
193
+ embedLabel,
194
+ analysisLabel,
195
+ 'Save & close',
196
+ ]);
197
+ if (!choice)
198
+ return; // escaped — discard all changes
199
+ if (choice === 'Save & close')
200
+ break;
201
+ if (choice === genLabel) {
202
+ generation = await configureGeneration(ui, generation);
203
+ }
204
+ else if (choice === embedLabel) {
205
+ embedding = await configureEmbedding(ui, embedding);
206
+ }
207
+ else if (choice === analysisLabel) {
208
+ const raw = await ui.input(`Max files to analyze (current: ${maxFiles})`, '500');
209
+ maxFiles = parseInt(raw ?? '', 10) || maxFiles;
210
+ }
211
+ }
212
+ const config = {
213
+ version: existing?.version ?? '1.0.0',
214
+ projectType: existing?.projectType ?? 'unknown',
215
+ openspecPath: existing?.openspecPath ?? 'openspec',
216
+ analysis: {
217
+ maxFiles,
218
+ includePatterns: existing?.analysis?.includePatterns ?? [],
219
+ excludePatterns: existing?.analysis?.excludePatterns ?? [],
220
+ },
221
+ generation,
222
+ ...(embedding ? { embedding } : {}),
223
+ createdAt: existing?.createdAt ?? new Date().toISOString(),
224
+ lastRun: existing?.lastRun ?? null,
225
+ };
226
+ await writeConfig(ctx.cwd, config);
227
+ ui.notify('Configuration saved.', 'info');
228
+ const runNow = await ui.confirm('Run openlore analyze now?', 'Builds the structural index required for navigation tools (~30s–2min depending on codebase size)');
229
+ if (runNow) {
230
+ ui.notify('Running openlore analyze…', 'info');
231
+ const [exitCode, errText] = await new Promise((resolve) => {
232
+ // Try `openlore` in PATH; fall back to `npx openlore` if not found.
233
+ const trySpawn = (cmd, args) => new Promise((res) => {
234
+ const chunks = [];
235
+ const proc = spawn(cmd, args, { cwd: ctx.cwd, stdio: ['ignore', 'ignore', 'pipe'] });
236
+ proc.stderr?.on('data', (d) => chunks.push(d));
237
+ proc.on('close', (code) => res([code ?? 1, Buffer.concat(chunks).toString().trim()]));
238
+ proc.on('error', () => res(null));
239
+ });
240
+ trySpawn('openlore', ['analyze']).then((r) => {
241
+ if (r !== null)
242
+ return resolve(r);
243
+ return trySpawn('npx', ['openlore', 'analyze']).then((r2) => resolve(r2 ?? [1, 'openlore not found in PATH']));
244
+ });
245
+ });
246
+ if (exitCode === 0) {
247
+ ui.notify('Analysis complete — openlore tools are ready.', 'info');
248
+ }
249
+ else {
250
+ ui.notify(`openlore analyze failed — run it manually. ${errText ? '(' + errText.slice(0, 120) + ')' : ''}`.trim(), 'error');
251
+ }
252
+ }
253
+ }
254
+ const HEALTH_TIMEOUT_MS = 8000;
255
+ const HEALTH_POLL_MS = 150;
256
+ const RESULT_MAX = 50_000;
257
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
258
+ async function readDescriptor(cwd) {
259
+ try {
260
+ return JSON.parse(await readFile(join(cwd, OPENLORE_DIR, 'serve.json'), 'utf-8'));
261
+ }
262
+ catch {
263
+ return null;
264
+ }
265
+ }
266
+ async function healthy(desc) {
267
+ try {
268
+ const res = await fetch(`http://${desc.host}:${desc.port}/health`, { signal: AbortSignal.timeout(1000) });
269
+ if (!res.ok)
270
+ return false;
271
+ return (await res.json().catch(() => null))?.ok === true;
272
+ }
273
+ catch {
274
+ return false;
275
+ }
276
+ }
277
+ async function ensureDaemon(cwd) {
278
+ const existing = await readDescriptor(cwd);
279
+ if (existing && (await healthy(existing)))
280
+ return { baseUrl: `http://${existing.host}:${existing.port}`, token: existing.token };
281
+ try {
282
+ spawn('openlore', ['serve', '--directory', cwd], { detached: true, stdio: 'ignore' }).unref();
283
+ }
284
+ catch {
285
+ return null;
286
+ }
287
+ const deadline = Date.now() + HEALTH_TIMEOUT_MS;
288
+ while (Date.now() < deadline) {
289
+ await sleep(HEALTH_POLL_MS);
290
+ const desc = await readDescriptor(cwd);
291
+ if (desc && (await healthy(desc)))
292
+ return { baseUrl: `http://${desc.host}:${desc.port}`, token: desc.token };
293
+ }
294
+ return null;
295
+ }
296
+ async function callTool(daemon, name, args, cwd, signal) {
297
+ const headers = { 'content-type': 'application/json' };
298
+ if (daemon.token)
299
+ headers['x-openlore-token'] = daemon.token;
300
+ try {
301
+ const res = await fetch(`${daemon.baseUrl}/tool/${encodeURIComponent(name)}`, {
302
+ method: 'POST', headers, body: JSON.stringify({ directory: cwd, args }), signal,
303
+ });
304
+ const body = await res.json().catch(() => ({ error: `non-JSON (${res.status})` }));
305
+ if (!res.ok)
306
+ return { error: body.error ?? `HTTP ${res.status}` };
307
+ return body;
308
+ }
309
+ catch (err) {
310
+ return { error: err instanceof Error ? err.message : String(err) };
311
+ }
312
+ }
313
+ // ── Context injection helpers ─────────────────────────────────────────────────
314
+ function truncate(s, max) {
315
+ return s.length <= max ? s : s.slice(0, max) + `\n… (truncated, ${s.length - max} more chars)`;
316
+ }
317
+ async function readDigest(cwd) {
318
+ try {
319
+ return await readFile(join(cwd, OPENLORE_DIR, 'analysis', 'CODEBASE.md'), 'utf-8');
320
+ }
321
+ catch {
322
+ return '';
323
+ }
324
+ }
325
+ async function readSpecIndex(cwd) {
326
+ try {
327
+ const { readdir } = await import('node:fs/promises');
328
+ const dirs = (await readdir(join(cwd, 'openspec', 'specs'), { withFileTypes: true }))
329
+ .filter((d) => d.isDirectory()).map((d) => d.name);
330
+ if (dirs.length === 0)
331
+ return '';
332
+ return ['## openlore spec domains', ...dirs.map((d) => `- ${d}`)].join('\n');
333
+ }
334
+ catch {
335
+ return '';
336
+ }
337
+ }
338
+ const NAV_TOOLS = [
339
+ {
340
+ name: 'orient',
341
+ label: 'openlore orient',
342
+ description: 'START HERE on any new task. Returns relevant functions, files, spec domains, call neighbours, and insertion points in one call.',
343
+ guideline: 'Use openlore_orient FIRST on any new task before reading files.',
344
+ parameters: Type.Object({ task: Type.String({ description: 'Natural-language task description' }), limit: Type.Optional(Type.Number()) }),
345
+ },
346
+ {
347
+ name: 'search_code',
348
+ label: 'openlore search_code',
349
+ description: 'Semantic + keyword search for functions by meaning or name.',
350
+ guideline: 'Use openlore_search_code to find where a concept lives instead of grepping.',
351
+ parameters: Type.Object({ query: Type.String(), limit: Type.Optional(Type.Number()), language: Type.Optional(Type.String()) }),
352
+ },
353
+ {
354
+ name: 'get_subgraph',
355
+ label: 'openlore get_subgraph',
356
+ description: 'Call topology around a function (callers/callees) to a given depth.',
357
+ guideline: 'Use openlore_get_subgraph to see blast radius before changing a function.',
358
+ parameters: Type.Object({ functionName: Type.String(), direction: Type.Optional(StringEnum(['downstream', 'upstream', 'both'])), maxDepth: Type.Optional(Type.Number()) }),
359
+ },
360
+ {
361
+ name: 'trace_execution_path',
362
+ label: 'openlore trace_execution_path',
363
+ description: 'Find call paths from an entry function to a target function.',
364
+ guideline: 'Use openlore_trace_execution_path to answer "how does X reach Y".',
365
+ parameters: Type.Object({ entryFunction: Type.String(), targetFunction: Type.String(), maxDepth: Type.Optional(Type.Number()) }),
366
+ },
367
+ {
368
+ name: 'analyze_impact',
369
+ label: 'openlore analyze_impact',
370
+ description: 'Blast radius of changing a symbol (transitive dependents).',
371
+ guideline: 'Use openlore_analyze_impact before editing a shared/hub symbol.',
372
+ parameters: Type.Object({ symbol: Type.String(), depth: Type.Optional(Type.Number()) }),
373
+ },
374
+ {
375
+ name: 'suggest_insertion_points',
376
+ label: 'openlore suggest_insertion_points',
377
+ description: 'Where to add a feature — ranked file/function insertion candidates.',
378
+ guideline: 'Use openlore_suggest_insertion_points when planning where new code goes.',
379
+ parameters: Type.Object({ description: Type.String(), limit: Type.Optional(Type.Number()) }),
380
+ },
381
+ {
382
+ name: 'get_function_skeleton',
383
+ label: 'openlore get_function_skeleton',
384
+ description: 'Compact skeleton of a file: signatures + control flow, noise stripped.',
385
+ guideline: 'Use openlore_get_function_skeleton to read a file cheaply before opening it.',
386
+ parameters: Type.Object({ filePath: Type.String() }),
387
+ },
388
+ ];
389
+ function toolResult(text, details = null) {
390
+ return { content: [{ type: 'text', text }], details };
391
+ }
392
+ // ── Extension entry point ─────────────────────────────────────────────────────
393
+ export default function openlore(pi) {
394
+ const daemons = new Map();
395
+ // Negative cache: when a daemon can't be reached, remember the failure for a
396
+ // short window so we don't pay the full 8s spawn-and-poll on every call in a
397
+ // repo that simply isn't analyzed yet. Transient failures recover after TTL.
398
+ const failedUntil = new Map();
399
+ const DAEMON_RETRY_COOLDOWN_MS = 30_000;
400
+ const primed = new Set();
401
+ let sessionCwd = process.cwd();
402
+ let sessionMode = 'tui';
403
+ async function getDaemon(cwd) {
404
+ const cached = daemons.get(cwd);
405
+ if (cached)
406
+ return cached;
407
+ if ((failedUntil.get(cwd) ?? 0) > Date.now())
408
+ return null;
409
+ const d = await ensureDaemon(cwd);
410
+ if (d) {
411
+ daemons.set(cwd, d);
412
+ failedUntil.delete(cwd);
413
+ }
414
+ else {
415
+ failedUntil.set(cwd, Date.now() + DAEMON_RETRY_COOLDOWN_MS);
416
+ }
417
+ return d;
418
+ }
419
+ // ── B: navigation tools ──
420
+ for (const tool of NAV_TOOLS) {
421
+ pi.registerTool({
422
+ name: `openlore_${tool.name}`,
423
+ label: tool.label,
424
+ description: tool.description,
425
+ promptSnippet: tool.description,
426
+ promptGuidelines: [tool.guideline],
427
+ parameters: tool.parameters,
428
+ async execute(_id, params, signal, _onUpdate, ctx) {
429
+ const daemon = await getDaemon(ctx.cwd);
430
+ if (!daemon)
431
+ return toolResult('openlore daemon unavailable — run `openlore analyze` then retry.');
432
+ const result = await callTool(daemon, tool.name, params, ctx.cwd, signal ?? undefined);
433
+ const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
434
+ return toolResult(truncate(text, RESULT_MAX), result);
435
+ },
436
+ });
437
+ }
438
+ // ── Config tool ──
439
+ pi.registerTool({
440
+ name: 'openlore_configure',
441
+ label: 'openlore configure',
442
+ description: 'Open the openlore configuration wizard to set provider, model, embedding, and analysis settings.',
443
+ promptSnippet: 'Configure openlore settings (provider, model, API key, embedding).',
444
+ promptGuidelines: ['Use openlore_configure to change the LLM provider, model, or embedding settings.'],
445
+ parameters: Type.Object({}),
446
+ async execute(_id, _params, _signal, _onUpdate, ctx) {
447
+ if (!ctx.hasUI)
448
+ return toolResult('Config wizard requires an interactive session (tui or rpc mode).');
449
+ const existing = await readConfig(ctx.cwd);
450
+ await runConfigWizard(ctx, existing);
451
+ return toolResult('Configuration saved to .openlore/config.json.');
452
+ },
453
+ });
454
+ // ── /configure slash command ──
455
+ pi.registerCommand('openlore', {
456
+ description: 'Open the openlore configuration wizard',
457
+ async handler(_args, ctx) {
458
+ if (!ctx.hasUI) {
459
+ ctx.ui.notify('Config wizard requires an interactive session.', 'error');
460
+ return;
461
+ }
462
+ const existing = await readConfig(ctx.cwd);
463
+ await runConfigWizard(ctx, existing);
464
+ },
465
+ });
466
+ // ── session_start: onboarding + daemon warmup ──
467
+ pi.on('session_start', async (_event, ctx) => {
468
+ sessionCwd = ctx.cwd;
469
+ sessionMode = ctx.mode;
470
+ if (ctx.hasUI && !(await readConfig(ctx.cwd))) {
471
+ await runConfigWizard(ctx, null);
472
+ }
473
+ if (ctx.mode !== 'json' && ctx.mode !== 'print') {
474
+ await getDaemon(ctx.cwd);
475
+ }
476
+ });
477
+ // ── C: context injection on the first turn ──
478
+ pi.on('before_agent_start', async (event, _ctx) => {
479
+ if (sessionMode === 'json' || sessionMode === 'print')
480
+ return;
481
+ if (primed.has(sessionCwd))
482
+ return;
483
+ primed.add(sessionCwd);
484
+ const blocks = [];
485
+ const digest = await readDigest(sessionCwd);
486
+ if (digest)
487
+ blocks.push('# Codebase architecture (openlore)\n\n' + truncate(digest, 8000));
488
+ const specIndex = await readSpecIndex(sessionCwd);
489
+ if (specIndex)
490
+ blocks.push(specIndex);
491
+ const daemon = await getDaemon(sessionCwd);
492
+ if (daemon && event.prompt) {
493
+ const oriented = await callTool(daemon, 'orient', { task: event.prompt }, sessionCwd);
494
+ if (oriented && typeof oriented === 'object' && !('error' in oriented)) {
495
+ blocks.push('# openlore orientation for this task\n\n' + truncate(JSON.stringify(oriented, null, 2), 6000));
496
+ }
497
+ }
498
+ const suffix = blocks.length > 0
499
+ ? blocks.join('\n\n')
500
+ : '[openlore: no analysis found — run `openlore analyze` to enable structural context.]';
501
+ return { systemPrompt: event.systemPrompt + '\n\n' + suffix };
502
+ });
503
+ }
504
+ export const installPaths = {
505
+ project: (cwd) => join(cwd, '.pi', 'extensions', 'openlore.js'),
506
+ global: () => join(homedir(), '.pi', 'agent', 'extensions', 'openlore.js'),
507
+ };
508
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../../src/pi/extension.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ # openlore × Pi
2
+
3
+ A [Pi](https://pi.dev) extension that brings openlore's deterministic structural
4
+ context into Pi — built for local models (Qwen, Gemma, …) that are strong at
5
+ using injected context but weaker at tool-calling.
6
+
7
+ It does **not** use MCP. It talks to a warm `openlore serve` HTTP daemon over
8
+ loopback, so tool calls hit warm caches and the analysis stays continuously
9
+ fresh while you edit.
10
+
11
+ ## What you get
12
+
13
+ - **Context injection** (no tool call needed): each session starts grounded with
14
+ the architecture digest (`CODEBASE.md`), the spec-domain index, and a
15
+ task-specific `orient` on your first message.
16
+ - **Native tools**: the navigation surface as Pi tools —
17
+ `openlore_orient`, `openlore_search_code`, `openlore_get_subgraph`,
18
+ `openlore_trace_execution_path`, `openlore_analyze_impact`,
19
+ `openlore_suggest_insertion_points`, `openlore_get_function_skeleton`.
20
+ - **Config wizard**: interactive setup on first run, or anytime via `/openlore`
21
+ slash command or `openlore_configure` tool.
22
+
23
+ ## Prerequisites
24
+
25
+ ```bash
26
+ npm i -g openlore # `openlore` must be on PATH
27
+ cd your-project
28
+ openlore analyze # build the structural index at least once
29
+ ```
30
+
31
+ ## Install
32
+
33
+ ### Recommended — Pi gallery
34
+
35
+ ```bash
36
+ pi install npm:openlore
37
+ ```
38
+
39
+ Pi discovers the extension automatically via the `"pi"` field in openlore's
40
+ `package.json`. On first session it launches the config wizard.
41
+
42
+ ### Alternative — openlore setup
43
+
44
+ ```bash
45
+ openlore setup --tools pi # → .pi/extensions/openlore.js (this project)
46
+ openlore setup --tools pi --global # → ~/.pi/agent/extensions/openlore.js (all projects)
47
+ ```
48
+
49
+ > Requires Pi ≥ 0.78.1. The extension uses `ctx.mode` (0.78.1+) for injection
50
+ > depth: full in `tui`/`rpc` (interactive), none in `json`/`print` (one-shot).
51
+
52
+ ## Configuration
53
+
54
+ On first session (no `.openlore/config.json`) the wizard runs automatically.
55
+ Re-open anytime:
56
+
57
+ ```
58
+ /openlore # slash command in any Pi session
59
+ ```
60
+
61
+ or ask Pi to call `openlore_configure`.
62
+
63
+ API keys are never stored in config — set them as environment variables:
64
+
65
+ | Provider | Env var |
66
+ |----------|---------|
67
+ | `anthropic` | `ANTHROPIC_API_KEY` |
68
+ | `openai` | `OPENAI_API_KEY` |
69
+ | `openai-compat` | `OPENAI_COMPAT_API_KEY` |
70
+ | Embedding | `OPENLORE_EMBEDDING_API_KEY` |
71
+
72
+ ## How it works
73
+
74
+ On `session_start` the extension looks for `.openlore/serve.json`; if no healthy
75
+ daemon is announced it spawns `openlore serve` detached and waits for `/health`.
76
+ The daemon:
77
+
78
+ - serves the `navigation` tool preset over `127.0.0.1`,
79
+ - keeps signatures/vector fresh live, and
80
+ - re-analyzes the call graph (debounced) after each edit burst — so what the
81
+ model sees never silently diverges from the code.
82
+
83
+ The extension never kills a daemon it didn't start; it may be serving other
84
+ clients (another Pi session, an editor).
85
+
86
+ ## Verify
87
+
88
+ ```bash
89
+ # daemon is reachable
90
+ curl 127.0.0.1:$(jq .port .openlore/serve.json)/health
91
+
92
+ # a tool round-trips
93
+ curl -XPOST 127.0.0.1:$(jq .port .openlore/serve.json)/tool/orient \
94
+ -d '{"args":{"task":"add rate limiting"}}'
95
+ ```
96
+
97
+ Then run Pi in the project and confirm the session opens with openlore context
98
+ and that `openlore_orient` is callable.