@code-yeongyu/senpi-codemode 2026.9.15-2 → 2026.9.16

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 (45) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +24 -0
  3. package/package.json +4 -4
  4. package/src/bridge/http-server.ts +7 -1
  5. package/src/bridge/kernel-tools-protocol.ts +85 -0
  6. package/src/bridge/protocol.ts +6 -0
  7. package/src/bridges/agent-bridge.ts +30 -11
  8. package/src/extension/session-manager.ts +11 -0
  9. package/src/index.ts +10 -0
  10. package/src/kernels/jl/prelude.jl +46 -0
  11. package/src/kernels/jl/runner.jl +1 -1
  12. package/src/kernels/js/context-manager.ts +29 -0
  13. package/src/kernels/js/kernel-contract.ts +12 -0
  14. package/src/kernels/js/kernel-tools-context.d.ts +13 -0
  15. package/src/kernels/js/kernel-tools-context.js +7 -0
  16. package/src/kernels/js/kernel-tools-define.d.ts +10 -0
  17. package/src/kernels/js/kernel-tools-define.js +12 -0
  18. package/src/kernels/js/kernel-tools-errors.js +22 -0
  19. package/src/kernels/js/kernel-tools-errors.ts +26 -0
  20. package/src/kernels/js/kernel-tools-host.ts +134 -0
  21. package/src/kernels/js/kernel-tools-naming.js +28 -0
  22. package/src/kernels/js/kernel-tools-parse.d.ts +5 -0
  23. package/src/kernels/js/kernel-tools-parse.js +255 -0
  24. package/src/kernels/js/kernel-tools-pump.js +105 -0
  25. package/src/kernels/js/kernel-tools-registry.d.ts +27 -0
  26. package/src/kernels/js/kernel-tools-registry.js +127 -0
  27. package/src/kernels/js/kernel-tools-schema.js +69 -0
  28. package/src/kernels/js/kernel-tools-types.ts +42 -0
  29. package/src/kernels/js/prelude.ts +2 -0
  30. package/src/kernels/js/worker-core.js +26 -3
  31. package/src/kernels/js/worker-runtime.js +20 -8
  32. package/src/kernels/js/worker-slot.ts +6 -1
  33. package/src/kernels/js/worker-startup.ts +9 -7
  34. package/src/kernels/js/workpool.js +37 -0
  35. package/src/kernels/kernel-tools-unavailable.ts +5 -0
  36. package/src/kernels/py/kernel.ts +13 -0
  37. package/src/kernels/py/prelude.py +57 -3
  38. package/src/kernels/rb/prelude.rb +13 -2
  39. package/src/kernels/rb/workpool.rb +38 -0
  40. package/src/kernels/shared/subprocess-kernel.ts +13 -0
  41. package/src/kernels/shared/subprocess-queue.ts +2 -0
  42. package/src/prompt/eval-prompt-template.ts +4 -2
  43. package/src/tool/cell-handler.ts +8 -1
  44. package/src/tool/run-eval-cell.ts +49 -30
  45. package/src/tool/types.ts +2 -0
@@ -90,6 +90,8 @@ export class CellHandler {
90
90
  case "init-failed":
91
91
  case "result":
92
92
  case "closed":
93
+ case "kernel-tool-describe-reply":
94
+ case "kernel-tool-invoke-reply":
93
95
  return;
94
96
  default:
95
97
  throw new TypeError(`Unhandled kernel message: ${String(message)}`);
@@ -223,7 +225,12 @@ export class CellHandler {
223
225
  type: "tool-reply",
224
226
  callId: message.callId,
225
227
  ok: false,
226
- error: { message: text },
228
+ error: {
229
+ message: text,
230
+ ...(error instanceof Error && "code" in error && typeof error.code === "string"
231
+ ? { code: error.code }
232
+ : {}),
233
+ },
227
234
  });
228
235
  }
229
236
  this.#resultBuilder.emitUpdate(false);
@@ -1,7 +1,8 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { join } from "node:path";
3
- import type { AgentToolResult, ExtensionContext } from "@code-yeongyu/senpi";
3
+ import { type AgentToolResult, type ExtensionContext, kernelToolsStorage } from "@code-yeongyu/senpi";
4
4
  import { DEFAULT_FOREGROUND_WINDOW_SECONDS, defaultCodemodeSettings } from "../config/settings.ts";
5
+ import type { KernelToolsCapability } from "../kernels/js/kernel-tools-types.ts";
5
6
  import { TIMEOUT_PAUSE_OP, TIMEOUT_RESUME_OP } from "../timeouts/bridge-timeout.ts";
6
7
  import { abortError, CellExecution, defaultTimeoutFactory } from "./cell-execution.ts";
7
8
  import { CellHandler, type CellState } from "./cell-handler.ts";
@@ -11,7 +12,7 @@ import { buildEvalExecutionEventPayload, type EvalExecutionSettleOutcome } from
11
12
  import { evalTimeoutBehavior } from "./eval-request.ts";
12
13
  import type { CreateEvalToolOptions, EvalCellInvocation } from "./eval-tool-options.ts";
13
14
  import { describeTimeoutState } from "./interrupt-note.ts";
14
- import type { EvalToolDetails } from "./types.ts";
15
+ import type { EvalKernel, EvalToolDetails } from "./types.ts";
15
16
 
