@agimon-ai/po-codemode 0.0.1-alpha.1 → 0.0.1-alpha.10

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/README.md CHANGED
@@ -19,26 +19,38 @@ The package declares poServer metadata for native server discovery. Include it t
19
19
 
20
20
  ## Use
21
21
 
22
- Run the registered command in the cockpit:
22
+ Call `discover({})` to list the session's contributed namespaces and reusable scripts. Use `exec` to run a TypeScript async function body against them.
23
23
 
24
- ```text
25
- /po-codemode
26
- ```
24
+ ## Package behavior
27
25
 
28
- Show code mode namespaces
26
+ Call `discover({ namespace: 'browser' })` for current types, then `exec({ code: 'return await browser.snapshot({});' })`. Namespace plugins supply their own `codemode-how-to-<plugin>` guides. Their summaries and the base `how-to-codemode` guide stay in the system prompt, outside skill search; `load_skill` still reads their full instructions by exact name.
29
27
 
30
- ## Package behavior
28
+ ### npm imports
29
+
30
+ On Node hosts, `await import('npm:is-number@7')` auto-installs through upm and returns the real module namespace. Registry names, scopes, versions, ranges, tags and subpaths are supported. The shared store uses the existing two-day release-age policy (exact and locked versions bypass it); lifecycle scripts are skipped. First installs may need a larger exec `timeoutMs`.
31
+
32
+ Packages run with full Node authority. Native code is not preemptible, package resources are not automatically closed, and cancellation cannot stop an install already in progress. `new` works on imported constructors; subclassing and `instanceof` are unsupported. Edge hosts cannot import. Script globals still omit `fetch`, `require` and `process`.
33
+
34
+ ### Short Bash commands
35
+
36
+ `shell.bash({ command, timeoutMs? })` returns `{ stdout, stderr, exitCode }` for code-side post-processing. It runs in the session cwd with its admitted environment. Nonzero exits are returned; startup failures, timeout and cancellation reject. The deadline defaults to 10 seconds (maximum 120 seconds) and the command is cancelled when exec ends. Each output stream is capped at 32768 characters with a `[truncated]` marker.
37
+
38
+ This is foreground-only execution, not Runner supervision: no background option, interactive terminal, Runner IDs or persistent logs. The standalone Runner `bash` tool remains visible for those workflows. See [shell guidance](./src/prompts/codemode-how-to-shell/SKILL.md).
39
+
40
+ ### LLM transformations
41
+
42
+ `llm.complete({ prompt, input? })` returns `{ text, model }`; `llm.json({ prompt, input?, schema })` returns `{ value, model }`. Calls are stateless, use no session history, and count toward session usage. JSON results require one private `return_result` call and local schema validation; tool choice is prompt-directed.
31
43
 
32
- > Before publishing, replace this paragraph with one concrete, copy-pasteable example of the package-specific input, output, configuration, or workflow that is not already demonstrated by the generated command.
44
+ Set the optional `llmModel: provider/id` in the `@agimon-ai/po-codemode` package configuration to choose a default. A per-call `model` wins, otherwise the current session model is used. Limits per exec are 8 calls and 2 concurrent calls, with 64 KiB input per call and 1024 default / 4096 maximum output tokens. There are no retries. See [LLM guidance](./src/prompts/codemode-how-to-llm/SKILL.md) for pipelines and schema constraints.
33
45
 
34
- ## Help
46
+ ## How-to guide
35
47
 
36
- The published package includes `llms.txt` and `src/prompts/po-use-codemode/SKILL.md`. Link additional prompts from `llms.txt` and declare them through named `resource/*.server.ts` routes using `defineResource`. Server lifecycle registration owns their disposal. Publish prompts under `src/prompts`, never export Markdown or copy it into `dist`.
48
+ The published package includes `llms.txt` and `src/prompts/how-to-codemode/SKILL.md`. Link additional prompts from `llms.txt` and declare them through named `resource/*.server.ts` routes using `defineResource`. Server lifecycle registration owns their disposal. Publish prompts under `src/prompts`, never export Markdown or copy it into `dist`.
37
49
 
38
50
  ## Public API
39
51
 
40
52
  ```ts
41
- import { DefaultCodemodeExtensionService } from '@agimon-ai/po-codemode';
53
+ import { createCodemodeRegistry, createCodemodeTools } from '@agimon-ai/po-codemode';
42
54
  ```
43
55
 
44
56
  The native server entry is also available at:
@@ -1,4 +1,5 @@
1
1
  let _agimon_ai_po_core_codemode = require("@agimon-ai/po-core/codemode");
2
+ let _agimon_ai_po_core_headless = require("@agimon-ai/po-core/headless");
2
3
  let typebox = require("typebox");
3
4
  //#region src/services/codemodeRegistry/index.ts
4
5
  /** The session's namespaces and script folders, in registration order. One name per session. */
@@ -57,15 +58,36 @@ const ExecToolSchema = typebox.Type.Object({
57
58
  description: "Deadline in milliseconds. Default 30000."
58
59
  }))
59
60
  });
61
+ const ExecBackgroundToolSchema = typebox.Type.Object({
62
+ code: ExecToolSchema.properties.code,
63
+ timeoutMs: typebox.Type.Optional(typebox.Type.Integer({
64
+ minimum: 1e3,
65
+ maximum: 72e5,
66
+ description: "Deadline in milliseconds. Default 1800000 (30 minutes), maximum 2 hours."
67
+ }))
68
+ });
69
+ const ExecCancelToolSchema = typebox.Type.Object({
70
+ id: typebox.Type.String({
71
+ minLength: 1,
72
+ description: "The background exec ID returned by exec_background."
73
+ }),
74
+ reason: typebox.Type.Optional(typebox.Type.String({ maxLength: 256 }))
75
+ });
60
76
  //#endregion
61
77
  //#region src/services/codemodeTools/index.ts
62
78
  const DEFAULT_TIMEOUT_MS = 3e4;
63
79
  const MAX_TIMEOUT_MS = 12e4;
64
80
  const MIN_TIMEOUT_MS = 1e3;
81
+ const BACKGROUND_DEFAULT_TIMEOUT_MS = 18e5;
82
+ const BACKGROUND_MAX_TIMEOUT_MS = 72e5;
65
83
  const MAX_LOG_CHARS = 1e4;
66
84
  const MAX_VALUE_CHARS = 65536;
67
- const MAX_DECLARATION_CHARS = 12e3;
85
+ const MAX_DECLARATION_CHARS = 24e3;
68
86
  const MAX_QUERY_LINES = 40;
