@dougbots/avenor-core 0.5.0 → 0.5.2
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 +3 -3
- package/dist/index.d.ts +7 -0
- package/dist/index.js +70 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ Status values: `running`, `done`, `failed`, `timeout`, `killed`. If a permission
|
|
|
67
67
|
|
|
68
68
|
### `resultTool`
|
|
69
69
|
|
|
70
|
-
Waits for one run to finish and returns its
|
|
70
|
+
Waits for one run to finish and returns its complete final output without transcript or event details.
|
|
71
71
|
|
|
72
72
|
```ts
|
|
73
73
|
import { resultTool } from '@dougbots/avenor-core'
|
|
@@ -138,7 +138,7 @@ const { run_id } = await spawnTool({
|
|
|
138
138
|
label: 'security-review',
|
|
139
139
|
})
|
|
140
140
|
|
|
141
|
-
// 3. Wait for the
|
|
141
|
+
// 3. Wait for the complete final output
|
|
142
142
|
const result = await resultTool({ runId: run_id })
|
|
143
143
|
console.log(result) // { run_id, label, status: 'done', ready: true, output: '...' }
|
|
144
144
|
|
|
@@ -156,7 +156,7 @@ await shutdownTool()
|
|
|
156
156
|
| `findAvenorBinary` | function | Discover the avenor binary path |
|
|
157
157
|
| `spawnTool` | function | Start a new agent run |
|
|
158
158
|
| `statusTool` | function | Query run lifecycle status (single or all) |
|
|
159
|
-
| `resultTool` | function | Wait for and retrieve one run's
|
|
159
|
+
| `resultTool` | function | Wait for and retrieve one run's complete final output |
|
|
160
160
|
| `answerPermissionTool` | function | Answer a pending permission request |
|
|
161
161
|
| `followUpTool` | function | Resume a session with a follow-up prompt |
|
|
162
162
|
| `eventsTool` | function | Read recent events from a run's event log |
|
package/dist/index.d.ts
CHANGED
|
@@ -62,6 +62,7 @@ declare class Client {
|
|
|
62
62
|
events(options?: SubscribeOptions): AsyncIterableIterator<Event>;
|
|
63
63
|
history(options: HistoryOptions): Promise<HistoryResult>;
|
|
64
64
|
status(runtimeId?: string): Promise<Record<string, unknown>>;
|
|
65
|
+
result(runtimeId?: string): Promise<Record<string, unknown>>;
|
|
65
66
|
list(): Promise<Array<Record<string, unknown>>>;
|
|
66
67
|
spawn(params: SpawnParams): Promise<Record<string, unknown>>;
|
|
67
68
|
shutdown(mode: string): Promise<void>;
|
|
@@ -232,6 +233,9 @@ interface RunInfo {
|
|
|
232
233
|
eventLogPath: string;
|
|
233
234
|
runtimeId?: string;
|
|
234
235
|
sessionId?: string;
|
|
236
|
+
agent?: string;
|
|
237
|
+
backend?: string;
|
|
238
|
+
dir?: string;
|
|
235
239
|
brokerUrl?: string;
|
|
236
240
|
parentToken?: string;
|
|
237
241
|
}
|
|
@@ -318,6 +322,7 @@ interface StatusResult {
|
|
|
318
322
|
usage?: Record<string, unknown>;
|
|
319
323
|
latest_seq?: number;
|
|
320
324
|
final_output?: string;
|
|
325
|
+
final_output_truncated?: boolean;
|
|
321
326
|
}
|
|
322
327
|
declare function statusTool(args: {
|
|
323
328
|
runId?: string;
|
|
@@ -356,6 +361,8 @@ interface ResultResult {
|
|
|
356
361
|
stop_reason?: string;
|
|
357
362
|
pending_permission?: StatusResult['pending_permission'];
|
|
358
363
|
output?: string;
|
|
364
|
+
output_truncated?: boolean;
|
|
365
|
+
output_event_path?: string;
|
|
359
366
|
timed_out?: boolean;
|
|
360
367
|
}
|
|
361
368
|
interface ResultToolArgs {
|
package/dist/index.js
CHANGED
|
@@ -233,6 +233,10 @@ var Client = class {
|
|
|
233
233
|
const params = runtimeId ? { runtime_id: runtimeId } : void 0;
|
|
234
234
|
return this.call("status", params);
|
|
235
235
|
}
|
|
236
|
+
async result(runtimeId) {
|
|
237
|
+
const params = runtimeId ? { runtime_id: runtimeId } : void 0;
|
|
238
|
+
return this.call("result", params);
|
|
239
|
+
}
|
|
236
240
|
async list() {
|
|
237
241
|
return this.call("list");
|
|
238
242
|
}
|
|
@@ -1257,6 +1261,9 @@ var Supervisor = class Supervisor {
|
|
|
1257
1261
|
eventLogPath: result.on_event ?? eventLogPath,
|
|
1258
1262
|
runtimeId: result.runtime_id,
|
|
1259
1263
|
sessionId: result.session_id,
|
|
1264
|
+
agent: spawnParams.agent ?? params.agent,
|
|
1265
|
+
backend: spawnParams.backend,
|
|
1266
|
+
dir: spawnParams.dir,
|
|
1260
1267
|
brokerUrl: result.broker_url,
|
|
1261
1268
|
parentToken: result.parent_token
|
|
1262
1269
|
};
|
|
@@ -1497,7 +1504,8 @@ function buildBaseStatus(source, fallback, translatedStatus) {
|
|
|
1497
1504
|
event_path: stringField(source, "event_path", "on_event"),
|
|
1498
1505
|
usage: asRecord(source.usage) ?? void 0,
|
|
1499
1506
|
latest_seq: numberField(source, "latest_seq"),
|
|
1500
|
-
final_output: stringField(source, "final_output", "finalOutput")
|
|
1507
|
+
final_output: stringField(source, "final_output", "finalOutput"),
|
|
1508
|
+
...source.final_output_truncated === true && { final_output_truncated: true }
|
|
1501
1509
|
};
|
|
1502
1510
|
}
|
|
1503
1511
|
function shapeStatusResult(result, view = "full") {
|
|
@@ -1874,9 +1882,23 @@ function sleep(ms, signal) {
|
|
|
1874
1882
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1875
1883
|
});
|
|
1876
1884
|
}
|
|
1885
|
+
async function fullOutput(runtimeId, supervisorId) {
|
|
1886
|
+
if (supervisorId) {
|
|
1887
|
+
const { client, isSingleton } = await getSupervisorClient(supervisorId);
|
|
1888
|
+
try {
|
|
1889
|
+
const result = await client.result(runtimeId);
|
|
1890
|
+
return typeof result.final_output === "string" ? result.final_output : void 0;
|
|
1891
|
+
} finally {
|
|
1892
|
+
if (!isSingleton) client.close();
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
const result = await (await Supervisor.get()).getClient().result(runtimeId);
|
|
1896
|
+
return typeof result.final_output === "string" ? result.final_output : void 0;
|
|
1897
|
+
}
|
|
1877
1898
|
const defaultDeps = {
|
|
1878
1899
|
status: statusTool,
|
|
1879
1900
|
inspect: inspectTool,
|
|
1901
|
+
fullOutput,
|
|
1880
1902
|
sleep,
|
|
1881
1903
|
now: Date.now,
|
|
1882
1904
|
pollIntervalMs: DEFAULT_POLL_INTERVAL_MS
|
|
@@ -1893,6 +1915,8 @@ function toResult(status, timedOut = false) {
|
|
|
1893
1915
|
stop_reason: status.stop_reason,
|
|
1894
1916
|
pending_permission: status.pending_permission,
|
|
1895
1917
|
output: ready ? status.final_output : void 0,
|
|
1918
|
+
output_truncated: ready && status.final_output_truncated ? true : void 0,
|
|
1919
|
+
output_event_path: ready && status.final_output_truncated ? status.event_path : void 0,
|
|
1896
1920
|
timed_out: timedOut || void 0
|
|
1897
1921
|
};
|
|
1898
1922
|
}
|
|
@@ -1911,13 +1935,23 @@ async function executeResultTool(args, deps) {
|
|
|
1911
1935
|
const status = Array.isArray(raw) ? raw[0] : raw;
|
|
1912
1936
|
if (!status) throw new Error(`run not found: ${args.runId}`);
|
|
1913
1937
|
if (TERMINAL_STATUSES.has(status.status)) {
|
|
1914
|
-
|
|
1938
|
+
let exactOutputRetrieved = false;
|
|
1939
|
+
try {
|
|
1940
|
+
const output = await deps.fullOutput?.(status.runtime_id, args.supervisorId);
|
|
1941
|
+
if (output !== void 0) {
|
|
1942
|
+
status.final_output = output;
|
|
1943
|
+
status.final_output_truncated = false;
|
|
1944
|
+
exactOutputRetrieved = true;
|
|
1945
|
+
}
|
|
1946
|
+
} catch {}
|
|
1947
|
+
if (status.final_output === void 0) try {
|
|
1915
1948
|
const inspected = await deps.inspect({
|
|
1916
1949
|
runId: args.runId,
|
|
1917
1950
|
supervisorId: args.supervisorId
|
|
1918
1951
|
});
|
|
1919
1952
|
status.final_output = inspected.final_output ?? inspected.snapshot.final_output ?? inspected.snapshot.assistant_text;
|
|
1920
1953
|
} catch {}
|
|
1954
|
+
if (!exactOutputRetrieved && status.final_output !== void 0) status.final_output_truncated = true;
|
|
1921
1955
|
return toResult(status);
|
|
1922
1956
|
}
|
|
1923
1957
|
if (status.status === "waiting" || !wait) return toResult(status);
|
|
@@ -1970,6 +2004,10 @@ function findRunByLabel(sup, runId) {
|
|
|
1970
2004
|
if (byKey) return byKey;
|
|
1971
2005
|
for (const info of runs.values()) if (info.label === runId) return info;
|
|
1972
2006
|
}
|
|
2007
|
+
function requireResumableAgent(agent) {
|
|
2008
|
+
if (agent === void 0) throw new Error("run has no agent to resume");
|
|
2009
|
+
return agent;
|
|
2010
|
+
}
|
|
1973
2011
|
async function parseSentinel(filePath) {
|
|
1974
2012
|
try {
|
|
1975
2013
|
const content = (await fs.promises.readFile(filePath, "utf-8")).trim();
|
|
@@ -1990,28 +2028,36 @@ async function parseSentinel(filePath) {
|
|
|
1990
2028
|
}
|
|
1991
2029
|
async function followUpTool(args) {
|
|
1992
2030
|
if (args.supervisorId) {
|
|
1993
|
-
const { client, isSingleton } = await getSupervisorClient(args.supervisorId);
|
|
2031
|
+
const { client, isSingleton, sup } = await getSupervisorClient(args.supervisorId);
|
|
1994
2032
|
try {
|
|
1995
2033
|
validateRunId(args.runId);
|
|
2034
|
+
let runInfo;
|
|
2035
|
+
if (isSingleton && sup) runInfo = findRunByLabel(sup, args.runId);
|
|
2036
|
+
const fallbackSessionId = runInfo?.sessionId;
|
|
1996
2037
|
let liveStatus = null;
|
|
1997
2038
|
try {
|
|
1998
2039
|
liveStatus = await client.status(args.runId);
|
|
1999
2040
|
} catch {}
|
|
2000
|
-
const
|
|
2001
|
-
if (!
|
|
2002
|
-
const agent = liveStatus?.agent ??
|
|
2041
|
+
const sessionId = (await parseSentinel(liveStatus?.sentinel_file ?? path.join(runsRoot(), args.runId, "sentinel.done")))?.SESSION ?? liveStatus?.session_id ?? fallbackSessionId;
|
|
2042
|
+
if (!sessionId) throw new Error("run has no session to resume");
|
|
2043
|
+
const agent = requireResumableAgent(liveStatus?.agent ?? runInfo?.agent);
|
|
2044
|
+
const backend = liveStatus?.backend ?? runInfo?.backend;
|
|
2045
|
+
const dir = liveStatus?.dir ?? runInfo?.dir;
|
|
2003
2046
|
const followUpRunId = crypto.randomUUID();
|
|
2004
2047
|
const followUpLabel = args.label ?? `${args.runId}-followup`;
|
|
2005
2048
|
const { sentinelPath: followUpSentinelPath, eventLogPath } = ensureRunPaths(followUpRunId);
|
|
2049
|
+
const spawnParams = {
|
|
2050
|
+
agent,
|
|
2051
|
+
prompt: args.message,
|
|
2052
|
+
label: followUpLabel,
|
|
2053
|
+
session_id: sessionId,
|
|
2054
|
+
sentinel_file: followUpSentinelPath,
|
|
2055
|
+
on_event: eventLogPath
|
|
2056
|
+
};
|
|
2057
|
+
if (backend) spawnParams.backend = backend;
|
|
2058
|
+
if (dir) spawnParams.dir = dir;
|
|
2006
2059
|
return {
|
|
2007
|
-
run_id: (await client.spawn(
|
|
2008
|
-
agent,
|
|
2009
|
-
prompt: args.message,
|
|
2010
|
-
label: followUpLabel,
|
|
2011
|
-
session_id: sentinel.SESSION,
|
|
2012
|
-
sentinel_file: followUpSentinelPath,
|
|
2013
|
-
on_event: eventLogPath
|
|
2014
|
-
})).runtime_id ?? followUpRunId,
|
|
2060
|
+
run_id: (await client.spawn(spawnParams)).runtime_id ?? followUpRunId,
|
|
2015
2061
|
label: followUpLabel
|
|
2016
2062
|
};
|
|
2017
2063
|
} finally {
|
|
@@ -2021,18 +2067,23 @@ async function followUpTool(args) {
|
|
|
2021
2067
|
const sup = await Supervisor.get();
|
|
2022
2068
|
const runInfo = findRunByLabel(sup, args.runId);
|
|
2023
2069
|
if (!runInfo) throw new Error(`run not found: ${args.runId}`);
|
|
2024
|
-
const
|
|
2025
|
-
if (!
|
|
2070
|
+
const sessionId = (await parseSentinel(runInfo.sentinelPath))?.SESSION ?? runInfo.sessionId;
|
|
2071
|
+
if (!sessionId) throw new Error("run has no session to resume");
|
|
2026
2072
|
const client = sup.getClient();
|
|
2027
|
-
let
|
|
2073
|
+
let liveStatus = null;
|
|
2028
2074
|
if (runInfo.runtimeId) try {
|
|
2029
|
-
|
|
2075
|
+
liveStatus = await client.status(runInfo.runtimeId);
|
|
2030
2076
|
} catch {}
|
|
2077
|
+
const agent = requireResumableAgent(liveStatus?.agent ?? runInfo.agent);
|
|
2078
|
+
const backend = liveStatus?.backend ?? runInfo.backend;
|
|
2079
|
+
const dir = liveStatus?.dir ?? runInfo.dir;
|
|
2031
2080
|
const followUpLabel = args.label ?? `${runInfo.label}-followup`;
|
|
2032
2081
|
const followUpRun = await sup.spawn({
|
|
2033
2082
|
agent,
|
|
2083
|
+
backend,
|
|
2084
|
+
dir,
|
|
2034
2085
|
prompt: args.message,
|
|
2035
|
-
session_id:
|
|
2086
|
+
session_id: sessionId,
|
|
2036
2087
|
label: followUpLabel
|
|
2037
2088
|
});
|
|
2038
2089
|
return {
|