@zenera/neo 1.1.24 → 1.1.26
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/dist/agent.js +2 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/inspect/client.d.ts +1 -1
- package/dist/inspect/client.js +82 -11
- package/dist/inspect/css.d.ts +1 -1
- package/dist/inspect/css.js +1 -0
- package/dist/inspect/index.d.ts +1 -1
- package/dist/inspect/report.d.ts +9 -0
- package/dist/inspect/report.js +1 -0
- package/dist/lock.d.ts +27 -0
- package/dist/lock.js +66 -0
- package/dist/match.d.ts +44 -0
- package/dist/match.js +100 -0
- package/dist/memory/diff.d.ts +39 -0
- package/dist/memory/diff.js +95 -0
- package/dist/memory/files.d.ts +1 -1
- package/dist/memory/grep.d.ts +1 -1
- package/dist/memory/grep.js +2 -2
- package/dist/memory/instructions.d.ts +15 -0
- package/dist/memory/instructions.js +103 -0
- package/dist/memory/merge.js +1 -31
- package/dist/memory/store.d.ts +1 -5
- package/dist/memory/store.js +7 -53
- package/dist/memory/twin.d.ts +6 -0
- package/dist/memory/twin.js +40 -0
- package/dist/memory-stores/factory.d.ts +15 -0
- package/dist/memory-stores/factory.js +29 -0
- package/dist/memory-stores/file.d.ts +37 -0
- package/dist/memory-stores/file.js +174 -0
- package/dist/memory-stores/in-memory.d.ts +17 -0
- package/dist/memory-stores/in-memory.js +80 -0
- package/dist/memory-stores/index.d.ts +4 -0
- package/dist/memory-stores/index.js +5 -0
- package/dist/memory.d.ts +115 -0
- package/dist/memory.js +213 -0
- package/dist/models/factory.d.ts +24 -0
- package/dist/models/factory.js +153 -14
- package/dist/project/config.d.ts +9 -9
- package/dist/runner.js +7 -0
- package/dist/tools/sandbox.js +40 -2
- package/package.json +1 -1
package/dist/runner.js
CHANGED
|
@@ -449,6 +449,13 @@ export class AgentRunner {
|
|
|
449
449
|
catch (e) {
|
|
450
450
|
return fail(`error: arguments are not valid JSON: ${String(e)}`);
|
|
451
451
|
}
|
|
452
|
+
if (typeof args !== 'object' || args === null || Array.isArray(args)) {
|
|
453
|
+
return fail(`error: arguments to ${def.name} must be a JSON object`);
|
|
454
|
+
}
|
|
455
|
+
const missing = (def.parameters.required ?? []).filter((k) => args[k] == null);
|
|
456
|
+
if (missing.length) {
|
|
457
|
+
return fail(`error: ${def.name} is missing required arguments: ${missing.join(', ')}`);
|
|
458
|
+
}
|
|
452
459
|
try {
|
|
453
460
|
const out = await def.execute(args, {
|
|
454
461
|
ctx: state.context,
|
package/dist/tools/sandbox.js
CHANGED
|
@@ -243,7 +243,10 @@ export class Sandbox {
|
|
|
243
243
|
this.#created = true;
|
|
244
244
|
return;
|
|
245
245
|
}
|
|
246
|
-
await this.#
|
|
246
|
+
const made = await this.#podman(this.#createArgs());
|
|
247
|
+
if (made.code !== 0) {
|
|
248
|
+
throw new SandboxError(`could not create container ${this.name}: ${message(made)}`, LOCKS.test(made.stderr) ? locksHint(this.spec.engine) : undefined);
|
|
249
|
+
}
|
|
247
250
|
this.#created = true;
|
|
248
251
|
}
|
|
249
252
|
#createArgs() {
|
|
@@ -320,7 +323,13 @@ export class Sandbox {
|
|
|
320
323
|
const cwd = this.inside(opts.cwd);
|
|
321
324
|
const timeoutMs = this.#timeout(opts.timeout);
|
|
322
325
|
const startedAt = Date.now();
|
|
323
|
-
const
|
|
326
|
+
const once = () => this.#run(this.spec.engine, ['exec', '--interactive', '--workdir', cwd, this.name, '/bin/sh', '-s'], { input: command, timeoutMs, signal: opts.signal });
|
|
327
|
+
let res = await once();
|
|
328
|
+
if (gone(res)) {
|
|
329
|
+
// podman refused before running anything, so the retry cannot run the command twice.
|
|
330
|
+
await this.#revive(res);
|
|
331
|
+
res = await once();
|
|
332
|
+
}
|
|
324
333
|
return {
|
|
325
334
|
exit_code: res.code,
|
|
326
335
|
stdout: res.stdout,
|
|
@@ -527,6 +536,18 @@ export class Sandbox {
|
|
|
527
536
|
#podman(args) {
|
|
528
537
|
return this.#run(this.spec.engine, args, { timeoutMs: 120_000 });
|
|
529
538
|
}
|
|
539
|
+
/** The container stopped or vanished under us (machine slept, restarted, or someone removed it). */
|
|
540
|
+
async #revive(res) {
|
|
541
|
+
this.#ready = undefined;
|
|
542
|
+
try {
|
|
543
|
+
await this.start();
|
|
544
|
+
}
|
|
545
|
+
catch (err) {
|
|
546
|
+
throw new SandboxError(`the sandbox container ${this.name} stopped (${message(res)}) and could not be restarted: ` +
|
|
547
|
+
(err instanceof Error ? err.message : String(err)), `the ${this.spec.engine} machine may have stopped or restarted — check \`${this.spec.engine} machine list\`, ` +
|
|
548
|
+
`start it with \`${this.spec.engine} machine start\`, then retry`);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
530
551
|
async #must(args, what) {
|
|
531
552
|
const res = await this.#podman(args);
|
|
532
553
|
if (res.code !== 0) {
|
|
@@ -541,6 +562,23 @@ function mount(m) {
|
|
|
541
562
|
function message(res) {
|
|
542
563
|
return (res.stderr.trim() || res.stdout.trim() || `exit ${res.code}`).split('\n')[0];
|
|
543
564
|
}
|
|
565
|
+
/** podman's words for "every lock is taken": `allocating lock … exceeded num_locks (2048)`. */
|
|
566
|
+
const LOCKS = /exceeded num_locks|allocating lock/i;
|
|
567
|
+
/**
|
|
568
|
+
* A stopped container holds a lock as surely as a running one, and a
|
|
569
|
+
* persisted sandbox is stopped, never removed — so they pile up one per
|
|
570
|
+
* session until the engine can create nothing at all, for anyone.
|
|
571
|
+
*/
|
|
572
|
+
function locksHint(engine) {
|
|
573
|
+
return (`the ${engine} engine has no locks left: every container it holds, stopped ones ` +
|
|
574
|
+
`included, takes one. Remove the stopped sandbox containers with ` +
|
|
575
|
+
`\`${engine} container prune --force --filter label=zenera=1\`, then retry`);
|
|
576
|
+
}
|
|
577
|
+
/** podman's own exit code for "could not exec at all", with the two reasons that mean the container is not there to exec in. */
|
|
578
|
+
function gone(res) {
|
|
579
|
+
return (res.code === 125 &&
|
|
580
|
+
/can only create exec sessions on running containers|container state improper|no such container/i.test(res.stderr));
|
|
581
|
+
}
|
|
544
582
|
/** Only ever applied to paths this module derived, never to a model's text. */
|
|
545
583
|
function quote(s) {
|
|
546
584
|
return `'${s.replaceAll("'", `'\\''`)}'`;
|