16
17
  export async function runEvalCell(
17
18
  options: CreateEvalToolOptions,
@@ -166,34 +167,39 @@ async function executeCell(
166
167
  void pending.catch((error: unknown) => execution.cancel(error));
167
168
  }),
168
169
  );
169
- execution.setKernel(kernel);
170
- const activeHandler = new CellHandler(kernel, state, {
171
- executeTool: options.executeTool,
172
- ...(options.listTools === undefined ? {} : { listTools: options.listTools }),
173
- settings: options.settings ?? defaultCodemodeSettings,
174
- ...(options.complete === undefined ? {} : { complete: options.complete }),
175
- ctx: bridgeContext,
176
- ...(options.artifactsDir === undefined
177
- ? {}
178
- : { artifactPath: join(options.artifactsDir, `eval-${randomUUID()}.log`) }),
179
- ...(options.imageResizer === undefined ? {} : { imageResizer: options.imageResizer }),
180
- });
181
- handler = activeHandler;
182
- cellManager.markRunning(
183
- cell,
184
- kernel,
185
- () => activeHandler.liveResult(),
186
- (error) => execution.cancel(error),
187
- );
188
- // Includes a steer already queued at execute start or received while acquiring the kernel.
189
- onReady();
190
- if ("setContext" in options.kernelManager && typeof options.kernelManager.setContext === "function") {
191
- options.kernelManager.setContext(bridgeContext);
192
- }
193
- if (invocation.input.reset) await execution.wait(kernel.reset());
194
- const result = await execution.wait(kernel.run({ cellId: invocation.cellId, code: invocation.input.code }));
195
- if (result.ok && state.pendingBridgeCalls.length > 0) await execution.wait(Promise.all(state.pendingBridgeCalls));
196
- return await handler.finalize(result);
170
+ const runBound = async (): Promise<AgentToolResult<EvalToolDetails>> => {
171
+ execution.setKernel(kernel);
172
+ const activeHandler = new CellHandler(kernel, state, {
173
+ executeTool: options.executeTool,
174
+ ...(options.listTools === undefined ? {} : { listTools: options.listTools }),
175
+ settings: options.settings ?? defaultCodemodeSettings,
176
+ ...(options.complete === undefined ? {} : { complete: options.complete }),
177
+ ctx: bridgeContext,
178
+ ...(options.artifactsDir === undefined
179
+ ? {}
180
+ : { artifactPath: join(options.artifactsDir, `eval-${randomUUID()}.log`) }),
181
+ ...(options.imageResizer === undefined ? {} : { imageResizer: options.imageResizer }),
182
+ });
183
+ handler = activeHandler;
184
+ cellManager.markRunning(
185
+ cell,
186
+ kernel,
187
+ () => activeHandler.liveResult(),
188
+ (error) => execution.cancel(error),
189
+ );
190
+ // Includes a steer already queued at execute start or received while acquiring the kernel.
191
+ onReady();
192
+ if ("setContext" in options.kernelManager && typeof options.kernelManager.setContext === "function") {
193
+ options.kernelManager.setContext(bridgeContext);
194
+ }
195
+ if (invocation.input.reset) await execution.wait(kernel.reset());
196
+ const result = await execution.wait(kernel.run({ cellId: invocation.cellId, code: invocation.input.code }));
197
+ if (result.ok && state.pendingBridgeCalls.length > 0)
198
+ await execution.wait(Promise.all(state.pendingBridgeCalls));
199
+ return await handler.finalize(result);
200
+ };
201
+ const kernelTools = jsKernelTools(kernel, invocation.input.language);
202
+ return kernelTools ? await kernelToolsStorage.run(kernelTools, runBound) : await runBound();
197
203
  } catch (error) {
198
204
  if (handler && error instanceof Error && error.name === "CodemodeSessionDisposedError")
199
205
  return await handler.finalizeCancellation(error);
@@ -206,3 +212,16 @@ async function executeCell(
206
212
  if (handler) await handler.flushOutput();
207
213
  }
208
214
  }
215
+
216
+ function jsKernelTools(kernel: EvalKernel, language: string): KernelToolsCapability | undefined {
217
+ if (language !== "js") return undefined;
218
+ if (!("describeKernelTools" in kernel) || typeof kernel.describeKernelTools !== "function") return undefined;
219
+ const js = kernel as EvalKernel & {
220
+ describeKernelTools: KernelToolsCapability["describe"];
221
+ invokeKernelTool: KernelToolsCapability["invoke"];
222
+ };
223
+ return {
224
+ describe: (names) => js.describeKernelTools(names),
225
+ invoke: (request, signal) => js.invokeKernelTool(request, signal),
226
+ };
227
+ }
package/src/tool/types.ts CHANGED
@@ -132,6 +132,8 @@ export interface EvalKernel {
132
132
  deliverToolReply(message: Extract<HostToKernelMessage, { type: "tool-reply" }>): void;
133
133
  reset(): Promise<void>;
134
134
  close(): Promise<void>;
135
+ /** Names this kernel has registered; JS collides with other languages in the same session. */
136
+ listKernelToolNames?(): readonly string[];
135
137
  }
136
138
 
137
139
  export interface EvalKernelManager {