@oh-my-pi/pi-coding-agent 13.19.0 → 14.0.3
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/CHANGELOG.md +277 -2
- package/package.json +86 -20
- package/scripts/format-prompts.ts +2 -2
- package/src/autoresearch/apply-contract-to-state.ts +24 -0
- package/src/autoresearch/contract.ts +0 -44
- package/src/autoresearch/dashboard.ts +1 -2
- package/src/autoresearch/git.ts +91 -0
- package/src/autoresearch/helpers.ts +49 -0
- package/src/autoresearch/index.ts +28 -187
- package/src/autoresearch/prompt.md +26 -9
- package/src/autoresearch/state.ts +0 -6
- package/src/autoresearch/tools/init-experiment.ts +202 -117
- package/src/autoresearch/tools/log-experiment.ts +83 -125
- package/src/autoresearch/tools/run-experiment.ts +48 -10
- package/src/autoresearch/types.ts +2 -2
- package/src/capability/index.ts +4 -2
- package/src/cli/file-processor.ts +3 -3
- package/src/cli/grep-cli.ts +8 -8
- package/src/cli/grievances-cli.ts +78 -0
- package/src/cli/read-cli.ts +67 -0
- package/src/cli/setup-cli.ts +4 -4
- package/src/cli/update-cli.ts +3 -3
- package/src/cli.ts +2 -0
- package/src/commands/grep.ts +6 -1
- package/src/commands/grievances.ts +20 -0
- package/src/commands/read.ts +33 -0
- package/src/commit/agentic/agent.ts +5 -5
- package/src/commit/agentic/index.ts +3 -4
- package/src/commit/agentic/tools/analyze-file.ts +3 -3
- package/src/commit/agentic/validation.ts +1 -1
- package/src/commit/analysis/conventional.ts +4 -4
- package/src/commit/analysis/summary.ts +3 -3
- package/src/commit/changelog/generate.ts +4 -4
- package/src/commit/map-reduce/map-phase.ts +4 -4
- package/src/commit/map-reduce/reduce-phase.ts +4 -4
- package/src/commit/pipeline.ts +3 -4
- package/src/config/model-registry.ts +17 -3
- package/src/config/prompt-templates.ts +44 -226
- package/src/config/resolve-config-value.ts +4 -2
- package/src/config/settings-schema.ts +54 -2
- package/src/config/settings.ts +25 -26
- package/src/dap/client.ts +674 -0
- package/src/dap/config.ts +150 -0
- package/src/dap/defaults.json +211 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1255 -0
- package/src/dap/types.ts +600 -0
- package/src/debug/log-viewer.ts +3 -2
- package/src/discovery/builtin.ts +1 -2
- package/src/discovery/codex.ts +2 -2
- package/src/discovery/github.ts +2 -1
- package/src/discovery/helpers.ts +2 -2
- package/src/discovery/opencode.ts +2 -2
- package/src/edit/diff.ts +818 -0
- package/src/edit/index.ts +309 -0
- package/src/edit/line-hash.ts +67 -0
- package/src/edit/modes/chunk.ts +454 -0
- package/src/{patch → edit/modes}/hashline.ts +741 -361
- package/src/{patch/applicator.ts → edit/modes/patch.ts} +420 -117
- package/src/{patch/fuzzy.ts → edit/modes/replace.ts} +519 -197
- package/src/{patch → edit}/normalize.ts +97 -76
- package/src/{patch/shared.ts → edit/renderer.ts} +181 -108
- package/src/exec/bash-executor.ts +4 -2
- package/src/exec/idle-timeout-watchdog.ts +126 -0
- package/src/exec/non-interactive-env.ts +5 -0
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +2 -2
- package/src/extensibility/custom-commands/bundled/review/index.ts +36 -15
- package/src/extensibility/custom-commands/loader.ts +1 -2
- package/src/extensibility/custom-tools/loader.ts +34 -11
- package/src/extensibility/extensions/loader.ts +9 -4
- package/src/extensibility/extensions/runner.ts +24 -1
- package/src/extensibility/extensions/types.ts +1 -1
- package/src/extensibility/hooks/loader.ts +5 -6
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/extensibility/plugins/doctor.ts +2 -1
- package/src/extensibility/slash-commands.ts +3 -7
- package/src/index.ts +2 -1
- package/src/internal-urls/docs-index.generated.ts +11 -11
- package/src/ipy/executor.ts +58 -17
- package/src/ipy/gateway-coordinator.ts +6 -4
- package/src/ipy/kernel.ts +45 -22
- package/src/ipy/runtime.ts +2 -2
- package/src/lsp/client.ts +7 -4
- package/src/lsp/clients/lsp-linter-client.ts +4 -4
- package/src/lsp/config.ts +20 -4
- package/src/lsp/defaults.json +688 -154
- package/src/lsp/index.ts +234 -45
- package/src/lsp/lspmux.ts +2 -2
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +12 -1
- package/src/lsp/utils.ts +8 -1
- package/src/main.ts +102 -46
- package/src/memories/index.ts +4 -5
- package/src/modes/acp/acp-agent.ts +563 -163
- package/src/modes/acp/acp-event-mapper.ts +9 -1
- package/src/modes/acp/acp-mode.ts +4 -2
- package/src/modes/components/agent-dashboard.ts +3 -4
- package/src/modes/components/diff.ts +6 -7
- package/src/modes/components/read-tool-group.ts +6 -12
- package/src/modes/components/session-observer-overlay.ts +21 -12
- package/src/modes/components/settings-defs.ts +5 -0
- package/src/modes/components/tool-execution.ts +1 -1
- package/src/modes/components/welcome.ts +1 -1
- package/src/modes/controllers/btw-controller.ts +2 -2
- package/src/modes/controllers/command-controller.ts +3 -2
- package/src/modes/controllers/input-controller.ts +12 -8
- package/src/modes/index.ts +20 -2
- package/src/modes/interactive-mode.ts +94 -37
- package/src/modes/rpc/host-tools.ts +186 -0
- package/src/modes/rpc/rpc-client.ts +178 -13
- package/src/modes/rpc/rpc-mode.ts +73 -3
- package/src/modes/rpc/rpc-types.ts +53 -1
- package/src/modes/theme/theme.ts +80 -8
- package/src/modes/types.ts +2 -2
- package/src/prompts/review-request.md +6 -0
- package/src/prompts/system/system-prompt.md +2 -1
- package/src/prompts/tools/chunk-edit.md +223 -0
- package/src/prompts/tools/debug.md +43 -0
- package/src/prompts/tools/grep.md +3 -0
- package/src/prompts/tools/lsp.md +5 -5
- package/src/prompts/tools/read-chunk.md +17 -0
- package/src/prompts/tools/read.md +19 -5
- package/src/sdk.ts +190 -154
- package/src/secrets/obfuscator.ts +1 -1
- package/src/session/agent-session.ts +306 -256
- package/src/session/agent-storage.ts +12 -12
- package/src/session/compaction/branch-summarization.ts +3 -3
- package/src/session/compaction/compaction.ts +5 -6
- package/src/session/compaction/utils.ts +3 -3
- package/src/session/history-storage.ts +62 -19
- package/src/session/messages.ts +3 -3
- package/src/session/session-dump-format.ts +203 -0
- package/src/session/session-storage.ts +4 -2
- package/src/session/streaming-output.ts +1 -1
- package/src/session/tool-choice-queue.ts +213 -0
- package/src/slash-commands/builtin-registry.ts +56 -8
- package/src/ssh/connection-manager.ts +2 -2
- package/src/ssh/sshfs-mount.ts +5 -5
- package/src/stt/downloader.ts +4 -4
- package/src/stt/recorder.ts +4 -4
- package/src/stt/transcriber.ts +2 -2
- package/src/system-prompt.ts +21 -13
- package/src/task/agents.ts +5 -6
- package/src/task/commands.ts +2 -5
- package/src/task/executor.ts +4 -4
- package/src/task/index.ts +3 -4
- package/src/task/template.ts +2 -2
- package/src/task/worktree.ts +4 -4
- package/src/tools/ask.ts +2 -3
- package/src/tools/ast-edit.ts +7 -7
- package/src/tools/ast-grep.ts +7 -7
- package/src/tools/auto-generated-guard.ts +36 -41
- package/src/tools/await-tool.ts +2 -2
- package/src/tools/bash.ts +5 -23
- package/src/tools/browser.ts +4 -5
- package/src/tools/calculator.ts +2 -3
- package/src/tools/cancel-job.ts +2 -2
- package/src/tools/checkpoint.ts +3 -3
- package/src/tools/debug.ts +1007 -0
- package/src/tools/exit-plan-mode.ts +2 -3
- package/src/tools/fetch.ts +67 -3
- package/src/tools/find.ts +4 -5
- package/src/tools/fs-cache-invalidation.ts +5 -0
- package/src/tools/gemini-image.ts +13 -5
- package/src/tools/gh.ts +10 -11
- package/src/tools/grep.ts +57 -9
- package/src/tools/index.ts +44 -22
- package/src/tools/inspect-image.ts +4 -4
- package/src/tools/output-meta.ts +1 -1
- package/src/tools/python.ts +19 -6
- package/src/tools/read.ts +198 -67
- package/src/tools/render-mermaid.ts +2 -3
- package/src/tools/render-utils.ts +20 -6
- package/src/tools/renderers.ts +3 -1
- package/src/tools/report-tool-issue.ts +80 -0
- package/src/tools/resolve.ts +70 -39
- package/src/tools/search-tool-bm25.ts +2 -2
- package/src/tools/ssh.ts +2 -2
- package/src/tools/todo-write.ts +2 -2
- package/src/tools/tool-timeouts.ts +1 -0
- package/src/tools/write.ts +5 -6
- package/src/tui/tree-list.ts +3 -1
- package/src/utils/clipboard.ts +80 -0
- package/src/utils/commit-message-generator.ts +2 -3
- package/src/utils/edit-mode.ts +49 -0
- package/src/utils/file-display-mode.ts +6 -5
- package/src/utils/file-mentions.ts +8 -7
- package/src/utils/git.ts +4 -4
- package/src/utils/image-loading.ts +98 -0
- package/src/utils/title-generator.ts +2 -3
- package/src/utils/tools-manager.ts +6 -6
- package/src/web/scrapers/choosealicense.ts +1 -1
- package/src/web/search/index.ts +3 -3
- package/src/autoresearch/command-initialize.md +0 -34
- package/src/patch/diff.ts +0 -433
- package/src/patch/index.ts +0 -888
- package/src/patch/parser.ts +0 -532
- package/src/patch/types.ts +0 -292
- package/src/prompts/agents/oracle.md +0 -77
- package/src/tools/pending-action.ts +0 -49
- package/src/utils/child-process.ts +0 -88
- package/src/utils/frontmatter.ts +0 -117
- package/src/utils/image-input.ts +0 -274
- package/src/utils/mime.ts +0 -53
- package/src/utils/prompt-format.ts +0 -170
package/src/ipy/executor.ts
CHANGED
|
@@ -299,6 +299,48 @@ async function writePreludeCache(state: PreludeCacheState, helpers: PreludeHelpe
|
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
function isPythonTestEnvironment(): boolean {
|
|
303
|
+
return Bun.env.BUN_ENV === "test" || Bun.env.NODE_ENV === "test";
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function getPreludeIntrospectionOptions(
|
|
307
|
+
options: KernelSessionExecutionOptions = {},
|
|
308
|
+
): Pick<KernelExecuteOptions, "signal" | "timeoutMs"> {
|
|
309
|
+
return {
|
|
310
|
+
signal: options.signal,
|
|
311
|
+
timeoutMs: requireRemainingTimeoutMs(options.deadlineMs),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async function cachePreludeDocs(
|
|
316
|
+
cwd: string,
|
|
317
|
+
docs: PreludeHelper[],
|
|
318
|
+
cacheState?: PreludeCacheState | null,
|
|
319
|
+
): Promise<PreludeHelper[]> {
|
|
320
|
+
cachedPreludeDocs = docs;
|
|
321
|
+
if (!isPythonTestEnvironment() && docs.length > 0) {
|
|
322
|
+
const state = cacheState ?? (await buildPreludeCacheState(cwd));
|
|
323
|
+
await writePreludeCache(state, docs);
|
|
324
|
+
}
|
|
325
|
+
return docs;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async function ensurePreludeDocsLoaded(
|
|
329
|
+
kernel: PythonKernel,
|
|
330
|
+
cwd: string,
|
|
331
|
+
options: KernelSessionExecutionOptions = {},
|
|
332
|
+
cacheState?: PreludeCacheState | null,
|
|
333
|
+
): Promise<PreludeHelper[]> {
|
|
334
|
+
if (cachedPreludeDocs && cachedPreludeDocs.length > 0) {
|
|
335
|
+
return cachedPreludeDocs;
|
|
336
|
+
}
|
|
337
|
+
const docs = await kernel.introspectPrelude(getPreludeIntrospectionOptions(options));
|
|
338
|
+
if (docs.length === 0) {
|
|
339
|
+
throw new Error("Python prelude helpers unavailable");
|
|
340
|
+
}
|
|
341
|
+
return cachePreludeDocs(cwd, docs, cacheState);
|
|
342
|
+
}
|
|
343
|
+
|
|
302
344
|
function startCleanupTimer(): void {
|
|
303
345
|
if (cleanupTimer) return;
|
|
304
346
|
cleanupTimer = setInterval(() => {
|
|
@@ -366,16 +408,15 @@ export async function warmPythonEnvironment(
|
|
|
366
408
|
useSharedGateway?: boolean,
|
|
367
409
|
sessionFile?: string,
|
|
368
410
|
): Promise<{ ok: boolean; reason?: string; docs: PreludeHelper[] }> {
|
|
369
|
-
const isTestEnv = Bun.env.BUN_ENV === "test" || Bun.env.NODE_ENV === "test";
|
|
370
411
|
let cacheState: PreludeCacheState | null = null;
|
|
371
412
|
try {
|
|
372
|
-
await logger.
|
|
413
|
+
await logger.time("warmPython:ensureKernelAvailable", ensureKernelAvailable, cwd);
|
|
373
414
|
} catch (err: unknown) {
|
|
374
415
|
const reason = err instanceof Error ? err.message : String(err);
|
|
375
416
|
cachedPreludeDocs = [];
|
|
376
417
|
return { ok: false, reason, docs: [] };
|
|
377
418
|
}
|
|
378
|
-
if (!
|
|
419
|
+
if (!isPythonTestEnvironment()) {
|
|
379
420
|
try {
|
|
380
421
|
cacheState = await buildPreludeCacheState(cwd);
|
|
381
422
|
const cached = await readPreludeCache(cacheState);
|
|
@@ -393,17 +434,17 @@ export async function warmPythonEnvironment(
|
|
|
393
434
|
}
|
|
394
435
|
const resolvedSessionId = sessionId ?? `session:${cwd}`;
|
|
395
436
|
try {
|
|
396
|
-
const docs = await logger.
|
|
397
|
-
withKernelSession
|
|
437
|
+
const docs = await logger.time(
|
|
438
|
+
"warmPython:withKernelSession",
|
|
439
|
+
withKernelSession,
|
|
440
|
+
resolvedSessionId,
|
|
441
|
+
cwd,
|
|
442
|
+
kernel => ensurePreludeDocsLoaded(kernel, cwd, { useSharedGateway, sessionFile }, cacheState),
|
|
443
|
+
{
|
|
398
444
|
useSharedGateway,
|
|
399
445
|
sessionFile,
|
|
400
|
-
}
|
|
446
|
+
},
|
|
401
447
|
);
|
|
402
|
-
cachedPreludeDocs = docs;
|
|
403
|
-
if (!isTestEnv && docs.length > 0) {
|
|
404
|
-
const state = cacheState ?? (await buildPreludeCacheState(cwd));
|
|
405
|
-
await writePreludeCache(state, docs);
|
|
406
|
-
}
|
|
407
448
|
return { ok: true, docs };
|
|
408
449
|
} catch (err: unknown) {
|
|
409
450
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -461,7 +502,7 @@ async function createKernelSession(
|
|
|
461
502
|
|
|
462
503
|
let kernel: PythonKernel;
|
|
463
504
|
try {
|
|
464
|
-
kernel = await logger.
|
|
505
|
+
kernel = await logger.time("createKernelSession:PythonKernel.start", PythonKernel.start, startOptions);
|
|
465
506
|
} catch (err) {
|
|
466
507
|
if (!isRetry && isResourceExhaustionError(err)) {
|
|
467
508
|
await recoverFromResourceExhaustion();
|
|
@@ -541,7 +582,7 @@ async function withKernelSession<T>(
|
|
|
541
582
|
if (options.signal?.aborted) {
|
|
542
583
|
throw new PythonExecutionCancelledError(isTimedOutCancellation(options.signal.reason, options.signal));
|
|
543
584
|
}
|
|
544
|
-
session = await logger.
|
|
585
|
+
session = await logger.time("kernel:createKernelSession", createKernelSession, sessionId, cwd, options);
|
|
545
586
|
kernelSessions.set(sessionId, session);
|
|
546
587
|
startCleanupTimer();
|
|
547
588
|
}
|
|
@@ -549,18 +590,18 @@ async function withKernelSession<T>(
|
|
|
549
590
|
const run = async (): Promise<T> => {
|
|
550
591
|
session!.lastUsedAt = Date.now();
|
|
551
592
|
if (session!.dead || !session!.kernel.isAlive()) {
|
|
552
|
-
await logger.
|
|
593
|
+
await logger.time("kernel:restartKernelSession", restartKernelSession, session!, cwd, options);
|
|
553
594
|
}
|
|
554
595
|
try {
|
|
555
|
-
const result = await logger.
|
|
596
|
+
const result = await logger.time("kernel:withSession:handler", handler, session!.kernel);
|
|
556
597
|
session!.restartCount = 0;
|
|
557
598
|
return result;
|
|
558
599
|
} catch (err) {
|
|
559
600
|
if (!session!.dead && session!.kernel.isAlive()) {
|
|
560
601
|
throw err;
|
|
561
602
|
}
|
|
562
|
-
await logger.
|
|
563
|
-
const result = await logger.
|
|
603
|
+
await logger.time("kernel:restartKernelSession", restartKernelSession, session!, cwd, options);
|
|
604
|
+
const result = await logger.time("kernel:postRestart:handler", handler, session!.kernel);
|
|
564
605
|
session!.restartCount = 0;
|
|
565
606
|
return result;
|
|
566
607
|
}
|
|
@@ -313,9 +313,9 @@ async function killGateway(pid: number, context: string): Promise<void> {
|
|
|
313
313
|
export async function acquireSharedGateway(cwd: string): Promise<AcquireResult | null> {
|
|
314
314
|
try {
|
|
315
315
|
return await withGatewayLock(async () => {
|
|
316
|
-
const existingInfo = await logger.
|
|
316
|
+
const existingInfo = await logger.time("acquireSharedGateway:readInfo", readGatewayInfo);
|
|
317
317
|
if (existingInfo) {
|
|
318
|
-
if (await logger.
|
|
318
|
+
if (await logger.time("acquireSharedGateway:isAlive", isGatewayAlive, existingInfo)) {
|
|
319
319
|
localGatewayUrl = existingInfo.url;
|
|
320
320
|
isCoordinatorInitialized = true;
|
|
321
321
|
logger.debug("Reusing global Python gateway", { url: existingInfo.url });
|
|
@@ -329,8 +329,10 @@ export async function acquireSharedGateway(cwd: string): Promise<AcquireResult |
|
|
|
329
329
|
await clearGatewayInfo();
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
-
const { url, pid, pythonPath, venvPath } = await logger.
|
|
333
|
-
|
|
332
|
+
const { url, pid, pythonPath, venvPath } = await logger.time(
|
|
333
|
+
"acquireSharedGateway:startGateway",
|
|
334
|
+
startGatewayProcess,
|
|
335
|
+
cwd,
|
|
334
336
|
);
|
|
335
337
|
const info: GatewayInfo = {
|
|
336
338
|
url,
|
package/src/ipy/kernel.ts
CHANGED
|
@@ -421,8 +421,10 @@ export class PythonKernel {
|
|
|
421
421
|
}
|
|
422
422
|
|
|
423
423
|
static async start(options: KernelStartOptions): Promise<PythonKernel> {
|
|
424
|
-
const availability = await logger.
|
|
425
|
-
|
|
424
|
+
const availability = await logger.time(
|
|
425
|
+
"PythonKernel.start:availabilityCheck",
|
|
426
|
+
checkPythonKernelAvailability,
|
|
427
|
+
options.cwd,
|
|
426
428
|
);
|
|
427
429
|
if (!availability.ok) {
|
|
428
430
|
throw new Error(availability.reason ?? "Python kernel unavailable");
|
|
@@ -443,14 +445,21 @@ export class PythonKernel {
|
|
|
443
445
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
444
446
|
throwIfAborted(startupSignal, "Python kernel startup aborted");
|
|
445
447
|
try {
|
|
446
|
-
const sharedResult = await logger.
|
|
447
|
-
acquireSharedGateway
|
|
448
|
+
const sharedResult = await logger.time(
|
|
449
|
+
"PythonKernel.start:acquireSharedGateway",
|
|
450
|
+
acquireSharedGateway,
|
|
451
|
+
options.cwd,
|
|
448
452
|
);
|
|
449
453
|
if (!sharedResult) {
|
|
450
454
|
throw new Error("Shared Python gateway unavailable");
|
|
451
455
|
}
|
|
452
|
-
const kernel = await logger.
|
|
453
|
-
PythonKernel
|
|
456
|
+
const kernel = await logger.time(
|
|
457
|
+
"PythonKernel.start:startWithSharedGateway",
|
|
458
|
+
PythonKernel.#startWithSharedGateway,
|
|
459
|
+
sharedResult.url,
|
|
460
|
+
options.cwd,
|
|
461
|
+
options.env,
|
|
462
|
+
startup,
|
|
454
463
|
);
|
|
455
464
|
return kernel;
|
|
456
465
|
} catch (err) {
|
|
@@ -538,13 +547,16 @@ export class PythonKernel {
|
|
|
538
547
|
): Promise<PythonKernel> {
|
|
539
548
|
const startupSignal = combineAbortSignal(startup, undefined, "Python kernel startup aborted");
|
|
540
549
|
throwIfAborted(startupSignal, "Python kernel startup aborted");
|
|
541
|
-
const createResponse = await logger.
|
|
542
|
-
|
|
550
|
+
const createResponse = await logger.time(
|
|
551
|
+
"startWithSharedGateway:createKernel",
|
|
552
|
+
fetch,
|
|
553
|
+
`${gatewayUrl}/api/kernels`,
|
|
554
|
+
{
|
|
543
555
|
method: "POST",
|
|
544
556
|
headers: { "Content-Type": "application/json" },
|
|
545
557
|
body: JSON.stringify({ name: "python3" }),
|
|
546
558
|
signal: startupSignal,
|
|
547
|
-
}
|
|
559
|
+
},
|
|
548
560
|
);
|
|
549
561
|
|
|
550
562
|
if (!createResponse.ok) {
|
|
@@ -557,35 +569,44 @@ export class PythonKernel {
|
|
|
557
569
|
);
|
|
558
570
|
}
|
|
559
571
|
|
|
560
|
-
const kernelInfo = await logger.
|
|
572
|
+
const kernelInfo = (await logger.time(
|
|
561
573
|
"startWithSharedGateway:parseJson",
|
|
562
|
-
|
|
563
|
-
);
|
|
574
|
+
createResponse.json.bind(createResponse),
|
|
575
|
+
)) as { id: string };
|
|
564
576
|
const kernelId = kernelInfo.id;
|
|
565
577
|
|
|
566
578
|
const kernel = new PythonKernel(Snowflake.next(), kernelId, gatewayUrl, Snowflake.next(), "omp", true);
|
|
567
579
|
|
|
568
580
|
try {
|
|
569
|
-
await logger.
|
|
570
|
-
await logger.
|
|
571
|
-
|
|
581
|
+
await logger.time("startWithSharedGateway:connectWS", kernel.#connectWebSocket.bind(kernel), startup);
|
|
582
|
+
await logger.time(
|
|
583
|
+
"startWithSharedGateway:initEnv",
|
|
584
|
+
kernel.#initializeKernelEnvironment.bind(kernel),
|
|
585
|
+
cwd,
|
|
586
|
+
env,
|
|
587
|
+
startup,
|
|
572
588
|
);
|
|
573
589
|
const preludeOptions = getStartupExecuteOptions(startup);
|
|
574
|
-
const preludeResult = await logger.
|
|
575
|
-
|
|
590
|
+
const preludeResult = await logger.time(
|
|
591
|
+
"startWithSharedGateway:prelude",
|
|
592
|
+
kernel.execute.bind(kernel),
|
|
593
|
+
PYTHON_PRELUDE,
|
|
594
|
+
{
|
|
576
595
|
...preludeOptions,
|
|
577
596
|
silent: true,
|
|
578
597
|
storeHistory: false,
|
|
579
|
-
}
|
|
598
|
+
},
|
|
580
599
|
);
|
|
581
600
|
throwIfStartupExecutionFailed(
|
|
582
601
|
preludeResult,
|
|
583
602
|
preludeOptions.signal,
|
|
584
603
|
"Failed to initialize Python kernel prelude",
|
|
585
604
|
);
|
|
586
|
-
await logger.
|
|
587
|
-
|
|
588
|
-
|
|
605
|
+
await logger.time("startWithSharedGateway:loadModules", loadPythonModules, kernel, {
|
|
606
|
+
cwd,
|
|
607
|
+
signal: startup.signal,
|
|
608
|
+
deadlineMs: startup.deadlineMs,
|
|
609
|
+
});
|
|
589
610
|
return kernel;
|
|
590
611
|
} catch (err: unknown) {
|
|
591
612
|
await kernel.shutdown({ timeoutMs: getStartupCleanupTimeoutMs(startup.deadlineMs) });
|
|
@@ -927,11 +948,13 @@ export class PythonKernel {
|
|
|
927
948
|
return promise;
|
|
928
949
|
}
|
|
929
950
|
|
|
930
|
-
async introspectPrelude(): Promise<PreludeHelper[]> {
|
|
951
|
+
async introspectPrelude(options: Pick<KernelExecuteOptions, "signal" | "timeoutMs"> = {}): Promise<PreludeHelper[]> {
|
|
931
952
|
let output = "";
|
|
932
953
|
const result = await this.execute(PRELUDE_INTROSPECTION_SNIPPET, {
|
|
933
954
|
silent: false,
|
|
934
955
|
storeHistory: false,
|
|
956
|
+
signal: options.signal,
|
|
957
|
+
timeoutMs: options.timeoutMs,
|
|
935
958
|
onChunk: text => {
|
|
936
959
|
output += text;
|
|
937
960
|
},
|
package/src/ipy/runtime.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
-
import { $env, getPythonEnvDir } from "@oh-my-pi/pi-utils";
|
|
9
|
+
import { $env, $which, getPythonEnvDir } from "@oh-my-pi/pi-utils";
|
|
10
10
|
|
|
11
11
|
const DEFAULT_ENV_ALLOWLIST = new Set([
|
|
12
12
|
"PATH",
|
|
@@ -210,7 +210,7 @@ export function resolvePythonRuntime(cwd: string, baseEnv: Record<string, string
|
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
const pythonPath =
|
|
213
|
+
const pythonPath = $which("python") ?? $which("python3");
|
|
214
214
|
if (!pythonPath) {
|
|
215
215
|
throw new Error("Python executable not found on PATH");
|
|
216
216
|
}
|
package/src/lsp/client.ts
CHANGED
|
@@ -3,11 +3,11 @@ import { ToolAbortError, throwIfAborted } from "../tools/tool-errors";
|
|
|
3
3
|
import { applyWorkspaceEdit } from "./edits";
|
|
4
4
|
import { getLspmuxCommand, isLspmuxSupported } from "./lspmux";
|
|
5
5
|
import type {
|
|
6
|
-
Diagnostic,
|
|
7
6
|
LspClient,
|
|
8
7
|
LspJsonRpcNotification,
|
|
9
8
|
LspJsonRpcRequest,
|
|
10
9
|
LspJsonRpcResponse,
|
|
10
|
+
PublishDiagnosticsParams,
|
|
11
11
|
ServerConfig,
|
|
12
12
|
WorkspaceEdit,
|
|
13
13
|
} from "./types";
|
|
@@ -130,7 +130,7 @@ const CLIENT_CAPABILITIES = {
|
|
|
130
130
|
},
|
|
131
131
|
publishDiagnostics: {
|
|
132
132
|
relatedInformation: true,
|
|
133
|
-
versionSupport:
|
|
133
|
+
versionSupport: true,
|
|
134
134
|
tagSupport: { valueSet: [1, 2] },
|
|
135
135
|
codeDescriptionSupport: true,
|
|
136
136
|
dataSupport: true,
|
|
@@ -261,8 +261,11 @@ async function startMessageReader(client: LspClient): Promise<void> {
|
|
|
261
261
|
} else if ("method" in message) {
|
|
262
262
|
// Server notification
|
|
263
263
|
if (message.method === "textDocument/publishDiagnostics" && message.params) {
|
|
264
|
-
const params = message.params as
|
|
265
|
-
client.diagnostics.set(params.uri,
|
|
264
|
+
const params = message.params as PublishDiagnosticsParams;
|
|
265
|
+
client.diagnostics.set(params.uri, {
|
|
266
|
+
diagnostics: params.diagnostics,
|
|
267
|
+
version: params.version ?? null,
|
|
268
|
+
});
|
|
266
269
|
client.diagnosticsVersion += 1;
|
|
267
270
|
}
|
|
268
271
|
}
|
|
@@ -77,14 +77,14 @@ export class LspLinterClient implements LinterClient {
|
|
|
77
77
|
const timeoutMs = 3000;
|
|
78
78
|
const start = Date.now();
|
|
79
79
|
while (Date.now() - start < timeoutMs) {
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
82
|
-
return diagnostics;
|
|
80
|
+
const publishedDiagnostics = client.diagnostics.get(uri);
|
|
81
|
+
if (publishedDiagnostics !== undefined) {
|
|
82
|
+
return publishedDiagnostics.diagnostics;
|
|
83
83
|
}
|
|
84
84
|
await Bun.sleep(100);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
return client.diagnostics.get(uri) ?? [];
|
|
87
|
+
return client.diagnostics.get(uri)?.diagnostics ?? [];
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
dispose(): void {
|
package/src/lsp/config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as os from "node:os";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { isRecord, logger } from "@oh-my-pi/pi-utils";
|
|
4
|
+
import { $which, isRecord, logger } from "@oh-my-pi/pi-utils";
|
|
5
5
|
import { YAML } from "bun";
|
|
6
6
|
import { getConfigDirPaths } from "../config";
|
|
7
7
|
import { getPreloadedPluginRoots } from "../discovery/helpers";
|
|
@@ -197,6 +197,21 @@ const LOCAL_BIN_PATHS: Array<{ markers: string[]; binDir: string }> = [
|
|
|
197
197
|
{ markers: ["go.mod", "go.sum"], binDir: "bin" },
|
|
198
198
|
];
|
|
199
199
|
|
|
200
|
+
const WINDOWS_LOCAL_EXECUTABLE_EXTENSIONS = [".exe", ".cmd", ".bat"] as const;
|
|
201
|
+
|
|
202
|
+
function resolveLocalCommand(basePath: string): string | null {
|
|
203
|
+
if (fs.existsSync(basePath)) return basePath;
|
|
204
|
+
if (process.platform !== "win32") return null;
|
|
205
|
+
|
|
206
|
+
// Package managers write Windows launchers with executable suffixes in node_modules/.bin.
|
|
207
|
+
for (const extension of WINDOWS_LOCAL_EXECUTABLE_EXTENSIONS) {
|
|
208
|
+
const candidate = `${basePath}${extension}`;
|
|
209
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
200
215
|
/**
|
|
201
216
|
* Resolve a command to an executable path.
|
|
202
217
|
* Checks project-local bin directories first, then falls back to $PATH.
|
|
@@ -210,14 +225,15 @@ export function resolveCommand(command: string, cwd: string): string | null {
|
|
|
210
225
|
for (const { markers, binDir } of LOCAL_BIN_PATHS) {
|
|
211
226
|
if (hasRootMarkers(cwd, markers)) {
|
|
212
227
|
const localPath = path.join(cwd, binDir, command);
|
|
213
|
-
|
|
214
|
-
|
|
228
|
+
const resolvedLocalPath = resolveLocalCommand(localPath);
|
|
229
|
+
if (resolvedLocalPath) {
|
|
230
|
+
return resolvedLocalPath;
|
|
215
231
|
}
|
|
216
232
|
}
|
|
217
233
|
}
|
|
218
234
|
|
|
219
235
|
// Fall back to $PATH
|
|
220
|
-
return
|
|
236
|
+
return $which(command);
|
|
221
237
|
}
|
|
222
238
|
|
|
223
239
|
/**
|