87
+ const MAX_CONCURRENT_RUNS = 8;
88
+ const MAX_RECORDED_CALLS = 50;
89
+ const MAX_RECORDED_TEXT = 8e3;
90
+ const MAX_RECORDED_JSON = 16e3;
69
91
  const MAX_LISTED_SCRIPTS = 20;
70
92
  const MAX_IMAGES = 4;
71
93
  const MAX_IMAGE_BYTES = 5242880;
@@ -95,7 +117,8 @@ function format(value) {
95
117
  }
96
118
  function memberNames(namespace) {
97
119
  const names = /* @__PURE__ */ new Set();
98
- for (const line of namespace.declarations.split("\n")) {
120
+ const declaration = new RegExp(`^declare const ${namespace.name}: \\{([\\s\\S]*?)^\\};`, "mu").exec(namespace.declarations)?.[1] ?? "";
121
+ for (const line of declaration.split("\n")) {
99
122
  const name = MEMBER_LINE.exec(line)?.[1];
100
123
  if (name) names.add(name);
101
124
  }
@@ -132,6 +155,8 @@ function createOutput() {
132
155
  if (images.length >= MAX_IMAGES) throw new RangeError(`An exec run returns at most ${MAX_IMAGES} images.`);
133
156
  imageBytes += Math.ceil(data.length * 3 / 4);
134
157
  if (imageBytes > MAX_IMAGE_BYTES) throw new RangeError("Images from one exec run exceed 5 MB.");
158
+ const invalid = (0, _agimon_ai_po_core_headless.invalidImageReason)(data, mime);
159
+ if (invalid !== void 0) throw new TypeError(`image() rejected an undecodable image: ${invalid}.`);
135
160
  images.push({
136
161
  data,
137
162
  mimeType: mime
@@ -155,7 +180,39 @@ function createOutput() {
155
180
  function activeDomains(execution) {
156
181
  return execution?.selection?.domains;
157
182
  }
158
- function toResult(result, output, saved) {
183
+ /** A JSON copy of `value`, or undefined when it does not serialise or is larger than `limit` characters. */
184
+ function bounded(value, limit) {
185
+ try {
186
+ const json = JSON.stringify(value);
187
+ return json !== void 0 && json.length <= limit ? JSON.parse(json) : void 0;
188
+ } catch {
189
+ return;
190
+ }
191
+ }
192
+ /** The call as it is kept in the transcript: text blocks only, clipped, with args and details dropped when large. */
193
+ function recordedCall(call) {
194
+ const content = (call.result?.content ?? []).flatMap((block) => {
195
+ const { type, text } = block ?? {};
196
+ return type === "text" && typeof text === "string" ? [{
197
+ type: "text",
198
+ text: truncate(text, MAX_RECORDED_TEXT)
199
+ }] : [];
200
+ });
201
+ const details = bounded(call.result?.details, MAX_RECORDED_JSON);
202
+ return {
203
+ name: call.name,
204
+ tool: call.tool,
205
+ args: bounded(call.args, MAX_RECORDED_JSON) ?? {},
206
+ ok: call.ok,
207
+ ms: Math.max(0, Math.round(call.ms)),
208
+ ...call.error === void 0 ? {} : { error: truncate(call.error, MAX_RECORDED_TEXT) },
209
+ ...call.result === void 0 ? {} : { result: {
210
+ content,
211
+ ...details === void 0 ? {} : { details }
212
+ } }
213
+ };
214
+ }
215
+ function toResult(result, output, saved, calls) {
159
216
  const content = [];
160
217
  if (output.lines.length > 0) content.push({
161
218
  type: "text",
@@ -193,23 +250,162 @@ function toResult(result, output, saved) {
193
250
  });
194
251
  return {
195
252
  content,
253
+ ...calls.length > 0 ? { details: { calls } } : {},
196
254
  ...result.ok ? {} : { isError: true }
197
255
  };
198
256
  }
199
257
  function sleep(ms, signal) {
200
258
  return new Promise((resolve, reject) => {
201
259
  if (signal.aborted) return reject(/* @__PURE__ */ new Error("Run ended."));
202
- const timer = setTimeout(resolve, Math.max(0, ms));
203
- signal.addEventListener("abort", () => {
260
+ const stop = () => {
204
261
  clearTimeout(timer);
205
262
  reject(/* @__PURE__ */ new Error("Run ended."));
206
- }, { once: true });
263
+ };
264
+ const timer = setTimeout(() => {
265
+ signal.removeEventListener("abort", stop);
266
+ resolve();
267
+ }, Math.max(0, ms));
268
+ signal.addEventListener("abort", stop, { once: true });
207
269
  });
208
270
  }
209
271
  /** `discover` and `exec` for one session, over the namespaces its packages contributed. */
210
- function createCodemodeTools({ registry, isolate, scripts }) {
211
- let busy = false;
272
+ function createCodemodeTools({ registry, isolate, scripts, npm, signal: lifecycleSignal, onBackgroundChange }) {
273
+ let running = 0;
274
+ let closing = false;
275
+ const lifecycle = new AbortController();
276
+ const ownerSignal = lifecycleSignal ? AbortSignal.any([lifecycle.signal, lifecycleSignal]) : lifecycle.signal;
277
+ const jobs = /* @__PURE__ */ new Map();
278
+ const backgroundWork = {
279
+ provider: "po-codemode-background",
280
+ listActiveWork: () => [...jobs.values()].map(({ id, sessionId, status }) => ({
281
+ id,
282
+ sessionId,
283
+ status,
284
+ label: "Background exec"
285
+ }))
286
+ };
212
287
  const visible = (service) => registry.list().filter((namespace) => service.liveObjects || namespace.portable === true);
288
+ const executeCode = async (parameters, signal, execution, deadlineMs) => {
289
+ const service = isolate();
290
+ if (!service) return text("Code mode is not available on this host.", true);
291
+ if (closing || ownerSignal.aborted) return text("Code mode session is disposing.", true);
292
+ if (running >= MAX_CONCURRENT_RUNS) return text(`This session already has ${MAX_CONCURRENT_RUNS} exec runs active. Wait for one to finish.`, true);
293
+ running += 1;
294
+ const controller = new AbortController();
295
+ const runSignal = AbortSignal.any([
296
+ ownerSignal,
297
+ controller.signal,
298
+ ...signal ? [signal] : []
299
+ ]);
300
+ const cleanups = [];
301
+ const calls = [];
302
+ const output = createOutput();
303
+ const run = {
304
+ sessionId: execution.sessionId,
305
+ signal: runSignal,
306
+ onDispose: (cleanup) => void cleanups.push(cleanup),
307
+ record: (call) => {
308
+ if (calls.length < MAX_RECORDED_CALLS) calls.push(recordedCall(call));
309
+ }
310
+ };
311
+ let saved;
312
+ let result = {
313
+ ok: true,
314
+ value: void 0
315
+ };
316
+ try {
317
+ runSignal.throwIfAborted();
318
+ try {
319
+ const file = await scripts?.save(parameters.code);
320
+ if (file) saved = `Saved as ${file.specifier} (${file.path})`;
321
+ } catch (error) {
322
+ output.note(`Could not save the script: ${error instanceof Error ? error.message : String(error)}`);
323
+ }
324
+ runSignal.throwIfAborted();
325
+ const globals = {
326
+ console: output.console,
327
+ image: output.addImage,
328
+ sleep: (ms) => sleep(ms, runSignal)
329
+ };
330
+ const deny = /* @__PURE__ */ new Set();
331
+ for (const namespace of visible(service)) {
332
+ globals[namespace.name] = namespace.bind(run);
333
+ for (const member of namespace.deny ?? []) deny.add(member);
334
+ }
335
+ result = await service.run({
336
+ source: parameters.code,
337
+ globals,
338
+ deadlineMs,
339
+ signal: runSignal,
340
+ deny: [...deny],
341
+ onDiagnostic: output.note,
342
+ resolveImport: async (specifier) => {
343
+ if (!specifier.startsWith("npm:")) {
344
+ if (!scripts) throw new Error("Script imports are not available on this host.");
345
+ return scripts.resolve(specifier, activeDomains(execution));
346
+ }
347
+ const loader = npm?.();
348
+ if (!loader) throw new Error("npm imports are not available on this host.");
349
+ run.signal.throwIfAborted();
350
+ const started = Date.now();
351
+ try {
352
+ const exports = await loader.import(specifier, {
353
+ sessionId: run.sessionId,
354
+ signal: run.signal
355
+ });
356
+ run.signal.throwIfAborted();
357
+ run.record?.({
358
+ name: "npm.import",
359
+ tool: "npm",
360
+ args: { specifier },
361
+ ms: Date.now() - started,
362
+ ok: true
363
+ });
364
+ return {
365
+ kind: "module",
366
+ id: specifier,
367
+ exports
368
+ };
369
+ } catch (error) {
370
+ run.record?.({
371
+ name: "npm.import",
372
+ tool: "npm",
373
+ args: { specifier },
374
+ ms: Date.now() - started,
375
+ ok: false,
376
+ error: error instanceof Error ? error.message : String(error)
377
+ });
378
+ throw error;
379
+ }
380
+ }
381
+ });
382
+ } catch (error) {
383
+ result = {
384
+ ok: false,
385
+ error: {
386
+ kind: "error",
387
+ name: "Error",
388
+ message: `Code mode could not run the script: ${error instanceof Error ? error.message : String(error)}`
389
+ }
390
+ };
391
+ } finally {
392
+ controller.abort();
393
+ for (const cleanup of cleanups.reverse()) await Promise.resolve().then(cleanup).catch((error) => {
394
+ const message = `Code mode cleanup failed: ${String(error)}`;
395
+ output.note(message);
396
+ result = {
397
+ ok: false,
398
+ error: {
399
+ kind: "error",
400
+ name: "CleanupError",
401
+ message
402
+ }
403
+ };
404
+ });
405
+ running -= 1;
406
+ }
407
+ return toResult(result, output, saved, calls);
408
+ };
213
409
  return {
214
410
  discover: {
215
411
  name: "discover",
@@ -280,55 +476,115 @@ function createCodemodeTools({ registry, isolate, scripts }) {
280
476
  promptSnippet: "Run a TypeScript script against live Po objects (browser and other namespaces)",
281
477
  executionMode: "serial",
282
478
  async execute(_toolCallId, parameters, signal, _onUpdate, execution) {
283
- const service = isolate();
284
- if (!service) return text("Code mode is not available on this host.", true);
285
- if (busy) return text("Another exec run is still active in this session. Wait for it to finish.", true);
286
- busy = true;
479
+ return executeCode(parameters, signal, execution, Math.min(MAX_TIMEOUT_MS, Math.max(MIN_TIMEOUT_MS, parameters.timeoutMs ?? DEFAULT_TIMEOUT_MS)));
480
+ }
481
+ },
482
+ execBackground: {
483
+ name: "exec_background",
484
+ label: "Background Exec",
485
+ description: "Run a long-lived Node code-mode script. Returns its ID immediately; one completion message arrives after execution and cleanup. End the turn rather than polling. Full server trust, like exec.",
486
+ parameters: ExecBackgroundToolSchema,
487
+ mainAgentOnly: true,
488
+ executionMode: "serial",
489
+ async execute(_toolCallId, parameters, signal, _onUpdate, execution) {
490
+ if (signal?.aborted) return text("Background exec launch was aborted.", true);
491
+ if (closing || ownerSignal.aborted) return text("Code mode session is disposing.", true);
492
+ if (!isolate()?.liveObjects) return text("Background exec requires a Node host with live objects.", true);
493
+ if (!execution.session?.admitMessage) return text("This session cannot admit background exec completion messages.", true);
494
+ if (running >= MAX_CONCURRENT_RUNS) return text(`This session already has ${MAX_CONCURRENT_RUNS} exec runs active. Wait for one to finish.`, true);
495
+ const deadlineMs = Math.min(BACKGROUND_MAX_TIMEOUT_MS, Math.max(MIN_TIMEOUT_MS, parameters.timeoutMs ?? BACKGROUND_DEFAULT_TIMEOUT_MS));
496
+ const id = crypto.randomUUID();
287
497
  const controller = new AbortController();
288
- const runSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
289
- const cleanups = [];
290
- const output = createOutput();
291
- const run = {
498
+ const job = {
499
+ id,
292
500
  sessionId: execution.sessionId,
293
- signal: runSignal,
294
- onDispose: (cleanup) => void cleanups.push(cleanup)
501
+ controller,
502
+ status: "running",
503
+ done: Promise.resolve()
295
504
  };
296
- try {
297
- let saved;
505
+ jobs.set(id, job);
506
+ onBackgroundChange?.();
507
+ job.done = (async () => {
508
+ let timedOut = false;
509
+ const timer = setTimeout(() => {
510
+ timedOut = true;
511
+ controller.abort();
512
+ }, deadlineMs);
298
513
  try {
299
- const file = await scripts?.save(parameters.code);
300
- if (file) saved = `Saved as ${file.specifier} (${file.path})`;
301
- } catch (error) {
302
- output.note(`Could not save the script: ${error instanceof Error ? error.message : String(error)}`);
514
+ const result = await executeCode(parameters, controller.signal, execution, deadlineMs);
515
+ clearTimeout(timer);
516
+ job.status = "reporting";
517
+ onBackgroundChange?.();
518
+ const status = timedOut ? "timed-out" : controller.signal.aborted ? "stopped" : result.isError ? "failed" : "completed";
519
+ const message = {
520
+ type: "po-codemode-finished",
521
+ text: `Background exec ${id} ${status}.\n${result.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("\n")}`,
522
+ display: true,
523
+ details: {
524
+ id,
525
+ status,
526
+ result
527
+ }
528
+ };
529
+ let warned = false;
530
+ while (!ownerSignal.aborted) {
531
+ let stopAdmission;
532
+ try {
533
+ const stopped = new Promise((resolve) => {
534
+ stopAdmission = resolve;
535
+ ownerSignal.addEventListener("abort", stopAdmission, { once: true });
536
+ if (ownerSignal.aborted) resolve();
537
+ });
538
+ await Promise.race([execution.session.admitMessage(message, "steer", `po-codemode-finished:${execution.sessionId}:${id}`), stopped]);
539
+ break;
540
+ } catch (error) {
541
+ if (ownerSignal.aborted) break;
542
+ if (!warned) {
543
+ warned = true;
544
+ await Promise.resolve().then(() => execution.client.notify({
545
+ body: `Background exec completion admission failed; retrying: ${String(error)}`,
546
+ level: "warning"
547
+ })).catch(() => void 0);
548
+ }
549
+ await sleep(250, ownerSignal).catch(() => void 0);
550
+ } finally {
551
+ if (stopAdmission) ownerSignal.removeEventListener("abort", stopAdmission);
552
+ }
553
+ }
554
+ } finally {
555
+ clearTimeout(timer);
556
+ jobs.delete(id);
557
+ onBackgroundChange?.();
303
558
  }
304
- const globals = {
305
- console: output.console,
306
- image: output.addImage,
307
- sleep: (ms) => sleep(ms, runSignal)
308
- };
309
- const deny = /* @__PURE__ */ new Set();
310
- for (const namespace of visible(service)) {
311
- globals[namespace.name] = namespace.bind(run);
312
- for (const member of namespace.deny ?? []) deny.add(member);
313
- }
314
- const deadlineMs = Math.min(MAX_TIMEOUT_MS, Math.max(MIN_TIMEOUT_MS, parameters.timeoutMs ?? DEFAULT_TIMEOUT_MS));
315
- return toResult(await service.run({
316
- source: parameters.code,
317
- globals,
318
- deadlineMs,
319
- signal: runSignal,
320
- deny: [...deny],
321
- onDiagnostic: output.note,
322
- ...scripts ? { resolveImport: (specifier) => scripts.resolve(specifier, activeDomains(execution)) } : {}
323
- }), output, saved);
324
- } catch (error) {
325
- return text(`Code mode could not run the script: ${error instanceof Error ? error.message : String(error)}`, true);
326
- } finally {
327
- controller.abort();
328
- for (const cleanup of cleanups.reverse()) await Promise.resolve().then(cleanup).catch((error) => output.note(`cleanup failed: ${String(error)}`));
329
- busy = false;
330
- }
559
+ })();
560
+ return {
561
+ ...text(JSON.stringify({ id })),
562
+ details: { id }
563
+ };
331
564
  }
565
+ },
566
+ execCancel: {
567
+ name: "exec_cancel",
568
+ label: "Cancel Exec",
569
+ description: "Cancel a background exec in this session. Its terminal message follows child cleanup.",
570
+ parameters: ExecCancelToolSchema,
571
+ mainAgentOnly: true,
572
+ executionMode: "serial",
573
+ async execute(_toolCallId, parameters, _signal, _onUpdate, execution) {
574
+ const job = jobs.get(parameters.id);
575
+ if (job && job.sessionId !== execution.sessionId) return text("Background exec belongs to another session.", true);
576
+ if (job?.status === "running") job.controller.abort(parameters.reason ? new Error(parameters.reason) : void 0);
577
+ return text(JSON.stringify({
578
+ id: parameters.id,
579
+ status: job?.status === "running" ? "stopping" : "finished"
580
+ }));
581
+ }
582
+ },
583
+ backgroundWork,
584
+ async dispose() {
585
+ closing = true;
586
+ lifecycle.abort();
587
+ await Promise.all([...jobs.values()].map((job) => job.done));
332
588
  }
333
589
  };
334
590
  }
@@ -346,4 +602,4 @@ Object.defineProperty(exports, "createCodemodeTools", {
346
602
  }
347
603
  });
348
604
 
349
- //# sourceMappingURL=codemodeTools-BX2qieCR.cjs.map
605
+ //# sourceMappingURL=codemodeTools-B3n6iodq.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codemodeTools-B3n6iodq.cjs","names":["Type","invalidImageReason"],"sources":["../src/services/codemodeRegistry/index.ts","../src/schemas/codemodeTools.ts","../src/services/codemodeTools/index.ts"],"sourcesContent":["import {\n assertCodemodeNamespaceName,\n type PoCodemodeNamespace,\n type PoCodemodeRegistration,\n type PoCodemodeScriptSource,\n type PoCodemodeService,\n} from '@agimon-ai/po-core/codemode';\n\n/** The session's namespaces and script folders, in registration order. One name per session. */\nexport function createCodemodeRegistry(): PoCodemodeService {\n const entries = new Map<string, { source: string; namespace: PoCodemodeNamespace }>();\n const scripts = new Set<PoCodemodeScriptSource>();\n const listeners = new Set<() => void>();\n const notify = (): void => {\n for (const listener of listeners) listener();\n };\n return {\n register(source: string, namespace: PoCodemodeNamespace): PoCodemodeRegistration {\n assertCodemodeNamespaceName(namespace.name);\n const taken = entries.get(namespace.name);\n if (taken) {\n throw new Error(\n `Code-mode namespace \"${namespace.name}\" from ${source} is already registered by ${taken.source}.`,\n );\n }\n const entry = { source, namespace };\n entries.set(namespace.name, entry);\n notify();\n return {\n dispose: () => {\n if (entries.get(namespace.name) !== entry) return;\n entries.delete(namespace.name);\n notify();\n },\n };\n },\n list: () => [...entries.values()].map((entry) => entry.namespace),\n registerScripts(_source: string, entry: PoCodemodeScriptSource): PoCodemodeRegistration {\n const owned = { domain: entry.domain, directory: entry.directory };\n scripts.add(owned);\n notify();\n return { dispose: () => void (scripts.delete(owned) && notify()) };\n },\n listScripts: () => [...scripts],\n subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n","import { Type, type Static } from 'typebox';\n\nexport const DiscoverToolSchema = Type.Object({\n namespace: Type.Optional(Type.String({ description: 'Show the full TypeScript declarations of one namespace.' })),\n query: Type.Optional(Type.String({ description: 'Find matching members across every namespace.' })),\n});\nexport type DiscoverToolParams = Static<typeof DiscoverToolSchema>;\n\nexport const ExecToolSchema = Type.Object({\n code: Type.String({\n description:\n 'TypeScript body of an async function. Top-level await and return work. The returned value, console output and image() calls come back.',\n }),\n timeoutMs: Type.Optional(\n Type.Integer({ minimum: 1_000, maximum: 120_000, description: 'Deadline in milliseconds. Default 30000.' }),\n ),\n});\nexport type ExecToolParams = Static<typeof ExecToolSchema>;\n\nexport const ExecBackgroundToolSchema = Type.Object({\n code: ExecToolSchema.properties.code,\n timeoutMs: Type.Optional(\n Type.Integer({\n minimum: 1_000,\n maximum: 7_200_000,\n description: 'Deadline in milliseconds. Default 1800000 (30 minutes), maximum 2 hours.',\n }),\n ),\n});\nexport type ExecBackgroundToolParams = Static<typeof ExecBackgroundToolSchema>;\n\nexport const ExecCancelToolSchema = Type.Object({\n id: Type.String({ minLength: 1, description: 'The background exec ID returned by exec_background.' }),\n reason: Type.Optional(Type.String({ maxLength: 256 })),\n});\nexport type ExecCancelToolParams = Static<typeof ExecCancelToolSchema>;\n","import type { BackgroundWorkProvider } from '@agimon-ai/po-core/backgroundWork';\nimport type {\n PoCodemodeCall,\n PoCodemodeNamespace,\n PoCodemodeRun,\n PoCodemodeService,\n} from '@agimon-ai/po-core/codemode';\nimport {\n invalidImageReason,\n type PoHeadlessContent,\n type PoHeadlessExecutionContext,\n type PoHeadlessTool,\n type PoHeadlessToolResult,\n} from '@agimon-ai/po-core/headless';\nimport type { PoIsolateResult, PoIsolateService, PoNpm } from '@agimon-ai/po-core/platform';\n\nimport {\n DiscoverToolSchema,\n ExecToolSchema,\n ExecBackgroundToolSchema,\n ExecCancelToolSchema,\n type DiscoverToolParams,\n type ExecToolParams,\n type ExecBackgroundToolParams,\n type ExecCancelToolParams,\n} from '../../schemas/codemodeTools';\nimport type { CodemodeScriptsPort } from '../codemodeScripts/type';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst MAX_TIMEOUT_MS = 120_000;\nconst MIN_TIMEOUT_MS = 1_000;\nconst BACKGROUND_DEFAULT_TIMEOUT_MS = 30 * 60_000;\nconst BACKGROUND_MAX_TIMEOUT_MS = 2 * 60 * 60_000;\nconst MAX_LOG_CHARS = 10_000;\nconst MAX_VALUE_CHARS = 64 * 1024;\nconst MAX_DECLARATION_CHARS = 24_000;\nconst MAX_QUERY_LINES = 40;\n// The main agent and its subagents share one exec tool, so several runs can overlap.\nconst MAX_CONCURRENT_RUNS = 8;\n// Recorded calls ride the result's details into the transcript, so they are few and small.\nconst MAX_RECORDED_CALLS = 50;\nconst MAX_RECORDED_TEXT = 8_000;\nconst MAX_RECORDED_JSON = 16_000;\nconst MAX_LISTED_SCRIPTS = 20;\nconst MAX_IMAGES = 4;\nconst MAX_IMAGE_BYTES = 5 * 1024 * 1024;\nconst DEFAULT_IMAGE_MIME = 'image/png';\nconst MEMBER_LINE = /^\\s{2}(?:readonly\\s+)?(\\w+)\\s*[(?:<]/u;\n\nconst GLOBALS_HELP =\n 'Globals: console.log/info/warn/error, image(data, mimeType?) to return a screenshot, sleep(ms). ' +\n 'Return a value with `return`.';\nconst SCRIPTS_HELP =\n 'Every exec run is saved. Call a saved script with `await (await import(specifier))(args)`; ' +\n 'inside it, `args` is the argument and its `return` is the result.';\n\nexport interface CodemodeToolsOptions {\n readonly registry: PoCodemodeService;\n /** Resolved per call, so a host that binds the isolate late still works. */\n readonly isolate: () => PoIsolateService | undefined;\n /** Saves every exec body and backs `import()`; without it nothing is saved or importable. */\n readonly scripts?: CodemodeScriptsPort;\n readonly npm?: () => PoNpm | undefined;\n readonly signal?: AbortSignal;\n readonly onBackgroundChange?: () => void;\n}\n\nexport interface CodemodeTools {\n readonly discover: PoHeadlessTool<typeof DiscoverToolSchema>;\n readonly exec: PoHeadlessTool<typeof ExecToolSchema>;\n readonly execBackground: PoHeadlessTool<typeof ExecBackgroundToolSchema>;\n readonly execCancel: PoHeadlessTool<typeof ExecCancelToolSchema>;\n readonly backgroundWork: BackgroundWorkProvider;\n dispose(): Promise<void>;\n}\n\ninterface BackgroundExec {\n readonly id: string;\n readonly sessionId: string;\n readonly controller: AbortController;\n status: 'running' | 'reporting';\n done: Promise<void>;\n}\n\nfunction text(value: string, isError = false): PoHeadlessToolResult {\n return { content: [{ type: 'text', text: value }], ...(isError ? { isError: true } : {}) };\n}\n\nfunction truncate(value: string, limit: number): string {\n return value.length <= limit ? value : `${value.slice(0, limit)}\\n[truncated ${value.length - limit} chars]`;\n}\n\nfunction format(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n const json = JSON.stringify(value, null, 2);\n if (json !== undefined) return json;\n } catch {\n // Cyclic or exotic values fall back to their string form.\n }\n return String(value);\n}\n\nfunction memberNames(namespace: PoCodemodeNamespace): string[] {\n const names = new Set<string>();\n const declaration =\n new RegExp(`^declare const ${namespace.name}: \\\\{([\\\\s\\\\S]*?)^\\\\};`, 'mu').exec(namespace.declarations)?.[1] ?? '';\n for (const line of declaration.split('\\n')) {\n const name = MEMBER_LINE.exec(line)?.[1];\n if (name) names.add(name);\n }\n return [...names];\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n for (let index = 0; index < bytes.length; index += 0x8000) {\n binary += String.fromCharCode(...bytes.subarray(index, index + 0x8000));\n }\n return btoa(binary);\n}\n\n/** Collects what a script prints and the images it returns, within the output caps. */\nfunction createOutput() {\n const lines: string[] = [];\n const images: { data: string; mimeType: string }[] = [];\n let imageBytes = 0;\n const log =\n (level: string) =>\n (...args: unknown[]) => {\n const line = args.map(format).join(' ');\n lines.push(level === 'log' || level === 'info' ? line : `[${level}] ${line}`);\n };\n const note = (message: string): void => void lines.push(`[note] ${message}`);\n const addImage = (input: unknown, mimeType?: unknown): void => {\n if (typeof input === 'object' && input !== null && 'images' in input && Array.isArray(input.images)) {\n for (const image of input.images) addImage(image);\n return;\n }\n let data: string;\n let mime = typeof mimeType === 'string' ? mimeType : DEFAULT_IMAGE_MIME;\n if (typeof input === 'string')\n data = input.replace(/^data:([^;]+);base64,/u, (_match, type: string) => ((mime = type), ''));\n else if (ArrayBuffer.isView(input))\n data = bytesToBase64(new Uint8Array(input.buffer, input.byteOffset, input.byteLength));\n else if (typeof input === 'object' && input !== null && 'data' in input && typeof input.data === 'string') {\n data = input.data;\n if ('mimeType' in input && typeof input.mimeType === 'string') mime = input.mimeType;\n } else throw new TypeError('image() takes base64 text, bytes, or { data, mimeType }.');\n if (images.length >= MAX_IMAGES) throw new RangeError(`An exec run returns at most ${MAX_IMAGES} images.`);\n imageBytes += Math.ceil((data.length * 3) / 4);\n if (imageBytes > MAX_IMAGE_BYTES) throw new RangeError('Images from one exec run exceed 5 MB.');\n const invalid = invalidImageReason(data, mime);\n if (invalid !== undefined) throw new TypeError(`image() rejected an undecodable image: ${invalid}.`);\n images.push({ data, mimeType: mime });\n };\n const console = { log: log('log'), info: log('info'), warn: log('warn'), error: log('error'), debug: log('debug') };\n return { console, note, addImage, lines, images };\n}\n\n/** The session's active domains; every registered domain when the host reports none. */\nfunction activeDomains(execution: PoHeadlessExecutionContext | undefined): readonly string[] | undefined {\n return execution?.selection?.domains;\n}\n\n/** A JSON copy of `value`, or undefined when it does not serialise or is larger than `limit` characters. */\nfunction bounded<T>(value: T, limit: number): T | undefined {\n try {\n const json = JSON.stringify(value);\n return json !== undefined && json.length <= limit ? (JSON.parse(json) as T) : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The call as it is kept in the transcript: text blocks only, clipped, with args and details dropped when large. */\nfunction recordedCall(call: PoCodemodeCall): PoCodemodeCall {\n const content = (call.result?.content ?? []).flatMap((block) => {\n const { type, text } = (block ?? {}) as { type?: unknown; text?: unknown };\n return type === 'text' && typeof text === 'string'\n ? [{ type: 'text', text: truncate(text, MAX_RECORDED_TEXT) }]\n : [];\n });\n const details = bounded(call.result?.details, MAX_RECORDED_JSON);\n return {\n name: call.name,\n tool: call.tool,\n args: bounded(call.args, MAX_RECORDED_JSON) ?? {},\n ok: call.ok,\n ms: Math.max(0, Math.round(call.ms)),\n ...(call.error === undefined ? {} : { error: truncate(call.error, MAX_RECORDED_TEXT) }),\n ...(call.result === undefined ? {} : { result: { content, ...(details === undefined ? {} : { details }) } }),\n };\n}\n\nfunction toResult(\n result: PoIsolateResult,\n output: ReturnType<typeof createOutput>,\n saved: string | undefined,\n calls: readonly PoCodemodeCall[],\n): PoHeadlessToolResult {\n const content: PoHeadlessContent[] = [];\n if (output.lines.length > 0) content.push({ type: 'text', text: truncate(output.lines.join('\\n'), MAX_LOG_CHARS) });\n if (result.ok) {\n if (ArrayBuffer.isView(result.value)) {\n content.push({ type: 'text', text: 'The script returned bytes. Pass them to image(data, mimeType) instead.' });\n } else if (result.value !== undefined) {\n content.push({ type: 'text', text: truncate(format(result.value), MAX_VALUE_CHARS) });\n }\n } else {\n const { kind, name, message } = result.error;\n const hint = kind === 'timeout' ? ' Raise timeoutMs or split the work into smaller exec calls.' : '';\n content.push({ type: 'text', text: `${name}: ${message}${hint}` });\n }\n if (content.length === 0) content.push({ type: 'text', text: '(no return value)' });\n if (saved !== undefined) content.push({ type: 'text', text: saved });\n for (const image of output.images) content.push({ type: 'image', data: image.data, mimeType: image.mimeType });\n return {\n content,\n ...(calls.length > 0 ? { details: { calls } } : {}),\n ...(result.ok ? {} : { isError: true }),\n };\n}\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) return reject(new Error('Run ended.'));\n const stop = () => {\n clearTimeout(timer);\n reject(new Error('Run ended.'));\n };\n const timer = setTimeout(\n () => {\n signal.removeEventListener('abort', stop);\n resolve();\n },\n Math.max(0, ms),\n );\n signal.addEventListener('abort', stop, { once: true });\n });\n}\n\n/** `discover` and `exec` for one session, over the namespaces its packages contributed. */\nexport function createCodemodeTools({\n registry,\n isolate,\n scripts,\n npm,\n signal: lifecycleSignal,\n onBackgroundChange,\n}: CodemodeToolsOptions): CodemodeTools {\n let running = 0;\n let closing = false;\n const lifecycle = new AbortController();\n const ownerSignal = lifecycleSignal ? AbortSignal.any([lifecycle.signal, lifecycleSignal]) : lifecycle.signal;\n const jobs = new Map<string, BackgroundExec>();\n const backgroundWork: BackgroundWorkProvider = {\n provider: 'po-codemode-background',\n listActiveWork: () =>\n [...jobs.values()].map(({ id, sessionId, status }) => ({ id, sessionId, status, label: 'Background exec' })),\n };\n\n const visible = (service: PoIsolateService): PoCodemodeNamespace[] =>\n registry.list().filter((namespace) => service.liveObjects || namespace.portable === true);\n\n const executeCode = async (\n parameters: ExecToolParams,\n signal: AbortSignal | undefined,\n execution: PoHeadlessExecutionContext,\n deadlineMs: number,\n ): Promise<PoHeadlessToolResult> => {\n const service = isolate();\n if (!service) return text('Code mode is not available on this host.', true);\n if (closing || ownerSignal.aborted) return text('Code mode session is disposing.', true);\n if (running >= MAX_CONCURRENT_RUNS)\n return text(`This session already has ${MAX_CONCURRENT_RUNS} exec runs active. Wait for one to finish.`, true);\n running += 1;\n const controller = new AbortController();\n const runSignal = AbortSignal.any([ownerSignal, controller.signal, ...(signal ? [signal] : [])]);\n const cleanups: (() => void | Promise<void>)[] = [];\n const calls: PoCodemodeCall[] = [];\n const output = createOutput();\n const run: PoCodemodeRun = {\n sessionId: execution.sessionId,\n signal: runSignal,\n onDispose: (cleanup) => void cleanups.push(cleanup),\n record: (call) => {\n if (calls.length < MAX_RECORDED_CALLS) calls.push(recordedCall(call));\n },\n };\n let saved: string | undefined;\n let result: PoIsolateResult = { ok: true, value: undefined };\n try {\n runSignal.throwIfAborted();\n try {\n const file = await scripts?.save(parameters.code);\n if (file) saved = `Saved as ${file.specifier} (${file.path})`;\n } catch (error) {\n output.note(`Could not save the script: ${error instanceof Error ? error.message : String(error)}`);\n }\n runSignal.throwIfAborted();\n const globals: Record<string, unknown> = {\n console: output.console,\n image: output.addImage,\n sleep: (ms: number) => sleep(ms, runSignal),\n };\n const deny = new Set<string>();\n for (const namespace of visible(service)) {\n globals[namespace.name] = namespace.bind(run);\n for (const member of namespace.deny ?? []) deny.add(member);\n }\n result = await service.run({\n source: parameters.code,\n globals,\n deadlineMs,\n signal: runSignal,\n deny: [...deny],\n onDiagnostic: output.note,\n resolveImport: async (specifier) => {\n if (!specifier.startsWith('npm:')) {\n if (!scripts) throw new Error('Script imports are not available on this host.');\n return scripts.resolve(specifier, activeDomains(execution));\n }\n const loader = npm?.();\n if (!loader) throw new Error('npm imports are not available on this host.');\n run.signal.throwIfAborted();\n const started = Date.now();\n try {\n const exports = await loader.import(specifier, { sessionId: run.sessionId, signal: run.signal });\n run.signal.throwIfAborted();\n run.record?.({ name: 'npm.import', tool: 'npm', args: { specifier }, ms: Date.now() - started, ok: true });\n return { kind: 'module', id: specifier, exports };\n } catch (error) {\n run.record?.({\n name: 'npm.import',\n tool: 'npm',\n args: { specifier },\n ms: Date.now() - started,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n },\n });\n } catch (error) {\n result = {\n ok: false,\n error: {\n kind: 'error',\n name: 'Error',\n message: `Code mode could not run the script: ${error instanceof Error ? error.message : String(error)}`,\n },\n };\n } finally {\n controller.abort();\n for (const cleanup of cleanups.reverse()) {\n await Promise.resolve()\n .then(cleanup)\n .catch((error: unknown) => {\n const message = `Code mode cleanup failed: ${String(error)}`;\n output.note(message);\n result = { ok: false, error: { kind: 'error', name: 'CleanupError', message } };\n });\n }\n running -= 1;\n }\n return toResult(result, output, saved, calls);\n };\n\n // ponytail: the cockpit's generic tool item renders both for now; add a poWeb renderer for exec code and images when it earns one.\n // web-plugin-tool-renderers: ignore discover, plain text result\n const discover: CodemodeTools['discover'] = {\n name: 'discover',\n label: 'Discover',\n description:\n 'List the code-mode namespaces and reusable scripts you can use from `exec`, show one namespace in full, ' +\n 'or search members and scripts. ' +\n 'Not required before exec: its description already names the namespaces.',\n parameters: DiscoverToolSchema,\n promptSnippet: 'List code-mode namespaces and their TypeScript declarations',\n executionMode: 'parallel',\n async execute(_toolCallId, parameters: DiscoverToolParams, _signal, _onUpdate, execution) {\n const service = isolate();\n if (!service) return text('Code mode is not available on this host.', true);\n const namespaces = visible(service);\n // Imports need a host with live objects; the edge saves scripts but cannot chain them.\n const listed = scripts && service.liveObjects ? await scripts.list(activeDomains(execution)) : [];\n if (parameters.namespace !== undefined) {\n const found = namespaces.find((namespace) => namespace.name === parameters.namespace);\n if (!found) {\n const names = namespaces.map((namespace) => namespace.name).join(', ') || 'none';\n return text(`Unknown namespace \"${parameters.namespace}\". Registered: ${names}.`, true);\n }\n return text(truncate(found.declarations, MAX_DECLARATION_CHARS));\n }\n if (parameters.query !== undefined) {\n const needle = parameters.query.toLowerCase();\n const hits: string[] = [];\n for (const namespace of namespaces) {\n const lines = namespace.declarations.split('\\n');\n lines.forEach((line, index) => {\n if (!line.toLowerCase().includes(needle) || hits.length >= MAX_QUERY_LINES) return;\n const doc = lines[index - 1]?.trim().startsWith('/**') ? `${lines[index - 1]?.trim()} ` : '';\n hits.push(`${namespace.name}: ${doc}${line.trim()}`);\n });\n }\n for (const script of listed) {\n if (hits.length >= MAX_QUERY_LINES) break;\n if (`${script.specifier} ${script.description}`.toLowerCase().includes(needle)) {\n hits.push(`script ${script.specifier}: ${script.description}`);\n }\n }\n return text(hits.length > 0 ? hits.join('\\n') : `No members or scripts match \"${parameters.query}\".`);\n }\n const sections: string[] = [];\n if (namespaces.length === 0) sections.push('No namespaces are registered in this session.');\n for (const namespace of namespaces) {\n sections.push(`- ${namespace.name}: ${namespace.summary}\\n members: ${memberNames(namespace).join(', ')}`);\n }\n sections.push(GLOBALS_HELP);\n if (!service.liveObjects) sections.push('This host runs plain JavaScript with JSON-only functions.');\n if (listed.length > 0) {\n sections.push(`Scripts. ${SCRIPTS_HELP}`);\n for (const script of listed.slice(0, MAX_LISTED_SCRIPTS)) {\n sections.push(`- ${script.specifier}${script.description ? `: ${script.description}` : ''}`);\n }\n if (listed.length > MAX_LISTED_SCRIPTS) {\n sections.push(`...and ${listed.length - MAX_LISTED_SCRIPTS} more; use discover({ query }) to search.`);\n }\n }\n if (namespaces.length > 0) sections.push('Call discover({ namespace }) for full types.');\n return text(sections.join('\\n'));\n },\n };\n\n // web-plugin-tool-renderers: ignore exec, generic item until a code and image renderer exists\n const exec: CodemodeTools['exec'] = {\n name: 'exec',\n label: 'Exec',\n get description(): string {\n const service = isolate();\n const namespaces = service ? visible(service) : [];\n const listed = namespaces.map((namespace) => `- ${namespace.name}: ${namespace.summary}`).join('\\n');\n return [\n 'Run a TypeScript script inside the Po server with live objects from the namespaces below in scope.',\n 'It runs with full server trust, like bash. Keep each call to one logical step.',\n listed || '(no namespaces registered yet; call discover to check)',\n GLOBALS_HELP,\n ...(scripts && service?.liveObjects ? [`${SCRIPTS_HELP} discover lists saved and domain scripts.`] : []),\n 'Use discover({ namespace }) for full signatures when needed.',\n ].join('\\n');\n },\n parameters: ExecToolSchema,\n promptSnippet: 'Run a TypeScript script against live Po objects (browser and other namespaces)',\n executionMode: 'serial',\n async execute(_toolCallId, parameters: ExecToolParams, signal, _onUpdate, execution) {\n return executeCode(\n parameters,\n signal,\n execution,\n Math.min(MAX_TIMEOUT_MS, Math.max(MIN_TIMEOUT_MS, parameters.timeoutMs ?? DEFAULT_TIMEOUT_MS)),\n );\n },\n };\n\n // web-plugin-tool-renderers: ignore exec_background, immediate job identity only\n const execBackground: CodemodeTools['execBackground'] = {\n name: 'exec_background',\n label: 'Background Exec',\n description:\n 'Run a long-lived Node code-mode script. Returns its ID immediately; one completion message arrives after execution and cleanup. End the turn rather than polling. Full server trust, like exec.',\n parameters: ExecBackgroundToolSchema,\n mainAgentOnly: true,\n executionMode: 'serial',\n async execute(_toolCallId, parameters: ExecBackgroundToolParams, signal, _onUpdate, execution) {\n if (signal?.aborted) return text('Background exec launch was aborted.', true);\n if (closing || ownerSignal.aborted) return text('Code mode session is disposing.', true);\n if (!isolate()?.liveObjects) return text('Background exec requires a Node host with live objects.', true);\n if (!execution.session?.admitMessage)\n return text('This session cannot admit background exec completion messages.', true);\n if (running >= MAX_CONCURRENT_RUNS)\n return text(`This session already has ${MAX_CONCURRENT_RUNS} exec runs active. Wait for one to finish.`, true);\n const deadlineMs = Math.min(\n BACKGROUND_MAX_TIMEOUT_MS,\n Math.max(MIN_TIMEOUT_MS, parameters.timeoutMs ?? BACKGROUND_DEFAULT_TIMEOUT_MS),\n );\n const id = crypto.randomUUID();\n const controller = new AbortController();\n const job: BackgroundExec = {\n id,\n sessionId: execution.sessionId,\n controller,\n status: 'running',\n done: Promise.resolve(),\n };\n jobs.set(id, job);\n onBackgroundChange?.();\n job.done = (async () => {\n let timedOut = false;\n const timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, deadlineMs);\n try {\n const result = await executeCode(parameters, controller.signal, execution, deadlineMs);\n clearTimeout(timer);\n job.status = 'reporting';\n onBackgroundChange?.();\n const status = timedOut\n ? 'timed-out'\n : controller.signal.aborted\n ? 'stopped'\n : result.isError\n ? 'failed'\n : 'completed';\n const message = {\n type: 'po-codemode-finished',\n text: `Background exec ${id} ${status}.\\n${result.content.flatMap((part) => (part.type === 'text' ? [part.text] : [])).join('\\n')}`,\n display: true,\n details: { id, status, result },\n };\n let warned = false;\n while (!ownerSignal.aborted) {\n let stopAdmission: (() => void) | undefined;\n try {\n const stopped = new Promise<void>((resolve) => {\n stopAdmission = resolve;\n ownerSignal.addEventListener('abort', stopAdmission, { once: true });\n if (ownerSignal.aborted) resolve();\n });\n await Promise.race([\n execution.session.admitMessage!(message, 'steer', `po-codemode-finished:${execution.sessionId}:${id}`),\n stopped,\n ]);\n break;\n } catch (error) {\n if (ownerSignal.aborted) break;\n if (!warned) {\n warned = true;\n await Promise.resolve()\n .then(() =>\n execution.client.notify({\n body: `Background exec completion admission failed; retrying: ${String(error)}`,\n level: 'warning',\n }),\n )\n .catch(() => undefined);\n }\n await sleep(250, ownerSignal).catch(() => undefined);\n } finally {\n if (stopAdmission) ownerSignal.removeEventListener('abort', stopAdmission);\n }\n }\n } finally {\n clearTimeout(timer);\n jobs.delete(id);\n onBackgroundChange?.();\n }\n })();\n return { ...text(JSON.stringify({ id })), details: { id } };\n },\n };\n\n // web-plugin-tool-renderers: ignore exec_cancel, immediate cancellation acknowledgement\n const execCancel: CodemodeTools['execCancel'] = {\n name: 'exec_cancel',\n label: 'Cancel Exec',\n description: 'Cancel a background exec in this session. Its terminal message follows child cleanup.',\n parameters: ExecCancelToolSchema,\n mainAgentOnly: true,\n executionMode: 'serial',\n async execute(_toolCallId, parameters: ExecCancelToolParams, _signal, _onUpdate, execution) {\n const job = jobs.get(parameters.id);\n if (job && job.sessionId !== execution.sessionId)\n return text('Background exec belongs to another session.', true);\n if (job?.status === 'running') job.controller.abort(parameters.reason ? new Error(parameters.reason) : undefined);\n return text(JSON.stringify({ id: parameters.id, status: job?.status === 'running' ? 'stopping' : 'finished' }));\n },\n };\n\n return {\n discover,\n exec,\n execBackground,\n execCancel,\n backgroundWork,\n async dispose() {\n closing = true;\n lifecycle.abort();\n await Promise.all([...jobs.values()].map((job) => job.done));\n },\n };\n}\n"],"mappings":"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"}