@zenera/engine 1.1.54 → 1.1.55
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/engine.d.ts +12 -5
- package/dist/engine.js +32 -3
- package/package.json +2 -2
package/dist/engine.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AgentRunner, Workspace, type AgentEvent, type AgentProject, type AgentState, type Input, type MemoryIndex, type RunIdentity, type RunResult } from '@zenera/neo';
|
|
1
|
+
import { AgentRunner, Workspace, type AgentEvent, type AgentProject, type AgentState, type Input, type ResumeAnswer, type MemoryIndex, type RunIdentity, type RunResult } from '@zenera/neo';
|
|
2
2
|
import { type ModelIssue } from './audit.ts';
|
|
3
3
|
import { type Logger } from './errors.ts';
|
|
4
|
-
import { type Project } from './projects.ts';
|
|
5
4
|
import { type ZenPlugin } from './plugins.ts';
|
|
5
|
+
import { type Project } from './projects.ts';
|
|
6
6
|
import { type Preflight, type SandboxSetup } from './sandbox.ts';
|
|
7
7
|
import { type Held, type RunPaths, type SessionPaths } from './session.ts';
|
|
8
8
|
/** Who a run acts for — re-exported so a host needs only this package. */
|
|
@@ -27,9 +27,9 @@ export interface EngineOptions {
|
|
|
27
27
|
/** recall only: nothing is written and several runs may share one graph */
|
|
28
28
|
memoryReadOnly?: boolean;
|
|
29
29
|
/**
|
|
30
|
-
* An already-open graph to remember into instead of opening `memoryDir`.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* An already-open graph to remember into instead of opening `memoryDir`.
|
|
31
|
+
* Sessions may each open the same directory; handing them one index saves
|
|
32
|
+
* every session loading the graph again.
|
|
33
33
|
* Name its directory in `memoryDir` too: that is what is mounted at `/memory`.
|
|
34
34
|
*/
|
|
35
35
|
memory?: MemoryIndex;
|
|
@@ -148,4 +148,11 @@ export declare function envelope(engine: Engine, outcome: RunOutcome): Record<st
|
|
|
148
148
|
* command.
|
|
149
149
|
*/
|
|
150
150
|
export declare function runEngine(engine: Engine, input: Input, onEvent?: (event: AgentEvent) => void, signal?: AbortSignal): Promise<RunOutcome>;
|
|
151
|
+
/**
|
|
152
|
+
* Continues a session whose last run stopped `suspended`: `answers` answer its
|
|
153
|
+
* suspended calls (re-run, a result, or cancelled - see `ResumeAnswer`). The
|
|
154
|
+
* run is recorded like any other turn; its input reads as the answers given.
|
|
155
|
+
* Calls left unanswered keep it suspended.
|
|
156
|
+
*/
|
|
157
|
+
export declare function resumeEngine(engine: Engine, answers: Record<string, ResumeAnswer>, onEvent?: (event: AgentEvent) => void, signal?: AbortSignal): Promise<RunOutcome>;
|
|
151
158
|
//# sourceMappingURL=engine.d.ts.map
|
package/dist/engine.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AgentRunner, FilePayloadStore, SANDBOX_MOUNT, SKILLS_MOUNT, Workspace, assertState, buildRunReport, compactIdentity, exaTools, fileTools, identityFromEnv, identityTools, lastText, loadProject, memoryDir, readProjectConfig, renderReportHtml, sandboxTools, turns, } from '@zenera/neo';
|
|
1
|
+
import { AgentRunner, FilePayloadStore, MemoryError, SANDBOX_MOUNT, SKILLS_MOUNT, Workspace, assertState, buildRunReport, compactIdentity, exaTools, fileTools, identityFromEnv, identityTools, lastText, loadProject, memoryDir, readProjectConfig, renderReportHtml, sandboxTools, turns, } from '@zenera/neo';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
3
|
import { writeFile } from 'node:fs/promises';
|
|
4
4
|
import { resolve } from 'node:path';
|
|
@@ -8,8 +8,8 @@ import { loadProjectEnv } from "./env.js";
|
|
|
8
8
|
import { EXIT, EngineError, invalidError, stderrLogger, usageError, } from "./errors.js";
|
|
9
9
|
import { readJson, writeJson } from "./home.js";
|
|
10
10
|
import { KeyStore, assertUsable } from "./keys.js";
|
|
11
|
-
import { projectMounts } from "./projects.js";
|
|
12
11
|
import { envPlugins, loadPlugins, mergePlugins, } from "./plugins.js";
|
|
12
|
+
import { projectMounts } from "./projects.js";
|
|
13
13
|
import { buildSandbox, prepareHome, teardown, usesSandbox, } from "./sandbox.js";
|
|
14
14
|
import { acquire, createRun, readSessionMeta, writeRunMeta, writeSessionMeta, } from "./session.js";
|
|
15
15
|
/**
|
|
@@ -118,7 +118,7 @@ export async function openEngine(opts) {
|
|
|
118
118
|
}
|
|
119
119
|
catch (err) {
|
|
120
120
|
await plugins?.close();
|
|
121
|
-
throw invalidError(err instanceof Error ? err.message : String(err), `while loading ${opts.project.dir}`);
|
|
121
|
+
throw invalidError(err instanceof Error ? err.message : String(err), err instanceof MemoryError && err.hint ? err.hint : `while loading ${opts.project.dir}`);
|
|
122
122
|
}
|
|
123
123
|
const loaded = plugins;
|
|
124
124
|
let state;
|
|
@@ -275,6 +275,35 @@ export async function runEngine(engine, input, onEvent, signal) {
|
|
|
275
275
|
}
|
|
276
276
|
return outcome;
|
|
277
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* Continues a session whose last run stopped `suspended`: `answers` answer its
|
|
280
|
+
* suspended calls (re-run, a result, or cancelled - see `ResumeAnswer`). The
|
|
281
|
+
* run is recorded like any other turn; its input reads as the answers given.
|
|
282
|
+
* Calls left unanswered keep it suspended.
|
|
283
|
+
*/
|
|
284
|
+
export async function resumeEngine(engine, answers, onEvent, signal) {
|
|
285
|
+
if (!engine.state?.suspended?.length) {
|
|
286
|
+
throw usageError('this session is not waiting on anything to resume');
|
|
287
|
+
}
|
|
288
|
+
const startedAt = new Date();
|
|
289
|
+
const stream = engine.runner.resume(engine.state, { answers, signal });
|
|
290
|
+
if (onEvent) {
|
|
291
|
+
for await (const event of stream) {
|
|
292
|
+
onEvent(event);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const result = await stream.final();
|
|
296
|
+
const durationMs = Date.now() - startedAt.getTime();
|
|
297
|
+
engine.state = result.state;
|
|
298
|
+
const input = `(resumed: ${Object.entries(answers)
|
|
299
|
+
.map(([id, a]) => `${id} ${a.status}`)
|
|
300
|
+
.join(', ')})`;
|
|
301
|
+
const outcome = await record(engine, input, result, startedAt, durationMs);
|
|
302
|
+
if (result.stopReason === 'failed') {
|
|
303
|
+
throw new EngineError(result.state.error ?? 'the run failed', EXIT.failed, `report: ${outcome.run.report}`);
|
|
304
|
+
}
|
|
305
|
+
return outcome;
|
|
306
|
+
}
|
|
278
307
|
/**
|
|
279
308
|
* Everything a finished turn leaves behind. The session state is written first:
|
|
280
309
|
* if the report fails to render, the conversation is still resumable, which is
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenera/engine",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.55",
|
|
4
4
|
"description": "Runs a @zenera/neo project on this machine: keyring, sandbox, sessions and the record each turn leaves behind.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -45,6 +45,6 @@
|
|
|
45
45
|
"prepack": "tsc -b"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@zenera/neo": "^1.1.
|
|
48
|
+
"@zenera/neo": "^1.1.55"
|
|
49
49
|
}
|
|
50
50
|
}
|