@ai-ecoverse/slicc-agent 3.9.0 → 3.10.0
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 +23 -1
- package/dist/codemode/index.js +288 -0
- package/dist/codemode/index.js.map +7 -0
- package/dist/main.js +25 -2
- package/dist/main.js.map +2 -2
- package/dist/types/codemode/index.d.ts +37 -0
- package/dist/types/main.d.ts +2 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -214,13 +214,35 @@ The worker watches the roots and reloads on change. A `skills` prompt section, g
|
|
|
214
214
|
- **v6's JS realm, `.jsh` and `ipk` (slicc-kernel#68):** `jshd`, `mcp`, `workflows`, `package-execution`, `biome`, `ffmpeg`.
|
|
215
215
|
- **Commands the kernel doesn't have:** `mount`, `theme`, `dips`, `image-processing` (ImageMagick), `dns` (`dig`), `meminfo`, `x-search` (xAI credentials).
|
|
216
216
|
|
|
217
|
+
### Codemode
|
|
218
|
+
|
|
219
|
+
The model can write a short JavaScript program that calls its tools, with the `codemode` tool from pi's [`@earendil-works/pi-codemode`](https://www.npmjs.com/package/@earendil-works/pi-codemode). Only the script's output reaches the model, so a script can run tool calls in a loop or in parallel and filter large results first. Codemode is separate from v6's `.jsh` and the node shim: it has no Node APIs, file system, network or timers, only the agent's tools.
|
|
220
|
+
|
|
221
|
+
**On by default.** Cones and scoops get `codemode` next to their other tools, which stay declared as before (pi's `codemode.mode: on`). `"defaultTools": ["-codemode"]` in `~/.pi/agent/settings.json` turns it off. The setting is read when the worker starts.
|
|
222
|
+
|
|
223
|
+
**The tool** follows coding-agent's `codemode` tool:
|
|
224
|
+
- **Input.** The input is raw JavaScript, run as the body of an async function. An optional first line, `// @options: {"max_output_tokens": …, "timeout_ms": …}`, sets an output budget and a deadline. The budget defaults to 10,000 tokens, and there's no deadline by default.
|
|
225
|
+
- **Tools.** `tools.<name>(args)` calls the agent's own tools through their registrations, so a scoop's file guard applies to nested calls too. Arguments are validated as for a model call. `bash` resolves to `{ output, exit_code }`, also for a non-zero exit; the other tools resolve to their text and reject on an error.
|
|
226
|
+
- **Globals.** `text()`, `image()`, `console.*`, `return`, `exit()`, `ALL_TOOLS`, and `store()`/`load()`.
|
|
227
|
+
- **The store** lives in the conversation document `slicc.codemode`, which is rewindable and forks as of the fork point, so each branch keeps its own values. Writes are kept only when the script succeeds.
|
|
228
|
+
- **The result** starts with `Script completed` or `Script failed` and the wall time. Several text items each start with `==> text N/M <==`, and `console` lines come last in one `<console_output>` block. A failure adds `Script error:` with the error and the tool calls made before it, which aren't undone. Output past the budget keeps its start and end, and the full text goes to `/tmp/slicc-codemode-<call>.txt`.
|
|
229
|
+
- **Not ported.** coding-agent's `models`, `searchTools`, `describeTool` and `describeNamespace`.
|
|
230
|
+
|
|
231
|
+
**In the browser.** pi-codemode runs QuickJS (`quickjs-wasi`) in a worker of its own, so a spinning script never blocks the agent worker.
|
|
232
|
+
- **The worker.** It starts through `node:worker_threads`, which slicc-bios provides as an `environment` stub (see Patched dependencies).
|
|
233
|
+
- **The wasm.** The agent compiles `quickjs.wasm` itself and hands it over: it walks up the `node_modules` folders from its own module, as bios's resolver does, and fetches the first `quickjs-wasi/quickjs.wasm` it finds. On Node, pi-codemode loads it itself.
|
|
234
|
+
- **Isolation.** Seven is cross-origin isolated, so pi-codemode's `SharedArrayBuffer` interrupt works.
|
|
235
|
+
- **Overrides.** `runAgentWorker` takes `codemodeWasm` and `codemodeWorker` to override both, for bundled hosts.
|
|
236
|
+
|
|
217
237
|
## Patched dependencies
|
|
218
238
|
|
|
219
239
|
Fixes to pi stay in this repository. [`patches/patches.json`](patches/patches.json) lists each one with its `kind`, `package`, `patchedVersion`, `reason`, `removeWhen` and `verify` command, and an optional `marker` (a file in the package and a string it must contain):
|
|
220
240
|
|
|
221
241
|
- `monkeypatch`: code that runs in users' browsers is patched at runtime. `applyPatches()` in [`src/patches.ts`](src/patches.ts) applies them once before pi is used: `PortListener.start()` calls it, so `hostAgent` and a `PortListener` used directly with pi's `Server` both get them. Each one checks that the code it replaces still looks as expected and throws, naming its manifest entry, if not. Today there is one: pi-server's `Server.accept` calls `unref()` on its handshake timer, which browsers don't have, so the patch gives numeric timer ids a no-op `unref`.
|
|
222
242
|
- `patch-package`: repository-only fixes go in `patches/<package>+<version>.patch`, applied by a `postinstall` that runs [patch-package](https://github.com/ds300/patch-package). There are none yet.
|
|
223
|
-
- `environment`: something the host must provide.
|
|
243
|
+
- `environment`: something the host must provide.
|
|
244
|
+
- pi-server imports `randomUUID` from `node:crypto`. slicc-bios serves a stub backed by `globalThis.crypto`, and the integration bundles alias it to `test/integration/shims/node-crypto.js`.
|
|
245
|
+
- pi-codemode runs QuickJS in a `node:worker_threads` Worker. slicc-bios must serve a `node:worker_threads` stub that wraps a module Web Worker; inside the worker, the stub gives `parentPort` and `workerData` from the first message. `test/integration/shims/node-worker-threads.js` is that stub, and the integration bundles alias to it.
|
|
224
246
|
|
|
225
247
|
`npm run lint:patches` (part of `npm run lint`) fails when an installed version differs from `patchedVersion`, a marker is gone, a monkeypatch isn't named in `src/patches.ts`, a patch file and its entry don't match, or `renovate.json` doesn't route the package to the `patched dependencies` group with automerge off. That group covers every `@earendil-works/*` package, so a pi bump is always a reviewed PR: rerun each entry's `verify`, then move `patchedVersion` forward or drop the entry.
|
|
226
248
|
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { withAbortSignal } from "@earendil-works/chord/context";
|
|
2
|
+
import { Type } from "@earendil-works/pi-ai";
|
|
3
|
+
import { validateToolArguments } from "@earendil-works/pi-ai/utils/validation";
|
|
4
|
+
import {
|
|
5
|
+
CodemodeSandbox,
|
|
6
|
+
loadQuickJSWasm,
|
|
7
|
+
parseCodemodeSource,
|
|
8
|
+
renderDeclarations
|
|
9
|
+
} from "@earendil-works/pi-codemode";
|
|
10
|
+
import {
|
|
11
|
+
defineDoc,
|
|
12
|
+
defineExtension,
|
|
13
|
+
defineTool
|
|
14
|
+
} from "@earendil-works/pi-durable";
|
|
15
|
+
const CODEMODE = "codemode";
|
|
16
|
+
const DEFAULT_MAX_OUTPUT_TOKENS = 1e4;
|
|
17
|
+
const MEMORY_LIMIT_BYTES = 256 * 1024 * 1024;
|
|
18
|
+
const CHARS_PER_TOKEN = 4;
|
|
19
|
+
const CodemodeDoc = defineDoc({
|
|
20
|
+
kind: "slicc.codemode",
|
|
21
|
+
version: 1,
|
|
22
|
+
scope: "conversation",
|
|
23
|
+
history: "rewindable",
|
|
24
|
+
fork: "asOf",
|
|
25
|
+
initial: () => ({ store: {} })
|
|
26
|
+
});
|
|
27
|
+
const INTRO = `Run JavaScript that calls other tools. The input is raw JavaScript (not JSON, no code fence), run as an async function body in a QuickJS sandbox: top-level \`await\` and \`return\` work. No Node, file system, network, or timers.
|
|
28
|
+
- \`await tools.<name>({ ...args })\` resolves to a string, or an object if the tool's declaration says so, and rejects with an Error on failure. Calls still running when the script ends are cancelled.
|
|
29
|
+
- Optional first line: \`// @options: {"max_output_tokens": 10000, "timeout_ms": 60000}\``;
|
|
30
|
+
const GLOBALS = [
|
|
31
|
+
"Globals:",
|
|
32
|
+
"- `text(value)`, `image(dataUrlOrImageBlock)`, `console.log(...)`, and top-level `return` add output; `exit()` ends the script. With several text items, each starts with a `==> text N/M <==` line, and `console` lines follow the other output in one `<console_output>` block.",
|
|
33
|
+
"- `store(key, value)` and `load(key)` keep JSON values across codemode calls in this conversation.",
|
|
34
|
+
"- `ALL_TOOLS` lists every tool scripts can call."
|
|
35
|
+
].join("\n");
|
|
36
|
+
const BASH_OUTPUT = {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: { output: { type: "string" }, exit_code: { type: "number" } },
|
|
39
|
+
required: ["output", "exit_code"]
|
|
40
|
+
};
|
|
41
|
+
function scriptTool(tool) {
|
|
42
|
+
return {
|
|
43
|
+
name: tool.name,
|
|
44
|
+
description: tool.description,
|
|
45
|
+
inputSchema: tool.parameters,
|
|
46
|
+
...tool.name === "bash" ? { outputSchema: BASH_OUTPUT } : {}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function codemodeDescription(declared) {
|
|
50
|
+
const tools = declared.filter((tool) => tool.name !== CODEMODE).map((tool) => ({ ...scriptTool(tool), execute: () => void 0 }));
|
|
51
|
+
const sections = [INTRO, GLOBALS];
|
|
52
|
+
if (tools.length) sections.push(`Nested tools:
|
|
53
|
+
${renderDeclarations({ tools })}`);
|
|
54
|
+
return sections.join("\n\n");
|
|
55
|
+
}
|
|
56
|
+
function textOf(content) {
|
|
57
|
+
return (content ?? []).filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
58
|
+
}
|
|
59
|
+
async function callNested(tool, args, api, context, id) {
|
|
60
|
+
const prepared = tool.prepareArguments ? tool.prepareArguments(args) : args;
|
|
61
|
+
const valid = validateToolArguments(tool, {
|
|
62
|
+
type: "toolCall",
|
|
63
|
+
id,
|
|
64
|
+
name: tool.name,
|
|
65
|
+
arguments: prepared
|
|
66
|
+
});
|
|
67
|
+
const decoder = new TextDecoder();
|
|
68
|
+
let output = "";
|
|
69
|
+
const nested = {
|
|
70
|
+
...api,
|
|
71
|
+
callId: id,
|
|
72
|
+
outputWindow: void 0,
|
|
73
|
+
output: (chunk) => {
|
|
74
|
+
output += typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
|
|
75
|
+
},
|
|
76
|
+
diagnostic: () => void 0,
|
|
77
|
+
details: async () => void 0
|
|
78
|
+
};
|
|
79
|
+
const bash = tool.name === "bash";
|
|
80
|
+
try {
|
|
81
|
+
const result = await tool.execute(valid, nested, context);
|
|
82
|
+
const text = result.content ? textOf(result.content) : output;
|
|
83
|
+
if (result.isError) throw new Error(text || `Tool "${tool.name}" failed`);
|
|
84
|
+
return bash ? { output: text, exit_code: 0 } : text;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
87
|
+
const exit = /exited with code (\d+)/.exec(message);
|
|
88
|
+
if (bash && exit) return { output, exit_code: Number(exit[1]) };
|
|
89
|
+
throw new Error(message);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function valueText(value) {
|
|
93
|
+
return typeof value === "string" ? value : JSON.stringify(value) ?? String(value);
|
|
94
|
+
}
|
|
95
|
+
function formatOutput(output) {
|
|
96
|
+
const total = output.filter((item) => item.type === "text" && !item.console).length;
|
|
97
|
+
const items = [];
|
|
98
|
+
const lines = [];
|
|
99
|
+
let index = 0;
|
|
100
|
+
for (const item of output) {
|
|
101
|
+
if (item.type === "image") items.push(item);
|
|
102
|
+
else if (item.console) lines.push(item.text);
|
|
103
|
+
else {
|
|
104
|
+
index++;
|
|
105
|
+
items.push({
|
|
106
|
+
type: "text",
|
|
107
|
+
text: total > 1 ? `==> text ${index}/${total} <==
|
|
108
|
+
${item.text}` : item.text
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (lines.length)
|
|
113
|
+
items.push({ type: "text", text: `<console_output>
|
|
114
|
+
${lines.join("\n")}
|
|
115
|
+
</console_output>` });
|
|
116
|
+
return items;
|
|
117
|
+
}
|
|
118
|
+
function joinText(items) {
|
|
119
|
+
const joined = [];
|
|
120
|
+
for (const item of items) {
|
|
121
|
+
const last = joined.at(-1);
|
|
122
|
+
if (item.type === "text" && last?.type === "text") {
|
|
123
|
+
const separator = last.text === "" || last.text.endsWith("\n") ? "" : "\n";
|
|
124
|
+
joined[joined.length - 1] = { type: "text", text: `${last.text}${separator}${item.text}` };
|
|
125
|
+
} else joined.push(item);
|
|
126
|
+
}
|
|
127
|
+
return joined;
|
|
128
|
+
}
|
|
129
|
+
function formatError(error, calls) {
|
|
130
|
+
const heads = {
|
|
131
|
+
timeout: `Script timed out: ${error.message}`,
|
|
132
|
+
aborted: `Script aborted: ${error.message}`,
|
|
133
|
+
sandbox: `Script sandbox failed: ${error.message}`
|
|
134
|
+
};
|
|
135
|
+
const head = error.kind === "script" ? error.stack ?? `${error.name ?? "Error"}: ${error.message}` : heads[error.kind];
|
|
136
|
+
const summary = calls.length ? `Tool calls made before the failure (they are not undone): ${calls.map((call) => `${call.name} (${call.status})`).join(", ")}` : "No tool calls were made.";
|
|
137
|
+
return `${head}
|
|
138
|
+
|
|
139
|
+
${summary}`;
|
|
140
|
+
}
|
|
141
|
+
function truncate(items, maxTokens) {
|
|
142
|
+
const text = items.filter((item) => item.type === "text").map((item) => item.text).join("\n");
|
|
143
|
+
const limit = maxTokens * CHARS_PER_TOKEN;
|
|
144
|
+
if (text.length <= limit) return { items: [...items], full: null };
|
|
145
|
+
const half = Math.floor(limit / 2);
|
|
146
|
+
const kept = `${text.slice(0, half)}
|
|
147
|
+
|
|
148
|
+
[\u2026 ${text.length - 2 * half} characters omitted \u2026]
|
|
149
|
+
|
|
150
|
+
${text.slice(-half)}`;
|
|
151
|
+
return {
|
|
152
|
+
items: [{ type: "text", text: kept }, ...items.filter((item) => item.type === "image")],
|
|
153
|
+
full: text
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
async function spill(api, text, context) {
|
|
157
|
+
const path = `/tmp/slicc-codemode-${api.callId.replace(/[^\w-]/g, "_")}.txt`;
|
|
158
|
+
const written = await api.env?.writeFile(path, text, context);
|
|
159
|
+
return written?.ok ? path : "";
|
|
160
|
+
}
|
|
161
|
+
async function saveStore(api, result, context) {
|
|
162
|
+
if (!result.ok) return;
|
|
163
|
+
const { set, delete: removed } = result.storeWrites;
|
|
164
|
+
if (!Object.keys(set).length && !removed.length) return;
|
|
165
|
+
await api.commit(async (tx) => {
|
|
166
|
+
const doc = await tx.doc(CodemodeDoc, api.conversationId);
|
|
167
|
+
for (const key of removed) delete doc.store[key];
|
|
168
|
+
Object.assign(doc.store, set);
|
|
169
|
+
}, context);
|
|
170
|
+
}
|
|
171
|
+
function codemodeTool(options) {
|
|
172
|
+
return defineTool({
|
|
173
|
+
name: CODEMODE,
|
|
174
|
+
description: codemodeDescription(options.declared),
|
|
175
|
+
parameters: Type.Object({ code: Type.String({ description: "Raw JavaScript source." }) }),
|
|
176
|
+
replay: "unsafe",
|
|
177
|
+
async execute({ code }, api, context) {
|
|
178
|
+
const started = performance.now();
|
|
179
|
+
const parsed = parseCodemodeSource(code);
|
|
180
|
+
const agent = await api.agent(context);
|
|
181
|
+
const callable = agent.tools.filter((tool) => tool.name !== CODEMODE);
|
|
182
|
+
let count = 0;
|
|
183
|
+
const tools = callable.map((tool) => ({
|
|
184
|
+
...scriptTool(tool),
|
|
185
|
+
execute: (args, { signal }) => callNested(tool, args, api, withAbortSignal(signal, context), `${api.callId}:${++count}`)
|
|
186
|
+
}));
|
|
187
|
+
const saved = await api.snapshot(CodemodeDoc, api.conversationId, context);
|
|
188
|
+
const sandbox = options.sandbox({
|
|
189
|
+
tools,
|
|
190
|
+
timeoutMs: parsed.options.timeoutMs ?? Number.POSITIVE_INFINITY,
|
|
191
|
+
memoryLimitBytes: MEMORY_LIMIT_BYTES
|
|
192
|
+
});
|
|
193
|
+
let result;
|
|
194
|
+
try {
|
|
195
|
+
result = await sandbox.execute(parsed.code, {
|
|
196
|
+
signal: context.abortSignal,
|
|
197
|
+
store: { ...saved?.store }
|
|
198
|
+
});
|
|
199
|
+
} finally {
|
|
200
|
+
await sandbox.close();
|
|
201
|
+
}
|
|
202
|
+
await saveStore(api, result, context);
|
|
203
|
+
const output = [...result.output];
|
|
204
|
+
if (result.ok && result.value !== void 0)
|
|
205
|
+
output.push({ type: "text", text: valueText(result.value) });
|
|
206
|
+
const items = formatOutput(output);
|
|
207
|
+
if (!result.ok)
|
|
208
|
+
items.push({
|
|
209
|
+
type: "text",
|
|
210
|
+
text: `Script error:
|
|
211
|
+
${formatError(result.error, result.calls)}`
|
|
212
|
+
});
|
|
213
|
+
const cut = truncate(
|
|
214
|
+
joinText(items),
|
|
215
|
+
parsed.options.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS
|
|
216
|
+
);
|
|
217
|
+
const path = cut.full === null ? "" : await spill(api, cut.full, context);
|
|
218
|
+
const note = path ? [{ type: "text", text: `Full output: ${path}` }] : [];
|
|
219
|
+
const seconds = ((performance.now() - started) / 1e3).toFixed(1);
|
|
220
|
+
const header = `${result.ok ? "Script completed" : "Script failed"}
|
|
221
|
+
Wall time ${seconds} seconds
|
|
222
|
+
Output:
|
|
223
|
+
`;
|
|
224
|
+
return {
|
|
225
|
+
content: [{ type: "text", text: header }, ...joinText([...cut.items, ...note])],
|
|
226
|
+
...result.ok ? {} : { isError: true }
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function codemodeExtension(tools) {
|
|
232
|
+
return defineExtension({ name: "slicc-codemode", tools });
|
|
233
|
+
}
|
|
234
|
+
function disabledBySettings(text) {
|
|
235
|
+
if (!text) return false;
|
|
236
|
+
try {
|
|
237
|
+
const settings = JSON.parse(text);
|
|
238
|
+
return Array.isArray(settings.defaultTools) && settings.defaultTools.includes(`-${CODEMODE}`);
|
|
239
|
+
} catch {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function wasmCandidates(from) {
|
|
244
|
+
const out = [];
|
|
245
|
+
let dir = new URL(".", from);
|
|
246
|
+
for (; ; ) {
|
|
247
|
+
out.push(new URL("node_modules/quickjs-wasi/quickjs.wasm", dir).href);
|
|
248
|
+
if (dir.pathname === "/") return out;
|
|
249
|
+
dir = new URL("..", dir);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async function locateWasm(fetcher, from) {
|
|
253
|
+
for (const url of wasmCandidates(from)) {
|
|
254
|
+
const response = await fetcher(url).catch(() => void 0);
|
|
255
|
+
if (response?.ok) return WebAssembly.compile(await response.arrayBuffer());
|
|
256
|
+
}
|
|
257
|
+
return void 0;
|
|
258
|
+
}
|
|
259
|
+
function sandboxFactory(wasm, workerUrl) {
|
|
260
|
+
let found;
|
|
261
|
+
return (options) => {
|
|
262
|
+
found ??= wasm().catch(() => void 0);
|
|
263
|
+
return new CodemodeSandbox({
|
|
264
|
+
...options,
|
|
265
|
+
...workerUrl ? { workerUrl } : {},
|
|
266
|
+
wasm: found.then((module) => module ?? loadQuickJSWasm())
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
export {
|
|
271
|
+
CODEMODE,
|
|
272
|
+
CodemodeDoc,
|
|
273
|
+
DEFAULT_MAX_OUTPUT_TOKENS,
|
|
274
|
+
MEMORY_LIMIT_BYTES,
|
|
275
|
+
callNested,
|
|
276
|
+
codemodeDescription,
|
|
277
|
+
codemodeExtension,
|
|
278
|
+
codemodeTool,
|
|
279
|
+
disabledBySettings,
|
|
280
|
+
formatError,
|
|
281
|
+
formatOutput,
|
|
282
|
+
joinText,
|
|
283
|
+
locateWasm,
|
|
284
|
+
sandboxFactory,
|
|
285
|
+
truncate,
|
|
286
|
+
wasmCandidates
|
|
287
|
+
};
|
|
288
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/codemode/index.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Context, JsonValue } from '@earendil-works/chord';\nimport { withAbortSignal } from '@earendil-works/chord/context';\nimport { Type } from '@earendil-works/pi-ai';\nimport { validateToolArguments } from '@earendil-works/pi-ai/utils/validation';\nimport {\n type CodemodeError,\n type CodemodeJsonSchema,\n type CodemodeOutputItem,\n type CodemodeResult,\n CodemodeSandbox,\n type CodemodeSandboxOptions,\n type CodemodeTool,\n loadQuickJSWasm,\n parseCodemodeSource,\n renderDeclarations,\n} from '@earendil-works/pi-codemode';\nimport {\n defineDoc,\n defineExtension,\n defineTool,\n type Extension,\n type ToolExecutionApi,\n type ToolRegistration,\n} from '@earendil-works/pi-durable';\n\nexport const CODEMODE = 'codemode';\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 10_000;\nexport const MEMORY_LIMIT_BYTES = 256 * 1024 * 1024;\nconst CHARS_PER_TOKEN = 4;\n\nexport const CodemodeDoc = defineDoc<{ store: Record<string, JsonValue> }>({\n kind: 'slicc.codemode',\n version: 1,\n scope: 'conversation',\n history: 'rewindable',\n fork: 'asOf',\n initial: () => ({ store: {} }),\n});\n\nexport interface Sandbox {\n execute(\n code: string,\n options: { signal?: AbortSignal; store?: Record<string, unknown> }\n ): Promise<CodemodeResult>;\n close(): Promise<void>;\n}\n\nexport type SandboxFactory = (options: CodemodeSandboxOptions) => Sandbox;\n\nexport interface CodemodeOptions {\n sandbox: SandboxFactory;\n declared: readonly ToolRegistration[];\n}\n\nconst INTRO = `Run JavaScript that calls other tools. The input is raw JavaScript (not JSON, no code fence), run as an async function body in a QuickJS sandbox: top-level \\`await\\` and \\`return\\` work. No Node, file system, network, or timers.\n- \\`await tools.<name>({ ...args })\\` resolves to a string, or an object if the tool's declaration says so, and rejects with an Error on failure. Calls still running when the script ends are cancelled.\n- Optional first line: \\`// @options: {\"max_output_tokens\": 10000, \"timeout_ms\": 60000}\\``;\n\nconst GLOBALS = [\n 'Globals:',\n '- `text(value)`, `image(dataUrlOrImageBlock)`, `console.log(...)`, and top-level `return` add output; `exit()` ends the script. With several text items, each starts with a `==> text N/M <==` line, and `console` lines follow the other output in one `<console_output>` block.',\n '- `store(key, value)` and `load(key)` keep JSON values across codemode calls in this conversation.',\n '- `ALL_TOOLS` lists every tool scripts can call.',\n].join('\\n');\n\nconst BASH_OUTPUT: CodemodeJsonSchema = {\n type: 'object',\n properties: { output: { type: 'string' }, exit_code: { type: 'number' } },\n required: ['output', 'exit_code'],\n};\n\nfunction scriptTool(tool: ToolRegistration): Omit<CodemodeTool, 'execute'> {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.parameters as CodemodeJsonSchema,\n ...(tool.name === 'bash' ? { outputSchema: BASH_OUTPUT } : {}),\n };\n}\n\nexport function codemodeDescription(declared: readonly ToolRegistration[]): string {\n const tools = declared\n .filter((tool) => tool.name !== CODEMODE)\n .map((tool) => ({ ...scriptTool(tool), execute: () => undefined }));\n const sections = [INTRO, GLOBALS];\n if (tools.length) sections.push(`Nested tools:\\n${renderDeclarations({ tools })}`);\n return sections.join('\\n\\n');\n}\n\nfunction textOf(content: readonly { type: string; text?: string }[] | undefined): string {\n return (content ?? [])\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('\\n');\n}\n\nexport async function callNested(\n tool: ToolRegistration,\n args: unknown,\n api: ToolExecutionApi,\n context: Context,\n id: string\n): Promise<unknown> {\n const prepared = tool.prepareArguments ? tool.prepareArguments(args) : args;\n const valid = validateToolArguments(tool, {\n type: 'toolCall',\n id,\n name: tool.name,\n arguments: prepared as never,\n });\n const decoder = new TextDecoder();\n let output = '';\n const nested: ToolExecutionApi = {\n ...api,\n callId: id,\n outputWindow: undefined,\n output: (chunk) => {\n output += typeof chunk === 'string' ? chunk : decoder.decode(chunk, { stream: true });\n },\n diagnostic: () => undefined,\n details: async () => undefined,\n };\n const bash = tool.name === 'bash';\n try {\n const result = await tool.execute(valid, nested, context);\n const text = result.content ? textOf(result.content) : output;\n if (result.isError) throw new Error(text || `Tool \"${tool.name}\" failed`);\n return bash ? { output: text, exit_code: 0 } : text;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const exit = /exited with code (\\d+)/.exec(message);\n if (bash && exit) return { output, exit_code: Number(exit[1]) };\n throw new Error(message);\n }\n}\n\nfunction valueText(value: unknown): string {\n return typeof value === 'string' ? value : (JSON.stringify(value) ?? String(value));\n}\n\nexport function formatOutput(output: readonly CodemodeOutputItem[]): CodemodeOutputItem[] {\n const total = output.filter((item) => item.type === 'text' && !item.console).length;\n const items: CodemodeOutputItem[] = [];\n const lines: string[] = [];\n let index = 0;\n for (const item of output) {\n if (item.type === 'image') items.push(item);\n else if (item.console) lines.push(item.text);\n else {\n index++;\n items.push({\n type: 'text',\n text: total > 1 ? `==> text ${index}/${total} <==\\n${item.text}` : item.text,\n });\n }\n }\n if (lines.length)\n items.push({ type: 'text', text: `<console_output>\\n${lines.join('\\n')}\\n</console_output>` });\n return items;\n}\n\nexport function joinText(items: readonly CodemodeOutputItem[]): CodemodeOutputItem[] {\n const joined: CodemodeOutputItem[] = [];\n for (const item of items) {\n const last = joined.at(-1);\n if (item.type === 'text' && last?.type === 'text') {\n const separator = last.text === '' || last.text.endsWith('\\n') ? '' : '\\n';\n joined[joined.length - 1] = { type: 'text', text: `${last.text}${separator}${item.text}` };\n } else joined.push(item);\n }\n return joined;\n}\n\nexport function formatError(error: CodemodeError, calls: CodemodeResult['calls']): string {\n const heads: Record<string, string> = {\n timeout: `Script timed out: ${error.message}`,\n aborted: `Script aborted: ${error.message}`,\n sandbox: `Script sandbox failed: ${error.message}`,\n };\n const head =\n error.kind === 'script'\n ? (error.stack ?? `${error.name ?? 'Error'}: ${error.message}`)\n : heads[error.kind];\n const summary = calls.length\n ? `Tool calls made before the failure (they are not undone): ${calls.map((call) => `${call.name} (${call.status})`).join(', ')}`\n : 'No tool calls were made.';\n return `${head}\\n\\n${summary}`;\n}\n\nexport function truncate(\n items: readonly CodemodeOutputItem[],\n maxTokens: number\n): { items: CodemodeOutputItem[]; full: string | null } {\n const text = items\n .filter((item) => item.type === 'text')\n .map((item) => item.text)\n .join('\\n');\n const limit = maxTokens * CHARS_PER_TOKEN;\n if (text.length <= limit) return { items: [...items], full: null };\n const half = Math.floor(limit / 2);\n const kept = `${text.slice(0, half)}\\n\\n[\u2026 ${text.length - 2 * half} characters omitted \u2026]\\n\\n${text.slice(-half)}`;\n return {\n items: [{ type: 'text', text: kept }, ...items.filter((item) => item.type === 'image')],\n full: text,\n };\n}\n\nasync function spill(api: ToolExecutionApi, text: string, context: Context): Promise<string> {\n const path = `/tmp/slicc-codemode-${api.callId.replace(/[^\\w-]/g, '_')}.txt`;\n const written = await api.env?.writeFile(path, text, context);\n return written?.ok ? path : '';\n}\n\nasync function saveStore(\n api: ToolExecutionApi,\n result: CodemodeResult,\n context: Context\n): Promise<void> {\n if (!result.ok) return;\n const { set, delete: removed } = result.storeWrites;\n if (!Object.keys(set).length && !removed.length) return;\n await api.commit(async (tx) => {\n const doc = await tx.doc(CodemodeDoc, api.conversationId);\n for (const key of removed) delete doc.store[key];\n Object.assign(doc.store, set);\n }, context);\n}\n\nexport function codemodeTool(options: CodemodeOptions): ToolRegistration {\n return defineTool({\n name: CODEMODE,\n description: codemodeDescription(options.declared),\n parameters: Type.Object({ code: Type.String({ description: 'Raw JavaScript source.' }) }),\n replay: 'unsafe',\n async execute({ code }, api, context) {\n const started = performance.now();\n const parsed = parseCodemodeSource(code);\n const agent = await api.agent(context);\n const callable = agent.tools.filter((tool) => tool.name !== CODEMODE);\n let count = 0;\n const tools: CodemodeTool[] = callable.map((tool) => ({\n ...scriptTool(tool),\n execute: (args, { signal }) =>\n callNested(tool, args, api, withAbortSignal(signal, context), `${api.callId}:${++count}`),\n }));\n const saved = await api.snapshot(CodemodeDoc, api.conversationId, context);\n const sandbox = options.sandbox({\n tools,\n timeoutMs: parsed.options.timeoutMs ?? Number.POSITIVE_INFINITY,\n memoryLimitBytes: MEMORY_LIMIT_BYTES,\n });\n let result: CodemodeResult;\n try {\n result = await sandbox.execute(parsed.code, {\n signal: context.abortSignal as AbortSignal,\n store: { ...saved?.store },\n });\n } finally {\n await sandbox.close();\n }\n await saveStore(api, result, context);\n const output = [...result.output];\n if (result.ok && result.value !== undefined)\n output.push({ type: 'text', text: valueText(result.value) });\n const items = formatOutput(output);\n if (!result.ok)\n items.push({\n type: 'text',\n text: `Script error:\\n${formatError(result.error, result.calls)}`,\n });\n const cut = truncate(\n joinText(items),\n parsed.options.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS\n );\n const path = cut.full === null ? '' : await spill(api, cut.full, context);\n const note = path ? [{ type: 'text' as const, text: `Full output: ${path}` }] : [];\n const seconds = ((performance.now() - started) / 1000).toFixed(1);\n const header = `${result.ok ? 'Script completed' : 'Script failed'}\\nWall time ${seconds} seconds\\nOutput:\\n`;\n return {\n content: [{ type: 'text', text: header }, ...joinText([...cut.items, ...note])],\n ...(result.ok ? {} : { isError: true }),\n };\n },\n }) as ToolRegistration;\n}\n\nexport function codemodeExtension(tools: readonly ToolRegistration[]): Extension {\n return defineExtension({ name: 'slicc-codemode', tools });\n}\n\nexport function disabledBySettings(text: string | undefined): boolean {\n if (!text) return false;\n try {\n const settings = JSON.parse(text) as { defaultTools?: unknown };\n return Array.isArray(settings.defaultTools) && settings.defaultTools.includes(`-${CODEMODE}`);\n } catch {\n return false;\n }\n}\n\nexport type Fetcher = (url: string) => Promise<Response>;\n\nexport function wasmCandidates(from: URL): string[] {\n const out: string[] = [];\n let dir = new URL('.', from);\n for (;;) {\n out.push(new URL('node_modules/quickjs-wasi/quickjs.wasm', dir).href);\n if (dir.pathname === '/') return out;\n dir = new URL('..', dir);\n }\n}\n\nexport async function locateWasm(\n fetcher: Fetcher,\n from: URL\n): Promise<WebAssembly.Module | undefined> {\n for (const url of wasmCandidates(from)) {\n const response = await fetcher(url).catch(() => undefined);\n if (response?.ok) return WebAssembly.compile(await response.arrayBuffer());\n }\n return undefined;\n}\n\nexport function sandboxFactory(\n wasm: () => Promise<WebAssembly.Module | undefined>,\n workerUrl?: string | URL\n): SandboxFactory {\n let found: Promise<WebAssembly.Module | undefined> | undefined;\n return (options) => {\n found ??= wasm().catch(() => undefined);\n return new CodemodeSandbox({\n ...options,\n ...(workerUrl ? { workerUrl } : {}),\n wasm: found.then((module) => module ?? loadQuickJSWasm()),\n });\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/main.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { attachKernel } from "@ai-ecoverse/slicc-kernel";
|
|
2
2
|
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createRegistry
|
|
5
|
+
} from "@earendil-works/pi-durable";
|
|
4
6
|
import { CodingTools } from "@earendil-works/pi-durable/tools";
|
|
5
7
|
import { openAgent } from "./agent.js";
|
|
8
|
+
import {
|
|
9
|
+
codemodeExtension,
|
|
10
|
+
codemodeTool,
|
|
11
|
+
disabledBySettings,
|
|
12
|
+
locateWasm,
|
|
13
|
+
sandboxFactory
|
|
14
|
+
} from "./codemode/index.js";
|
|
6
15
|
import { EncryptedCredentialStore } from "./credentials.js";
|
|
7
16
|
import { hostAgent } from "./host.js";
|
|
8
17
|
import { createActivity } from "./kernel/activity.js";
|
|
@@ -39,8 +48,22 @@ async function start(scope, port, options) {
|
|
|
39
48
|
const registry = createRegistry();
|
|
40
49
|
registry.install(CodingTools);
|
|
41
50
|
registry.install(sliccPrompt(facts));
|
|
51
|
+
const settings = await client.fs.readFile(`${HOME}/.pi/agent/settings.json`).catch(() => void 0);
|
|
52
|
+
const coding = CodingTools.tools;
|
|
53
|
+
const codemode = disabledBySettings(
|
|
54
|
+
settings === void 0 ? void 0 : new TextDecoder().decode(settings)
|
|
55
|
+
) ? [] : [
|
|
56
|
+
codemodeTool({
|
|
57
|
+
declared: coding,
|
|
58
|
+
sandbox: sandboxFactory(
|
|
59
|
+
options.codemodeWasm ?? (() => locateWasm(native, new URL(import.meta.url))),
|
|
60
|
+
options.codemodeWorker
|
|
61
|
+
)
|
|
62
|
+
})
|
|
63
|
+
];
|
|
64
|
+
registry.install(codemodeExtension(codemode));
|
|
42
65
|
const licks = setupLicks(registry);
|
|
43
|
-
const scoops = setupScoops(registry, licks.licks,
|
|
66
|
+
const scoops = setupScoops(registry, licks.licks, [...coding, ...codemode]);
|
|
44
67
|
const skills = setupSkills(registry, licks.licks);
|
|
45
68
|
const activity = createActivity();
|
|
46
69
|
const groups = processGroups(client);
|
package/dist/main.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/main.ts"],
|
|
4
|
-
"sourcesContent": ["import { attachKernel } from '@ai-ecoverse/slicc-kernel';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport {
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AAEnC,
|
|
4
|
+
"sourcesContent": ["import { attachKernel } from '@ai-ecoverse/slicc-kernel';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport {\n createRegistry,\n type ModelRef,\n type Storage,\n type ToolRegistration,\n} from '@earendil-works/pi-durable';\nimport { CodingTools } from '@earendil-works/pi-durable/tools';\nimport { type Agent, openAgent } from './agent.ts';\nimport {\n codemodeExtension,\n codemodeTool,\n disabledBySettings,\n locateWasm,\n sandboxFactory,\n} from './codemode/index.ts';\nimport { EncryptedCredentialStore } from './credentials.ts';\nimport { type AgentHost, hostAgent } from './host.ts';\nimport { createActivity } from './kernel/activity.ts';\nimport type { KernelClient } from './kernel/client.ts';\nimport { HOME, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';\nimport { processGroups } from './kernel/groups.ts';\nimport { setupLicks } from './licks/index.ts';\nimport { type Transport, transportFetch } from './net.ts';\nimport { sliccPrompt } from './prompt.ts';\nimport { identity } from './scoops/identity.ts';\nimport { type Assets, packageAssets, setupScoops } from './scoops/index.ts';\nimport {\n createAgentSettings,\n createSliccModels,\n DEFAULT_MODEL,\n sliccProviders,\n} from './settings.ts';\nimport { RELOAD_MS, setupSkills } from './skills/index.ts';\nimport { openOpfsSqliteStorage } from './sqlite.ts';\nimport { agentVersion, commandsOnPath, kernelBoot, transportName } from './system.ts';\nimport { kernelPort, serveConnections, type WorkerScope } from './worker.ts';\n\nexport interface AgentWorkerScope extends WorkerScope {\n fetch: typeof fetch;\n location: { origin: string };\n}\n\nexport type KernelAttach = (port: MessagePort) => Promise<KernelClient & { transport: Transport }>;\n\nexport interface AgentWorkerOptions {\n model?: ModelRef;\n providers?: Provider[];\n attach?: KernelAttach;\n credentials?: () => Promise<CredentialStore>;\n storage?: () => Promise<Storage>;\n assets?: Assets;\n codemodeWasm?: () => Promise<WebAssembly.Module | undefined>;\n codemodeWorker?: string | URL;\n}\n\nasync function start(\n scope: AgentWorkerScope,\n port: Promise<MessagePort>,\n options: AgentWorkerOptions\n): Promise<AgentHost> {\n const attach: KernelAttach = options.attach ?? attachKernel;\n const client = await attach(await port);\n const native = scope.fetch.bind(scope);\n scope.fetch = transportFetch(client.transport, scope.location.origin, native);\n const facts = {\n version: await agentVersion((url) => native(url)),\n commands: await commandsOnPath(client),\n transport: transportName(client.transport),\n };\n const credentials = await (options.credentials ?? (() => EncryptedCredentialStore.open()))();\n const providers = options.providers ?? sliccProviders();\n const models = createSliccModels(credentials, providers);\n const registry = createRegistry();\n registry.install(CodingTools);\n registry.install(sliccPrompt(facts));\n const settings = await client.fs\n .readFile(`${HOME}/.pi/agent/settings.json`)\n .catch(() => undefined);\n const coding = CodingTools.tools as readonly ToolRegistration[];\n const codemode = disabledBySettings(\n settings === undefined ? undefined : new TextDecoder().decode(settings)\n )\n ? []\n : [\n codemodeTool({\n declared: coding,\n sandbox: sandboxFactory(\n options.codemodeWasm ?? (() => locateWasm(native, new URL(import.meta.url))),\n options.codemodeWorker\n ),\n }),\n ];\n registry.install(codemodeExtension(codemode));\n const licks = setupLicks(registry);\n const scoops = setupScoops(registry, licks.licks, [...coding, ...codemode]);\n const skills = setupSkills(registry, licks.licks);\n const activity = createActivity();\n const groups = processGroups(client);\n const model = options.model ?? DEFAULT_MODEL;\n let opened: Agent | undefined;\n const environment = kernelEnvironment(client, {\n activity,\n groups,\n identify: identity(() => opened?.agents, model),\n });\n const agent = await openAgent({\n models,\n model,\n storage: await (options.storage ?? (() => openOpfsSqliteStorage()))(),\n registry,\n env: environment,\n });\n opened = agent;\n const home = new SliccKernelEnv(client, { cwd: HOME });\n const sources = licks.attach(agent, { env: home, home: HOME, activity });\n await sources.start(BACKGROUND_CONTEXT);\n await sources.boot(\n { version: facts.version, boot: await kernelBoot(client) },\n BACKGROUND_CONTEXT\n );\n const skillsRuntime = await skills.attach(\n { env: home, home: HOME, assets: options.assets ?? packageAssets(), reloadMs: RELOAD_MS },\n BACKGROUND_CONTEXT\n );\n const runtime = await scoops.attach(\n {\n harness: agent.harness,\n agents: agent.agents,\n groups,\n env: home,\n home: HOME,\n alive: alive(client),\n reads: skillsRuntime.dirs,\n ...(options.assets ? { assets: options.assets } : {}),\n },\n BACKGROUND_CONTEXT\n );\n return hostAgent(agent, {\n settings: await createAgentSettings(models, credentials, providers),\n licks: { licks: licks.licks, sources },\n scoops: { scoops: scoops.scoops, runtime },\n skills: skillsRuntime,\n });\n}\n\nexport function alive(client: KernelClient) {\n return async (pid: number): Promise<boolean> => {\n if (!client.ps) return true;\n return (await client.ps()).some((process) => process.pid === pid);\n };\n}\n\nexport function runAgentWorker(\n scope: AgentWorkerScope,\n options: AgentWorkerOptions = {}\n): Promise<AgentHost> {\n const host = start(scope, kernelPort(scope), options);\n host.catch(() => undefined);\n serveConnections(scope, host);\n return host;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Context, JsonValue } from '@earendil-works/chord';
|
|
2
|
+
import { type CodemodeError, type CodemodeOutputItem, type CodemodeResult, type CodemodeSandboxOptions } from '@earendil-works/pi-codemode';
|
|
3
|
+
import { type Extension, type ToolExecutionApi, type ToolRegistration } from '@earendil-works/pi-durable';
|
|
4
|
+
export declare const CODEMODE = "codemode";
|
|
5
|
+
export declare const DEFAULT_MAX_OUTPUT_TOKENS = 10000;
|
|
6
|
+
export declare const MEMORY_LIMIT_BYTES: number;
|
|
7
|
+
export declare const CodemodeDoc: import("@earendil-works/pi-durable").RewindableConversationDocToken<{
|
|
8
|
+
store: Record<string, JsonValue>;
|
|
9
|
+
}>;
|
|
10
|
+
export interface Sandbox {
|
|
11
|
+
execute(code: string, options: {
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
store?: Record<string, unknown>;
|
|
14
|
+
}): Promise<CodemodeResult>;
|
|
15
|
+
close(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export type SandboxFactory = (options: CodemodeSandboxOptions) => Sandbox;
|
|
18
|
+
export interface CodemodeOptions {
|
|
19
|
+
sandbox: SandboxFactory;
|
|
20
|
+
declared: readonly ToolRegistration[];
|
|
21
|
+
}
|
|
22
|
+
export declare function codemodeDescription(declared: readonly ToolRegistration[]): string;
|
|
23
|
+
export declare function callNested(tool: ToolRegistration, args: unknown, api: ToolExecutionApi, context: Context, id: string): Promise<unknown>;
|
|
24
|
+
export declare function formatOutput(output: readonly CodemodeOutputItem[]): CodemodeOutputItem[];
|
|
25
|
+
export declare function joinText(items: readonly CodemodeOutputItem[]): CodemodeOutputItem[];
|
|
26
|
+
export declare function formatError(error: CodemodeError, calls: CodemodeResult['calls']): string;
|
|
27
|
+
export declare function truncate(items: readonly CodemodeOutputItem[], maxTokens: number): {
|
|
28
|
+
items: CodemodeOutputItem[];
|
|
29
|
+
full: string | null;
|
|
30
|
+
};
|
|
31
|
+
export declare function codemodeTool(options: CodemodeOptions): ToolRegistration;
|
|
32
|
+
export declare function codemodeExtension(tools: readonly ToolRegistration[]): Extension;
|
|
33
|
+
export declare function disabledBySettings(text: string | undefined): boolean;
|
|
34
|
+
export type Fetcher = (url: string) => Promise<Response>;
|
|
35
|
+
export declare function wasmCandidates(from: URL): string[];
|
|
36
|
+
export declare function locateWasm(fetcher: Fetcher, from: URL): Promise<WebAssembly.Module | undefined>;
|
|
37
|
+
export declare function sandboxFactory(wasm: () => Promise<WebAssembly.Module | undefined>, workerUrl?: string | URL): SandboxFactory;
|
package/dist/types/main.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface AgentWorkerOptions {
|
|
|
21
21
|
credentials?: () => Promise<CredentialStore>;
|
|
22
22
|
storage?: () => Promise<Storage>;
|
|
23
23
|
assets?: Assets;
|
|
24
|
+
codemodeWasm?: () => Promise<WebAssembly.Module | undefined>;
|
|
25
|
+
codemodeWorker?: string | URL;
|
|
24
26
|
}
|
|
25
27
|
export declare function alive(client: KernelClient): (pid: number) => Promise<boolean>;
|
|
26
28
|
export declare function runAgentWorker(scope: AgentWorkerScope, options?: AgentWorkerOptions): Promise<AgentHost>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-agent",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.0",
|
|
4
4
|
"description": "SLICC's agent core on pi durable: an agent worker, session storage, remoting and pi extensions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@ai-ecoverse/slicc-shared-web": "1.8.0",
|
|
65
|
-
"@ai-ecoverse/slicc-spectrum": "1.23.
|
|
65
|
+
"@ai-ecoverse/slicc-spectrum": "1.23.3",
|
|
66
66
|
"@ai-ecoverse/wasm-bash": "5.3.0-7",
|
|
67
67
|
"@ai-ecoverse/wasm-coreutils": "9.7.0-3",
|
|
68
68
|
"@biomejs/biome": "2.5.15",
|
|
@@ -76,10 +76,11 @@
|
|
|
76
76
|
"typescript": "7.0.2"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
|
-
"@ai-ecoverse/slicc-kernel": "1.
|
|
79
|
+
"@ai-ecoverse/slicc-kernel": "1.17.3",
|
|
80
80
|
"@earendil-works/chord": "1.0.4",
|
|
81
81
|
"@earendil-works/pi-ai": "1.0.4",
|
|
82
82
|
"@earendil-works/pi-client": "1.0.4",
|
|
83
|
+
"@earendil-works/pi-codemode": "1.1.0",
|
|
83
84
|
"@earendil-works/pi-durable": "1.0.4",
|
|
84
85
|
"@earendil-works/pi-protocol": "1.0.4",
|
|
85
86
|
"@earendil-works/pi-server": "1.0.4",
|