nexus-agentd 0.2.6 → 0.3.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/LICENSE +22 -22
- package/README.md +103 -14
- package/dist/a2a/runtime.d.ts +4 -1
- package/dist/a2a/runtime.js +213 -10
- package/dist/acp/runtime.js +13 -6
- package/dist/artifact-store.d.ts +162 -0
- package/dist/artifact-store.js +1081 -0
- package/dist/cli.js +13 -14
- package/dist/config.js +45 -5
- package/dist/control-plane-validation.d.ts +54 -0
- package/dist/control-plane-validation.js +152 -0
- package/dist/control-plane.d.ts +9 -32
- package/dist/control-plane.js +41 -157
- package/dist/drivers/index.js +12 -0
- package/dist/drivers/pi.js +1 -1
- package/dist/drivers/stdio.d.ts +4 -1
- package/dist/drivers/stdio.js +135 -19
- package/dist/events.d.ts +9 -0
- package/dist/events.js +17 -4
- package/dist/index.js +10 -1
- package/dist/process-tree.js +15 -6
- package/dist/run-store.d.ts +52 -7
- package/dist/run-store.js +178 -22
- package/dist/server/auth-policy.d.ts +27 -0
- package/dist/server/auth-policy.js +143 -0
- package/dist/server/connection.d.ts +8 -0
- package/dist/server/connection.js +67 -0
- package/dist/server/diagnostics.d.ts +40 -0
- package/dist/server/diagnostics.js +130 -0
- package/dist/server/metrics.d.ts +51 -0
- package/dist/server/metrics.js +56 -0
- package/dist/server/quota.d.ts +59 -0
- package/dist/server/quota.js +176 -0
- package/dist/server/validation.d.ts +29 -0
- package/dist/server/validation.js +221 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +682 -418
- package/dist/session/admin-runs.d.ts +73 -0
- package/dist/session/admin-runs.js +297 -0
- package/dist/session/admission.d.ts +32 -0
- package/dist/session/admission.js +62 -0
- package/dist/session/readiness.d.ts +33 -0
- package/dist/session/readiness.js +174 -0
- package/dist/session.d.ts +58 -6
- package/dist/session.js +244 -109
- package/dist/sse-writer.d.ts +7 -0
- package/dist/sse-writer.js +60 -0
- package/dist/types.d.ts +44 -2
- package/dist/types.js +1 -0
- package/dist/webui/app/sources.js +16 -8
- package/dist/webui/index.js +11 -11
- package/dist/webui/markup.js +2 -0
- package/dist/webui/styles.js +46 -1
- package/examples/client.mjs +102 -0
- package/nexus-agentd.example.json +53 -34
- package/package.json +3 -2
package/dist/drivers/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { createHermesDriver } from './hermes.js';
|
|
|
4
4
|
import { createOpenCodeDriver } from './opencode.js';
|
|
5
5
|
import { createOpenClawDriver } from './openclaw.js';
|
|
6
6
|
import { createPiDriver } from './pi.js';
|
|
7
|
+
import { createStdioAcpDriver } from './stdio.js';
|
|
7
8
|
export function createDriverRegistry(config) {
|
|
8
9
|
const drivers = new Map();
|
|
9
10
|
for (const [id, driver] of Object.entries(config.agents)) {
|
|
@@ -12,6 +13,17 @@ export function createDriverRegistry(config) {
|
|
|
12
13
|
if (driver.enabled === false)
|
|
13
14
|
continue;
|
|
14
15
|
switch (driver.driver) {
|
|
16
|
+
case 'stdio':
|
|
17
|
+
if (!driver.command)
|
|
18
|
+
break;
|
|
19
|
+
drivers.set(id, createStdioAcpDriver(id, driver, {
|
|
20
|
+
name: driver.name || id,
|
|
21
|
+
description: driver.description || 'Custom ACP agent over stdio',
|
|
22
|
+
command: driver.command,
|
|
23
|
+
args: driver.args || [],
|
|
24
|
+
probeArgs: driver.probeArgs
|
|
25
|
+
}));
|
|
26
|
+
break;
|
|
15
27
|
case 'opencode':
|
|
16
28
|
drivers.set(id, createOpenCodeDriver(id, driver));
|
|
17
29
|
break;
|
package/dist/drivers/pi.js
CHANGED
|
@@ -15,7 +15,7 @@ export function createPiDriver(id, config) {
|
|
|
15
15
|
return adapter;
|
|
16
16
|
const command = driver.env.PI_ACP_PI_COMMAND || 'pi';
|
|
17
17
|
try {
|
|
18
|
-
const version = await probeCommand(command, ['--version'], driver.env, 'Pi runtime');
|
|
18
|
+
const version = await probeCommand(command, ['--version'], driver.env, 'Pi runtime', { ownsProcessGroup: process.platform !== 'win32' });
|
|
19
19
|
return { ...adapter, version };
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
package/dist/drivers/stdio.d.ts
CHANGED
|
@@ -10,4 +10,7 @@ export interface StdioAcpDriverDefaults {
|
|
|
10
10
|
}
|
|
11
11
|
export declare function createStdioAcpDriver(id: string, config: AgentdDriverConfig, defaults: StdioAcpDriverDefaults): AgentDriver;
|
|
12
12
|
export declare function buildEnvironment(config: AgentdDriverConfig, defaults?: Record<string, string>): NodeJS.ProcessEnv;
|
|
13
|
-
export declare function probeCommand(command: string, args: string[], env: NodeJS.ProcessEnv, label: string
|
|
13
|
+
export declare function probeCommand(command: string, args: string[], env: NodeJS.ProcessEnv, label: string, options?: {
|
|
14
|
+
ownsProcessGroup?: boolean;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
}): Promise<string>;
|
package/dist/drivers/stdio.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
+
import { existsSync, statSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
2
5
|
import { resolveSecret } from '../config.js';
|
|
6
|
+
import { terminateProcessTree } from '../process-tree.js';
|
|
3
7
|
const BASE_ENV_KEYS = [
|
|
4
8
|
'PATH',
|
|
5
9
|
'HOME',
|
|
@@ -11,7 +15,17 @@ const BASE_ENV_KEYS = [
|
|
|
11
15
|
'TMPDIR',
|
|
12
16
|
'TEMP',
|
|
13
17
|
'LANG',
|
|
14
|
-
'LC_ALL'
|
|
18
|
+
'LC_ALL',
|
|
19
|
+
// Node's Windows process creation and a number of ACP launchers require
|
|
20
|
+
// these values even when the command itself is an absolute path.
|
|
21
|
+
'SystemRoot',
|
|
22
|
+
'ComSpec',
|
|
23
|
+
'USERPROFILE',
|
|
24
|
+
'APPDATA',
|
|
25
|
+
'LOCALAPPDATA',
|
|
26
|
+
'ProgramFiles',
|
|
27
|
+
'ProgramFiles(x86)',
|
|
28
|
+
'PATHEXT'
|
|
15
29
|
];
|
|
16
30
|
export function createStdioAcpDriver(id, config, defaults) {
|
|
17
31
|
const command = config.command || defaults.command;
|
|
@@ -31,7 +45,7 @@ export function createStdioAcpDriver(id, config, defaults) {
|
|
|
31
45
|
ownsProcessGroup: process.platform !== 'win32',
|
|
32
46
|
async probe() {
|
|
33
47
|
try {
|
|
34
|
-
const version = await probeCommand(command, defaults.probeArgs || ['--version'], env, name);
|
|
48
|
+
const version = await probeCommand(command, config.probeArgs || defaults.probeArgs || ['--version'], env, name, { ownsProcessGroup: process.platform !== 'win32' });
|
|
35
49
|
return {
|
|
36
50
|
id,
|
|
37
51
|
name,
|
|
@@ -53,7 +67,7 @@ export function createStdioAcpDriver(id, config, defaults) {
|
|
|
53
67
|
}
|
|
54
68
|
},
|
|
55
69
|
spawn(workspace) {
|
|
56
|
-
return
|
|
70
|
+
return spawnCommand(command, args, {
|
|
57
71
|
cwd: workspace,
|
|
58
72
|
env,
|
|
59
73
|
detached: process.platform !== 'win32',
|
|
@@ -75,42 +89,144 @@ export function buildEnvironment(config, defaults = {}) {
|
|
|
75
89
|
}
|
|
76
90
|
return result;
|
|
77
91
|
}
|
|
78
|
-
export function probeCommand(command, args, env, label) {
|
|
92
|
+
export function probeCommand(command, args, env, label, options = {}) {
|
|
79
93
|
return new Promise((resolve, reject) => {
|
|
80
|
-
const child =
|
|
94
|
+
const child = spawnCommand(command, args, {
|
|
81
95
|
env,
|
|
82
|
-
stdio: ['ignore', 'pipe', 'pipe']
|
|
96
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
97
|
+
detached: options.ownsProcessGroup ?? process.platform !== 'win32',
|
|
98
|
+
windowsHide: true
|
|
83
99
|
});
|
|
84
100
|
let output = '';
|
|
85
101
|
let settled = false;
|
|
102
|
+
let finishing = false;
|
|
103
|
+
let timedOut = false;
|
|
104
|
+
let timer;
|
|
86
105
|
const finish = (error) => {
|
|
87
106
|
if (settled)
|
|
88
107
|
return;
|
|
89
108
|
settled = true;
|
|
90
|
-
|
|
109
|
+
if (timer)
|
|
110
|
+
clearTimeout(timer);
|
|
91
111
|
if (error)
|
|
92
112
|
reject(error);
|
|
93
113
|
else
|
|
94
114
|
resolve(output.trim().split(/\r?\n/)[0] || 'unknown');
|
|
95
115
|
};
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
116
|
+
const ownsProcessGroup = options.ownsProcessGroup ?? process.platform !== 'win32';
|
|
117
|
+
const cleanup = () => terminateProcessTree(child, {
|
|
118
|
+
ownsProcessGroup,
|
|
119
|
+
graceMs: 250
|
|
120
|
+
});
|
|
121
|
+
const cleanupFailure = (error) => error instanceof Error ? error.message : String(error);
|
|
122
|
+
const settleExit = (code, signal) => {
|
|
123
|
+
if (settled || finishing || timedOut)
|
|
124
|
+
return;
|
|
125
|
+
finishing = true;
|
|
126
|
+
if (timer)
|
|
127
|
+
clearTimeout(timer);
|
|
128
|
+
// A successful wrapper can leave a child in its process group.
|
|
129
|
+
// Clean the group before exposing probe success/failure.
|
|
130
|
+
void cleanup().then(() => {
|
|
131
|
+
if (timedOut || settled)
|
|
132
|
+
return;
|
|
133
|
+
finishing = false;
|
|
134
|
+
if (code === 0)
|
|
135
|
+
finish();
|
|
136
|
+
else {
|
|
137
|
+
finish(new Error(output.trim() ||
|
|
138
|
+
`${label} probe exited with ${signal || code || 'unknown'}`));
|
|
139
|
+
}
|
|
140
|
+
}, (error) => {
|
|
141
|
+
if (settled)
|
|
142
|
+
return;
|
|
143
|
+
finishing = false;
|
|
144
|
+
finish(new Error(`${label} probe cleanup failed: ${cleanupFailure(error)}`));
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
timer = setTimeout(() => {
|
|
148
|
+
if (settled || finishing || timedOut)
|
|
149
|
+
return;
|
|
150
|
+
timedOut = true;
|
|
151
|
+
finishing = true;
|
|
152
|
+
if (timer)
|
|
153
|
+
clearTimeout(timer);
|
|
154
|
+
// Probe commands are allowed to be wrappers that launch another
|
|
155
|
+
// process. Wait for tree termination before rejecting so a timed
|
|
156
|
+
// out health check cannot leave an agent running in the background.
|
|
157
|
+
void cleanup().then(() => finish(new Error(`${label} probe timed out`)), (error) => finish(new Error(`${label} probe timed out; cleanup failed: ${cleanupFailure(error)}`)));
|
|
158
|
+
}, options.timeoutMs ?? 5000);
|
|
159
|
+
timer.unref?.();
|
|
100
160
|
child.stdout.on('data', (chunk) => {
|
|
101
161
|
output = `${output}${String(chunk)}`.slice(-8192);
|
|
102
162
|
});
|
|
103
163
|
child.stderr.on('data', (chunk) => {
|
|
104
164
|
output = `${output}${String(chunk)}`.slice(-8192);
|
|
105
165
|
});
|
|
106
|
-
child.once('error', (error) =>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
166
|
+
child.once('error', (error) => {
|
|
167
|
+
if (settled || finishing || timedOut)
|
|
168
|
+
return;
|
|
169
|
+
finishing = true;
|
|
170
|
+
if (timer)
|
|
171
|
+
clearTimeout(timer);
|
|
172
|
+
void cleanup().then(() => finish(error), (cleanupError) => finish(new Error(`${label} probe failed (${error.message}); cleanup failed: ${cleanupFailure(cleanupError)}`)));
|
|
114
173
|
});
|
|
174
|
+
child.once('exit', (code, signal) => settleExit(code, signal));
|
|
115
175
|
});
|
|
116
176
|
}
|
|
177
|
+
function needsWindowsShell(command) {
|
|
178
|
+
return process.platform === 'win32' && /\.(?:cmd|bat)$/i.test(command);
|
|
179
|
+
}
|
|
180
|
+
function spawnCommand(command, args, options) {
|
|
181
|
+
const resolvedCommand = resolveWindowsCommand(command, options.env, options.cwd);
|
|
182
|
+
if (!needsWindowsShell(resolvedCommand)) {
|
|
183
|
+
return spawn(resolvedCommand, args, options);
|
|
184
|
+
}
|
|
185
|
+
// cmd.exe's /S /C parser needs an outer pair around the complete command
|
|
186
|
+
// when the batch path itself is quoted; otherwise it treats the first
|
|
187
|
+
// argument as part of the executable path.
|
|
188
|
+
const commandLine = `"${[quoteWindowsArg(resolvedCommand), ...args.map(quoteWindowsArg)].join(' ')}"`;
|
|
189
|
+
return spawn(process.env.ComSpec || 'cmd.exe', ['/d', '/s', '/c', commandLine], {
|
|
190
|
+
...options,
|
|
191
|
+
windowsVerbatimArguments: true,
|
|
192
|
+
shell: false
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function resolveWindowsCommand(command, env, cwd) {
|
|
196
|
+
if (process.platform !== 'win32')
|
|
197
|
+
return command;
|
|
198
|
+
const pathValue = env?.PATH || process.env.PATH || '';
|
|
199
|
+
const directory = cwd instanceof URL ? fileURLToPath(cwd) : cwd || process.cwd();
|
|
200
|
+
const pathEntries = pathValue.split(path.delimiter).filter(Boolean).map((entry) => entry.replace(/^"|"$/g, ''));
|
|
201
|
+
const pathExtValue = env?.PATHEXT || process.env.PATHEXT || '.COM;.EXE;.BAT;.CMD';
|
|
202
|
+
const extensions = pathExtValue
|
|
203
|
+
.split(';')
|
|
204
|
+
.map((extension) => extension.trim())
|
|
205
|
+
.filter((extension) => /^\.(?:com|exe|bat|cmd)$/i.test(extension));
|
|
206
|
+
// npm installs a POSIX shim without an extension beside its .cmd shim.
|
|
207
|
+
// That file is not a Windows executable; selecting it makes real npm
|
|
208
|
+
// commands fail even though a runnable .cmd exists in the same directory.
|
|
209
|
+
const names = /\.(?:com|exe|bat|cmd)$/i.test(command)
|
|
210
|
+
? [command] : extensions.map((extension) => `${command}${extension}`);
|
|
211
|
+
const candidates = commandHasPath(command)
|
|
212
|
+
? names.map((name) => path.resolve(directory, name))
|
|
213
|
+
: [directory, ...pathEntries].flatMap((entry) => names.map((name) => path.resolve(directory, entry, name)));
|
|
214
|
+
const match = candidates.find(isRegularFile);
|
|
215
|
+
return match || command;
|
|
216
|
+
}
|
|
217
|
+
function commandHasPath(command) {
|
|
218
|
+
return command.includes('\\') || command.includes('/') || path.win32.isAbsolute(command);
|
|
219
|
+
}
|
|
220
|
+
function isRegularFile(file) {
|
|
221
|
+
try {
|
|
222
|
+
return existsSync(file) && statSync(file).isFile();
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function quoteWindowsArg(value) {
|
|
229
|
+
if (!/[\s"&()^|<>]/.test(value))
|
|
230
|
+
return value;
|
|
231
|
+
return `"${value.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/g, '$1$1')}"`;
|
|
232
|
+
}
|
package/dist/events.d.ts
CHANGED
|
@@ -8,6 +8,15 @@ export declare class SessionEventLog {
|
|
|
8
8
|
constructor(sessionId: string, maxEvents: number);
|
|
9
9
|
append(type: AgentdEventType, data?: unknown): AgentdEvent;
|
|
10
10
|
after(id?: string): AgentdEvent[];
|
|
11
|
+
replay(id?: string): {
|
|
12
|
+
earliestId: string;
|
|
13
|
+
latestId: string;
|
|
14
|
+
reset: {
|
|
15
|
+
reason: string;
|
|
16
|
+
requestedAfter: string | null;
|
|
17
|
+
} | undefined;
|
|
18
|
+
events: AgentdEvent[];
|
|
19
|
+
};
|
|
11
20
|
subscribe(listener: (event: AgentdEvent) => void): () => boolean;
|
|
12
21
|
get lastId(): string | undefined;
|
|
13
22
|
}
|
package/dist/events.js
CHANGED
|
@@ -36,10 +36,23 @@ export class SessionEventLog {
|
|
|
36
36
|
return event;
|
|
37
37
|
}
|
|
38
38
|
after(id) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
return this.replay(id).events;
|
|
40
|
+
}
|
|
41
|
+
replay(id) {
|
|
42
|
+
const sequence = id === undefined ? 0 : Number(id);
|
|
43
|
+
const earliest = Number(this.events[0]?.id || this.sequence + 1);
|
|
44
|
+
const reason = id !== undefined && (!/^\d+$/.test(id) || !Number.isSafeInteger(sequence))
|
|
45
|
+
? 'invalid'
|
|
46
|
+
: sequence > this.sequence ? 'ahead'
|
|
47
|
+
: sequence < earliest - 1 ? 'expired' : undefined;
|
|
48
|
+
return {
|
|
49
|
+
earliestId: this.events[0]?.id ?? null,
|
|
50
|
+
latestId: String(this.sequence),
|
|
51
|
+
reset: reason ? { reason, requestedAfter: id ?? null } : undefined,
|
|
52
|
+
events: reason ? [] : this.events
|
|
53
|
+
.filter((event) => Number(event.id) > sequence)
|
|
54
|
+
.map((event) => structuredClone(event))
|
|
55
|
+
};
|
|
43
56
|
}
|
|
44
57
|
subscribe(listener) {
|
|
45
58
|
this.listeners.add(listener);
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,16 @@ import { WorkspacePolicy } from './workspace.js';
|
|
|
9
9
|
export async function startAgentd(configPath) {
|
|
10
10
|
const absoluteConfigPath = path.resolve(configPath);
|
|
11
11
|
const config = await loadAgentdConfig(absoluteConfigPath);
|
|
12
|
-
const runStore = new RunStore(runStorePathForConfig(absoluteConfigPath),
|
|
12
|
+
const runStore = new RunStore(runStorePathForConfig(absoluteConfigPath), {
|
|
13
|
+
maxRuns: config.history?.maxRuns ?? 1000,
|
|
14
|
+
maxTaskChars: config.maxRequestBytes,
|
|
15
|
+
historyRetentionDays: config.history?.retentionDays ?? 30,
|
|
16
|
+
historyMaxBytes: config.history?.maxBytes ?? 64 * 1024 * 1024,
|
|
17
|
+
retentionDays: config.artifacts?.retentionDays ?? 30,
|
|
18
|
+
maxTotalBytes: config.artifacts?.maxBytes ?? 512 * 1024 * 1024,
|
|
19
|
+
maxArtifactBytes: config.artifacts?.maxArtifactBytes ?? 12 * 1024 * 1024,
|
|
20
|
+
maxQueuedBytes: config.artifacts?.maxQueuedBytes ?? 64 * 1024 * 1024
|
|
21
|
+
});
|
|
13
22
|
await runStore.init();
|
|
14
23
|
const workspacePolicy = await WorkspacePolicy.create(config.workspaceRoots);
|
|
15
24
|
const sessions = new SessionManager(config, workspacePolicy, createDriverRegistry(config), runStore);
|
package/dist/process-tree.js
CHANGED
|
@@ -3,30 +3,39 @@ const DEFAULT_GRACE_MS = 2_000;
|
|
|
3
3
|
const FORCE_KILL_WAIT_MS = 1_000;
|
|
4
4
|
export async function terminateProcessTree(child, options = {}) {
|
|
5
5
|
const pid = child.pid;
|
|
6
|
-
if (!pid
|
|
6
|
+
if (!pid)
|
|
7
7
|
return;
|
|
8
8
|
const graceMs = Math.max(0, options.graceMs ?? DEFAULT_GRACE_MS);
|
|
9
9
|
if (process.platform === 'win32') {
|
|
10
|
+
// Once a Windows process has exited taskkill can no longer address its
|
|
11
|
+
// descendants by the parent's PID. Callers should tear down before
|
|
12
|
+
// exit when they need Windows tree semantics.
|
|
13
|
+
if (hasExited(child))
|
|
14
|
+
return;
|
|
10
15
|
await taskkill(pid, false);
|
|
11
16
|
if (await waitForExit(child, graceMs))
|
|
12
17
|
return;
|
|
13
18
|
await taskkill(pid, true);
|
|
14
|
-
await waitForExit(child, FORCE_KILL_WAIT_MS)
|
|
15
|
-
|
|
19
|
+
if (await waitForExit(child, FORCE_KILL_WAIT_MS))
|
|
20
|
+
return;
|
|
21
|
+
throw new Error(`Failed to terminate process ${pid}`);
|
|
16
22
|
}
|
|
17
23
|
if (options.ownsProcessGroup === true) {
|
|
18
24
|
signalUnixGroup(pid, 'SIGTERM');
|
|
19
25
|
if (await waitForUnixGroupExit(pid, graceMs))
|
|
20
26
|
return;
|
|
21
27
|
signalUnixGroup(pid, 'SIGKILL');
|
|
22
|
-
await waitForUnixGroupExit(pid, FORCE_KILL_WAIT_MS)
|
|
23
|
-
|
|
28
|
+
if (await waitForUnixGroupExit(pid, FORCE_KILL_WAIT_MS))
|
|
29
|
+
return;
|
|
30
|
+
throw new Error(`Failed to terminate process group ${pid}`);
|
|
24
31
|
}
|
|
25
32
|
signalUnix(child, 'SIGTERM');
|
|
26
33
|
if (await waitForExit(child, graceMs))
|
|
27
34
|
return;
|
|
28
35
|
signalUnix(child, 'SIGKILL');
|
|
29
|
-
await waitForExit(child, FORCE_KILL_WAIT_MS)
|
|
36
|
+
if (await waitForExit(child, FORCE_KILL_WAIT_MS))
|
|
37
|
+
return;
|
|
38
|
+
throw new Error(`Failed to terminate process ${pid}`);
|
|
30
39
|
}
|
|
31
40
|
function signalUnix(child, signal) {
|
|
32
41
|
try {
|
package/dist/run-store.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { ArtifactStore, type ArtifactReadResult, type ArtifactStoreMetrics, type ArtifactStoreOptions, type StoredArtifactView } from './artifact-store.js';
|
|
2
|
+
import type { AgentdArtifact, AgentdProtocol, AgentdRunDetail, AgentdRunView, AgentdSessionState } from './types.js';
|
|
3
|
+
export { ArtifactStore, artifactStorePathForRunStore } from './artifact-store.js';
|
|
4
|
+
export type { ArtifactReadResult, ArtifactStorageStatus, ArtifactStoreMetrics, ArtifactStoreIo, ArtifactStoreOptions, StoredArtifactView } from './artifact-store.js';
|
|
5
|
+
interface StoredRun extends Omit<AgentdRunDetail, 'taskPreview'> {
|
|
3
6
|
ownerKeyId: string;
|
|
4
7
|
}
|
|
5
8
|
export interface CreateRunInput {
|
|
@@ -12,6 +15,17 @@ export interface CreateRunInput {
|
|
|
12
15
|
ownerKeyId: string;
|
|
13
16
|
task: string;
|
|
14
17
|
inputAttachmentCount?: number;
|
|
18
|
+
retryOfRunId?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RunStoreOptions extends ArtifactStoreOptions {
|
|
21
|
+
/** History count cap; the positional maxRuns argument takes precedence. */
|
|
22
|
+
maxRuns?: number;
|
|
23
|
+
/** Task text cap; the positional maxTaskChars argument takes precedence. */
|
|
24
|
+
maxTaskChars?: number;
|
|
25
|
+
/** Terminal run metadata retention duration. Active runs are protected. */
|
|
26
|
+
historyRetentionDays?: number;
|
|
27
|
+
/** JSON run-history byte budget, independent from artifact payload bytes. */
|
|
28
|
+
historyMaxBytes?: number;
|
|
15
29
|
}
|
|
16
30
|
export interface RunListQuery {
|
|
17
31
|
agentId?: string;
|
|
@@ -19,20 +33,51 @@ export interface RunListQuery {
|
|
|
19
33
|
state?: AgentdSessionState;
|
|
20
34
|
query?: string;
|
|
21
35
|
limit?: number;
|
|
36
|
+
offset?: number;
|
|
22
37
|
}
|
|
23
38
|
export declare class RunStore {
|
|
24
39
|
readonly filePath: string;
|
|
25
|
-
private readonly maxRuns;
|
|
26
|
-
private readonly maxTaskChars;
|
|
27
40
|
private readonly runs;
|
|
28
41
|
private initialized;
|
|
29
42
|
private dirty;
|
|
30
43
|
private persistTimer?;
|
|
31
44
|
private writeQueue;
|
|
32
|
-
|
|
45
|
+
readonly artifactStore: ArtifactStore;
|
|
46
|
+
private readonly maxRuns;
|
|
47
|
+
private readonly maxTaskChars;
|
|
48
|
+
private readonly historyRetentionDays?;
|
|
49
|
+
private readonly historyMaxBytes?;
|
|
50
|
+
private readonly now;
|
|
51
|
+
private lastWriteMs;
|
|
52
|
+
private writeFailures;
|
|
53
|
+
private historyBytes;
|
|
54
|
+
constructor(filePath: string, maxRuns?: number, maxTaskChars?: number | RunStoreOptions, options?: RunStoreOptions);
|
|
55
|
+
constructor(filePath: string, options?: RunStoreOptions);
|
|
33
56
|
init(): Promise<void>;
|
|
34
57
|
create(input: CreateRunInput): AgentdRunDetail;
|
|
35
|
-
update(id: string, patch: Partial<Pick<StoredRun, 'protocolSessionId' | 'state' | 'progress' | 'output' | 'error' | 'artifacts' | 'artifactCount' | 'updatedAt' | 'endedAt' | 'durationMs' | 'inputAttachmentCount' | 'completion'>>): AgentdRunDetail | undefined;
|
|
58
|
+
update(id: string, patch: Partial<Pick<StoredRun, 'protocolSessionId' | 'state' | 'progress' | 'output' | 'error' | 'artifacts' | 'artifactCount' | 'updatedAt' | 'endedAt' | 'durationMs' | 'inputAttachmentCount' | 'completion' | 'retryOfRunId'>>): AgentdRunDetail | undefined;
|
|
59
|
+
/** Queue payload snapshots without blocking the protocol sink. */
|
|
60
|
+
recordArtifacts(runId: string, artifacts: AgentdArtifact[]): StoredArtifactView[] | undefined;
|
|
61
|
+
artifactViews(runId: string): StoredArtifactView[] | undefined;
|
|
62
|
+
readArtifact(runId: string, artifactId: string): Promise<ArtifactReadResult | undefined>;
|
|
63
|
+
getOwnerKeyId(runId: string): string | undefined;
|
|
64
|
+
metrics(): {
|
|
65
|
+
historyBytes: number;
|
|
66
|
+
retainedRuns: number;
|
|
67
|
+
pendingWrites: number;
|
|
68
|
+
lastWriteMs: number;
|
|
69
|
+
writeFailures: number;
|
|
70
|
+
artifactStoreStats: ArtifactStoreMetrics;
|
|
71
|
+
};
|
|
72
|
+
stats(): {
|
|
73
|
+
historyBytes: number;
|
|
74
|
+
retainedRuns: number;
|
|
75
|
+
pendingWrites: number;
|
|
76
|
+
lastWriteMs: number;
|
|
77
|
+
writeFailures: number;
|
|
78
|
+
artifactStoreStats: ArtifactStoreMetrics;
|
|
79
|
+
};
|
|
80
|
+
setRetryOfRunId(runId: string, retryOfRunId?: string): AgentdRunDetail | undefined;
|
|
36
81
|
get(id: string): AgentdRunDetail | undefined;
|
|
37
82
|
list(query?: RunListQuery): {
|
|
38
83
|
runs: AgentdRunView[];
|
|
@@ -49,6 +94,6 @@ export declare class RunStore {
|
|
|
49
94
|
private prune;
|
|
50
95
|
private persist;
|
|
51
96
|
private assertInitialized;
|
|
97
|
+
private applyArtifactViews;
|
|
52
98
|
}
|
|
53
99
|
export declare function runStorePathForConfig(configPath: string): string;
|
|
54
|
-
export {};
|