@code-yeongyu/senpi-codemode 2026.10.10-2 → 2026.10.10-4
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 +34 -0
- package/README.md +80 -2
- package/package.json +4 -4
- package/src/bridge/protocol.ts +8 -3
- package/src/extension/kernel-registration.ts +7 -2
- package/src/extension/runtime-factory.ts +8 -1
- package/src/extension/runtime-info.ts +6 -2
- package/src/extension/session-manager.ts +9 -2
- package/src/kernels/AGENTS.md +2 -0
- package/src/kernels/js/context-manager.ts +23 -24
- package/src/kernels/js/control-frames.ts +24 -0
- package/src/kernels/js/kernel-contract.ts +14 -1
- package/src/kernels/js/kernel-memory-bridge.ts +1 -1
- package/src/kernels/js/kernel-memory.ts +79 -0
- package/src/kernels/js/process-drain-scan.d.ts +8 -0
- package/src/kernels/js/process-drain-scan.js +28 -0
- package/src/kernels/js/process-entry.js +462 -0
- package/src/kernels/js/process-memory-host.ts +83 -0
- package/src/kernels/js/process-worker.ts +298 -0
- package/src/kernels/js/run-queue.ts +7 -0
- package/src/kernels/js/worker-core.js +4 -2
- package/src/kernels/js/worker-cwd.js +5 -2
- package/src/kernels/js/worker-host.ts +9 -2
- package/src/kernels/js/worker-slot.ts +9 -0
- package/src/kernels/js/worker-startup.ts +48 -1
- package/src/kernels/js/worker-webview.js +8 -0
- package/src/kernels/sandbox/sandbox-cell.ts +26 -1
- package/src/kernels/shared/subprocess-process.ts +14 -0
- package/src/tool/AGENTS.md +1 -0
- package/src/tool/cell-runtime.ts +4 -2
- package/src/tool/detached-cell-manager.ts +4 -4
- package/src/tool/detached-cell-snapshot.ts +17 -0
- package/src/tool/detached-eval-result.ts +13 -7
- package/src/tool/interrupt-note.ts +4 -5
- package/src/tool/render.ts +2 -0
- package/src/tool/run-eval-cell.ts +3 -2
- package/src/tool/runtime-label.ts +2 -1
- package/src/tool/types.ts +2 -0
|
@@ -63,6 +63,23 @@ export function currentDetachedResult(cell: DetachedCellResultSource): AgentTool
|
|
|
63
63
|
return cell.terminalResult ?? cell.liveResult?.() ?? fallbackResult(cell.input);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* The result a cell cancelled before its handler finished settles with: its buffered output, not the live progress
|
|
68
|
+
* frame ("1/1 cells running"), so a stopped cell never reads as still running.
|
|
69
|
+
*/
|
|
70
|
+
export function cancelledDetachedResult(cell: DetachedCellResultSource): AgentToolResult<EvalToolDetails> {
|
|
71
|
+
if (cell.terminalResult !== undefined) return cell.terminalResult;
|
|
72
|
+
const current = currentDetachedResult(cell);
|
|
73
|
+
const output = detachedOutputTail(current);
|
|
74
|
+
return {
|
|
75
|
+
content: [
|
|
76
|
+
{ type: "text", text: output.length > 0 ? output : "(no output)" },
|
|
77
|
+
...current.content.filter((part) => part.type === "image"),
|
|
78
|
+
],
|
|
79
|
+
details: current.details,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
66
83
|
export function detachedErrorResult(cell: DetachedCellResultSource, error: Error): AgentToolResult<EvalToolDetails> {
|
|
67
84
|
const current = currentDetachedResult(cell);
|
|
68
85
|
const output = detachedOutputTail(current);
|
|
@@ -46,9 +46,7 @@ function createEvalListResult(cellManager: EvalDetachedCellManager): AgentToolRe
|
|
|
46
46
|
language: snapshot.language,
|
|
47
47
|
state: snapshot.state,
|
|
48
48
|
startedAtMs: snapshot.startedAtMs,
|
|
49
|
-
...(snapshot.queuedBehind === undefined
|
|
50
|
-
? {}
|
|
51
|
-
: { queuedBehind: [...snapshot.queuedBehind] }),
|
|
49
|
+
...(snapshot.queuedBehind === undefined ? {} : { queuedBehind: [...snapshot.queuedBehind] }),
|
|
52
50
|
...(summary ? { summary } : {}),
|
|
53
51
|
};
|
|
54
52
|
});
|
|
@@ -60,7 +58,7 @@ function createEvalListResult(cellManager: EvalDetachedCellManager): AgentToolRe
|
|
|
60
58
|
" ",
|
|
61
59
|
);
|
|
62
60
|
const elapsed = Math.floor(snapshot.result.details.durationMs / 1000);
|
|
63
|
-
const queued = cell.queuedBehind === undefined ? "" : `
|
|
61
|
+
const queued = cell.queuedBehind === undefined ? "" : ` ${queuedPhrase(cell.queuedBehind, cell.language)}`;
|
|
64
62
|
return `${cell.cellId} ${cell.language} ${cell.state} ${elapsed}s${queued} - ${preview}`;
|
|
65
63
|
})
|
|
66
64
|
.join("\n");
|
|
@@ -76,11 +74,13 @@ export function resultAfterDetach(
|
|
|
76
74
|
otherLiveCells: number,
|
|
77
75
|
): AgentToolResult<EvalToolDetails> {
|
|
78
76
|
if (snapshot.state !== "detached" && snapshot.state !== "running") return createDetachedControlResult(snapshot);
|
|
79
|
-
const
|
|
77
|
+
const queuedBehind = snapshot.queuedBehind;
|
|
80
78
|
const text =
|
|
81
|
-
|
|
79
|
+
queuedBehind === undefined
|
|
82
80
|
? `Eval cell ${snapshot.cellId} detached and is running in the ${input.language} kernel (${otherLiveCells} other live cells). Completion arrives as a notification; do not re-run it. eval({ action: "peek" | "stop", cell_id }) or eval({ action: "list" }).`
|
|
83
|
-
:
|
|
81
|
+
: queuedBehind.length === 0
|
|
82
|
+
? `Eval cell ${snapshot.cellId} is detached and waiting for the ${input.language} kernel to be ready; it runs first once the kernel is ready and completes as one notification. peek/stop/list with eval({ action, cell_id })`
|
|
83
|
+
: `Eval cell ${snapshot.cellId} is queued behind ${queuedBehind.join(", ")} in the ${input.language} kernel and detached; it runs after ${queuedBehind.join(", ")} and completes as one notification. peek/stop/list with eval({ action, cell_id })`;
|
|
84
84
|
return {
|
|
85
85
|
content: [
|
|
86
86
|
{
|
|
@@ -164,6 +164,12 @@ export function resultForDetachedState(
|
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
function queuedPhrase(queuedBehind: readonly string[], language: string): string {
|
|
168
|
+
return queuedBehind.length === 0
|
|
169
|
+
? `waiting for the ${language} kernel to be ready`
|
|
170
|
+
: `queued behind ${queuedBehind.join(", ")}`;
|
|
171
|
+
}
|
|
172
|
+
|
|
167
173
|
function textContent(result: AgentToolResult<EvalToolDetails>): string {
|
|
168
174
|
return result.content
|
|
169
175
|
.filter((part) => part.type === "text")
|
|
@@ -26,9 +26,8 @@ export async function describeTimeoutState(
|
|
|
26
26
|
);
|
|
27
27
|
if (outcome === undefined) error.message = fallbackTimeoutMessage(error.message);
|
|
28
28
|
else if (outcome.retained)
|
|
29
|
-
error.message = `${error.message} The kernel
|
|
30
|
-
else
|
|
31
|
-
error.message = `${error.message} The kernel was unresponsive and restarted; variables from earlier cells are lost.`;
|
|
29
|
+
error.message = `${error.message} The kernel was not restarted; variables from earlier cells are kept.`;
|
|
30
|
+
else error.message = `${error.message} The kernel was restarted; variables from earlier cells are lost.`;
|
|
32
31
|
if (outcome?.note !== undefined) error.message = `${error.message} ${outcome.note.trim()}`;
|
|
33
32
|
return error;
|
|
34
33
|
}
|
|
@@ -63,8 +62,8 @@ const LANGUAGE_LABEL: Record<EvalLanguage, string> = {
|
|
|
63
62
|
export function interruptionStateNote(language: EvalLanguage, stateRetained: boolean | undefined): string | undefined {
|
|
64
63
|
if (stateRetained === undefined) return undefined;
|
|
65
64
|
const label = LANGUAGE_LABEL[language];
|
|
66
|
-
if (stateRetained) return
|
|
67
|
-
return
|
|
65
|
+
if (stateRetained) return `The ${label} was not restarted; variables from earlier cells are kept.`;
|
|
66
|
+
return `The ${label} was restarted; variables from earlier cells are lost.`;
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
export function unknownInterruptionStateNote(language: EvalLanguage): string {
|
package/src/tool/render.ts
CHANGED
|
@@ -344,6 +344,8 @@ function cellHeader(cell: EvalCellResult, environment: RenderEnvironment, badges
|
|
|
344
344
|
let header = `eval ${cell.language}${runtimeBadge} ${presentation.label} ${presentation.icon}`;
|
|
345
345
|
if (cell.queuedBehind !== undefined && cell.queuedBehind.length > 0)
|
|
346
346
|
header += ` · queued behind ${cell.queuedBehind.map(sanitizeTerminalLabel).join(", ")}`;
|
|
347
|
+
else if (cell.queuedBehind !== undefined && cell.status === "queued")
|
|
348
|
+
header += ` · waiting for the ${cell.language} kernel to be ready`;
|
|
347
349
|
const throughputBadge = badges.throughput === undefined ? undefined : formatThroughputBadge(badges.throughput);
|
|
348
350
|
if (throughputBadge !== undefined) header += ` · ${throughputBadge}`;
|
|
349
351
|
const elapsedMs = badges.throughput?.wallDurationMs ?? cellElapsedMs(cell, environment);
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
type KernelToolsCapability,
|
|
15
15
|
type KernelToolsDescribeResult,
|
|
16
16
|
} from "../kernels/js/kernel-tools-types.ts";
|
|
17
|
-
import { sandboxCellExecutor } from "../kernels/sandbox/sandbox-cell.ts";
|
|
17
|
+
import { sandboxCellExecutor, sandboxRuntimeInfo } from "../kernels/sandbox/sandbox-cell.ts";
|
|
18
18
|
import { TIMEOUT_PAUSE_OP, TIMEOUT_RESUME_OP } from "../timeouts/bridge-timeout.ts";
|
|
19
19
|
import { abortError, CellExecution, defaultTimeoutFactory } from "./cell-execution.ts";
|
|
20
20
|
import { CellHandler, type CellState } from "./cell-handler.ts";
|
|
@@ -44,7 +44,8 @@ export async function runEvalCell(
|
|
|
44
44
|
const bridgeAbortController = new AbortController();
|
|
45
45
|
const cellSignal = AbortSignal.any([invocation.signal, bridgeAbortController.signal]);
|
|
46
46
|
const bridgeContext: ExtensionContext = { ...invocation.ctx, signal: cellSignal };
|
|
47
|
-
const runtime =
|
|
47
|
+
const runtime =
|
|
48
|
+
invocation.input.isolate === true ? sandboxRuntimeInfo() : options.runtimes?.[invocation.input.language];
|
|
48
49
|
const state: CellState = {
|
|
49
50
|
input: invocation.input,
|
|
50
51
|
...(runtime === undefined ? {} : { runtime }),
|
|
@@ -10,7 +10,8 @@ const ELLIPSIS = "\u2026";
|
|
|
10
10
|
* runtime name because node and bun are otherwise indistinguishable.
|
|
11
11
|
*/
|
|
12
12
|
export function formatRuntimeBadge(language: EvalLanguage, runtime: EvalRuntimeInfo, home: string = homedir()): string {
|
|
13
|
-
const
|
|
13
|
+
const base = language === "js" ? `${runtime.name} ${runtime.version}` : runtime.version;
|
|
14
|
+
const label = runtime.isolation === undefined ? base : `${base}, ${runtime.isolation}`;
|
|
14
15
|
if (runtime.path === undefined || runtime.path.length === 0) return label;
|
|
15
16
|
return `${label}, ${minifyPath(runtime.path, home)}`;
|
|
16
17
|
}
|
package/src/tool/types.ts
CHANGED
|
@@ -279,6 +279,8 @@ export interface EvalRuntimeInfo {
|
|
|
279
279
|
readonly name: string;
|
|
280
280
|
readonly version: string;
|
|
281
281
|
readonly path?: string;
|
|
282
|
+
/** JS only: the kernel runs in a child process (`process`), or the cell ran in an isolated QuickJS VM (`sandbox`). */
|
|
283
|
+
readonly isolation?: "process" | "sandbox";
|
|
282
284
|
}
|
|
283
285
|
|
|
284
286
|
export type EvalRuntimes = Readonly<Partial<Record<EvalLanguage, EvalRuntimeInfo>>>;
|