fix(coding-agent): shared Python kernels between eval and user shortcut

- Namespaced `AgentSession.executePython()` session IDs before invoking the Python executor.
- Added a regression test proving eval state is visible to the user shortcut path.
This commit is contained in:
Scott Hyndman
2026-05-27 22:16:23 -04:00
parent fe0b7794d8
commit e46ee155a8
4 changed files with 24 additions and 4 deletions
+2 -1
View File
@@ -46,6 +46,7 @@
- Fixed `eval` tool image rendering to resize displayed images before returning them and append image-dimension notes to text output
- Fixed `write` tool output sanitation to strip malformed or loose hashline section headers before writing file content
- Fixed `omp auth-broker serve` crashing at startup with `logger.setTransports is not a function` — switched the call site to `import { setTransports } from "@oh-my-pi/pi-utils/logger"`, bypassing the `logger` namespace re-export that some Bun versions failed to expose at runtime
- Fixed user shortcut Python execution to namespace session IDs like eval, so both paths share one kernel
## [15.5.7] - 2026-05-27
### Added
@@ -8932,4 +8933,4 @@ Initial public release.
- Git branch display in footer
- Message queueing during streaming responses
- OAuth integration for Gmail and Google Calendar access
- HTML export with syntax highlighting and collapsible sections
- HTML export with syntax highlighting and collapsible sections
+1 -1
View File
@@ -5,7 +5,7 @@ import { checkPythonKernelAvailability } from "./kernel";
const PYTHON_SESSION_PREFIX = "python:";
function namespaceSessionId(sessionId: string): string {
export function namespaceSessionId(sessionId: string): string {
return sessionId.startsWith(PYTHON_SESSION_PREFIX) ? sessionId : `${PYTHON_SESSION_PREFIX}${sessionId}`;
}
@@ -106,6 +106,7 @@ import { RawSseDebugBuffer } from "../debug/raw-sse-buffer";
import { loadCapability } from "../discovery";
import { expandApplyPatchToEntries, normalizeDiff, normalizeToLF, ParseError, previewPatch, stripBom } from "../edit";
import { getFileSnapshotStore } from "../edit/file-snapshot-store";
import { namespaceSessionId as namespacePythonSessionId } from "../eval/py";
import {
disposeKernelSessionsByOwner,
executePython as executePythonCommand,
@@ -7525,7 +7526,7 @@ export class AgentSession {
});
const result = await executePythonCommand(code, {
cwd,
sessionId,
sessionId: namespacePythonSessionId(sessionId),
kernelOwnerId: this.#evalKernelOwnerId,
kernelMode: this.settings.get("python.kernelMode"),
onChunk,
@@ -29,6 +29,7 @@ describe("AgentSession user shortcut hooks", () => {
if (session) {
await session.dispose();
}
await pythonExecutor.disposeAllKernelSessions();
authStorage?.close();
authStorage = undefined;
tempDir.removeSync();
@@ -49,7 +50,7 @@ describe("AgentSession user shortcut hooks", () => {
session = new AgentSession({
agent,
sessionManager: SessionManager.inMemory(),
sessionManager: SessionManager.inMemory(tempDir.path()),
settings: Settings.isolated({ "compaction.enabled": false }),
modelRegistry,
extensionRunner,
@@ -177,4 +178,21 @@ describe("AgentSession user shortcut hooks", () => {
session.messages.some(message => message.role === "pythonExecution" && message.excludeFromContext === false),
).toBe(true);
});
it("shares Python state between eval and user shortcut execution", async () => {
createSession();
const evalSessionId = session.getEvalSessionId();
if (!evalSessionId) throw new Error("Expected eval session ID");
await pythonExecutor.executePython("shared_value = 123", {
cwd: tempDir.path(),
sessionId: `python:${evalSessionId}`,
kernelMode: "session",
});
const result = await session.executePython("print(shared_value)");
expect(result.exitCode).toBe(0);
expect(result.output.trim()).toBe("123");
});
});