agentfootprint 7.13.0 → 7.14.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/dist/core/Agent.js +79 -2
- package/dist/core/Agent.js.map +1 -1
- package/dist/esm/core/Agent.d.ts +47 -0
- package/dist/esm/core/Agent.js +79 -2
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/hosting/envelope.d.ts +33 -0
- package/dist/esm/hosting/envelope.js +49 -0
- package/dist/esm/hosting/envelope.js.map +1 -0
- package/dist/esm/hosting/errors.d.ts +78 -0
- package/dist/esm/hosting/errors.js +119 -0
- package/dist/esm/hosting/errors.js.map +1 -0
- package/dist/esm/hosting/index.d.ts +53 -0
- package/dist/esm/hosting/index.js +52 -0
- package/dist/esm/hosting/index.js.map +1 -0
- package/dist/esm/hosting/memorySessions.d.ts +22 -0
- package/dist/esm/hosting/memorySessions.js +31 -0
- package/dist/esm/hosting/memorySessions.js.map +1 -0
- package/dist/esm/hosting/nodeHost.d.ts +64 -0
- package/dist/esm/hosting/nodeHost.js +245 -0
- package/dist/esm/hosting/nodeHost.js.map +1 -0
- package/dist/esm/hosting/standingAgent.d.ts +62 -0
- package/dist/esm/hosting/standingAgent.js +192 -0
- package/dist/esm/hosting/standingAgent.js.map +1 -0
- package/dist/esm/hosting/types.d.ts +206 -0
- package/dist/esm/hosting/types.js +21 -0
- package/dist/esm/hosting/types.js.map +1 -0
- package/dist/hosting/envelope.js +54 -0
- package/dist/hosting/envelope.js.map +1 -0
- package/dist/hosting/errors.js +126 -0
- package/dist/hosting/errors.js.map +1 -0
- package/dist/hosting/index.js +64 -0
- package/dist/hosting/index.js.map +1 -0
- package/dist/hosting/memorySessions.js +35 -0
- package/dist/hosting/memorySessions.js.map +1 -0
- package/dist/hosting/nodeHost.js +272 -0
- package/dist/hosting/nodeHost.js.map +1 -0
- package/dist/hosting/standingAgent.js +196 -0
- package/dist/hosting/standingAgent.js.map +1 -0
- package/dist/hosting/types.js +22 -0
- package/dist/hosting/types.js.map +1 -0
- package/dist/types/core/Agent.d.ts +47 -0
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/hosting/envelope.d.ts +34 -0
- package/dist/types/hosting/envelope.d.ts.map +1 -0
- package/dist/types/hosting/errors.d.ts +79 -0
- package/dist/types/hosting/errors.d.ts.map +1 -0
- package/dist/types/hosting/index.d.ts +54 -0
- package/dist/types/hosting/index.d.ts.map +1 -0
- package/dist/types/hosting/memorySessions.d.ts +23 -0
- package/dist/types/hosting/memorySessions.d.ts.map +1 -0
- package/dist/types/hosting/nodeHost.d.ts +65 -0
- package/dist/types/hosting/nodeHost.d.ts.map +1 -0
- package/dist/types/hosting/standingAgent.d.ts +63 -0
- package/dist/types/hosting/standingAgent.d.ts.map +1 -0
- package/dist/types/hosting/types.d.ts +207 -0
- package/dist/types/hosting/types.d.ts.map +1 -0
- package/package.json +14 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hosting/nodeHost — the plain HTTP adapter, built on `node:http` and nothing
|
|
3
|
+
* else.
|
|
4
|
+
*
|
|
5
|
+
* const host = nodeHost({ port: 8080 });
|
|
6
|
+
* const handle = await host.serve(async (request, reply) => {
|
|
7
|
+
* reply.complete(await answer(request.input));
|
|
8
|
+
* });
|
|
9
|
+
*
|
|
10
|
+
* Two routes: `POST /invoke` takes `{ input, sessionId? }` and answers
|
|
11
|
+
* `{ output }`; `GET /health` answers `{ status: 'ok' }`. Both paths are
|
|
12
|
+
* options, because the paths are the part most likely to be dictated to you by
|
|
13
|
+
* whatever is in front of the process — a load balancer, a container contract,
|
|
14
|
+
* a colleague's convention. A path is a deployment detail, so it is a knob
|
|
15
|
+
* here and absent from the port entirely.
|
|
16
|
+
*
|
|
17
|
+
* **Streaming is the caller's choice, not the server's.** Send
|
|
18
|
+
* `Accept: text/event-stream` and the reply is Server-Sent Events, one `chunk`
|
|
19
|
+
* event per `reply.emit(...)` then a final `complete`. Send anything else and
|
|
20
|
+
* the same handler produces one JSON body — it emits into a buffer that the
|
|
21
|
+
* completion settles. The handler cannot tell the difference and does not need
|
|
22
|
+
* to, which is the property `capabilities` exists to describe.
|
|
23
|
+
*
|
|
24
|
+
* Pattern: Adapter. Everything specific to HTTP — the paths, the JSON body
|
|
25
|
+
* shape, the status codes, the SSE framing — lives in this file. `types.ts`
|
|
26
|
+
* knows none of it, and a future adapter for somewhere else re-decides all of
|
|
27
|
+
* it without touching a port.
|
|
28
|
+
*/
|
|
29
|
+
import { encodeSSE } from '../stream.js';
|
|
30
|
+
import { HostClosedError } from './errors.js';
|
|
31
|
+
const HOST_NAME = 'nodeHost';
|
|
32
|
+
const CAPABILITIES = ['streaming'];
|
|
33
|
+
/**
|
|
34
|
+
* Status codes this adapter maps by error code. Anything else is a 500.
|
|
35
|
+
*
|
|
36
|
+
* All three are deliberately NOT 5xx: none of them is the agent breaking. A
|
|
37
|
+
* closed host is shutting down (503), a concurrent turn conflicts with the run
|
|
38
|
+
* already going (409), and a paused run conflicts with the state this reply can
|
|
39
|
+
* carry (409) — the run is unfinished, not failed, and a 500 would say
|
|
40
|
+
* otherwise to every dashboard that ever sees it.
|
|
41
|
+
*/
|
|
42
|
+
const STATUS_BY_CODE = {
|
|
43
|
+
ERR_HOST_CLOSED: 503,
|
|
44
|
+
ERR_CONCURRENT_RUN: 409,
|
|
45
|
+
ERR_PAUSE_NOT_CARRIED: 409,
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* An HTTP host for one handler.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const handle = await nodeHost({ port: 0 }).serve(handler);
|
|
52
|
+
* await fetch(`${handle.url}/invoke`, {
|
|
53
|
+
* method: 'POST',
|
|
54
|
+
* headers: { 'content-type': 'application/json' },
|
|
55
|
+
* body: JSON.stringify({ input: 'hello', sessionId: 'c-1' }),
|
|
56
|
+
* });
|
|
57
|
+
* await handle.close();
|
|
58
|
+
*/
|
|
59
|
+
export function nodeHost(options = {}) {
|
|
60
|
+
const port = options.port ?? 8080;
|
|
61
|
+
const hostname = options.hostname ?? '0.0.0.0';
|
|
62
|
+
const invokePath = options.invokePath ?? '/invoke';
|
|
63
|
+
const healthPath = options.healthPath ?? '/health';
|
|
64
|
+
return {
|
|
65
|
+
name: HOST_NAME,
|
|
66
|
+
capabilities: CAPABILITIES,
|
|
67
|
+
async serve(handler) {
|
|
68
|
+
const { createServer } = await import('node:http');
|
|
69
|
+
const startedAt = Date.now();
|
|
70
|
+
const inFlight = new Set();
|
|
71
|
+
let accepting = true;
|
|
72
|
+
let closing;
|
|
73
|
+
const server = createServer((req, res) => {
|
|
74
|
+
const path = (req.url ?? '').split('?')[0];
|
|
75
|
+
if (req.method === 'GET' && path === healthPath) {
|
|
76
|
+
sendJson(res, 200, { status: 'ok', uptimeMs: Date.now() - startedAt });
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (req.method !== 'POST' || path !== invokePath) {
|
|
80
|
+
sendJson(res, 404, { error: `no route for ${req.method ?? '?'} ${path}` });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!accepting) {
|
|
84
|
+
const refusal = new HostClosedError(HOST_NAME);
|
|
85
|
+
sendJson(res, STATUS_BY_CODE[refusal.code] ?? 500, {
|
|
86
|
+
error: refusal.message,
|
|
87
|
+
code: refusal.code,
|
|
88
|
+
});
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const served = serveOne(req, res, handler);
|
|
92
|
+
inFlight.add(served);
|
|
93
|
+
void served.finally(() => inFlight.delete(served));
|
|
94
|
+
});
|
|
95
|
+
await new Promise((resolve, reject) => {
|
|
96
|
+
server.once('error', reject);
|
|
97
|
+
server.listen(port, hostname, resolve);
|
|
98
|
+
});
|
|
99
|
+
const address = server.address();
|
|
100
|
+
const boundPort = typeof address === 'object' && address ? address.port : port;
|
|
101
|
+
const displayHost = hostname === '0.0.0.0' || hostname === '::' ? '127.0.0.1' : hostname;
|
|
102
|
+
return {
|
|
103
|
+
url: `http://${displayHost}:${boundPort}`,
|
|
104
|
+
port: boundPort,
|
|
105
|
+
close() {
|
|
106
|
+
// Idempotent: the first call owns the shutdown, later ones await it.
|
|
107
|
+
closing ??= (async () => {
|
|
108
|
+
accepting = false;
|
|
109
|
+
// Drain BEFORE touching sockets — an in-flight request is work the
|
|
110
|
+
// caller is still waiting on, and dropping it would be the exact
|
|
111
|
+
// thing close() promises not to do.
|
|
112
|
+
await Promise.allSettled([...inFlight]);
|
|
113
|
+
server.closeIdleConnections();
|
|
114
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
115
|
+
})();
|
|
116
|
+
return closing;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** Run one request through the handler and write whatever it decides. */
|
|
123
|
+
async function serveOne(req, res, handler) {
|
|
124
|
+
const wantsStream = (req.headers.accept ?? '').includes('text/event-stream');
|
|
125
|
+
const controller = new AbortController();
|
|
126
|
+
let body;
|
|
127
|
+
try {
|
|
128
|
+
body = await readJson(req);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
sendJson(res, 400, { error: `invalid JSON body: ${asError(err).message}` });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const input = typeof body.input === 'string' ? body.input : '';
|
|
135
|
+
// sessionId is caller data whichever way it arrives; the body wins so a
|
|
136
|
+
// caller that sets both is not surprised by which one the server preferred.
|
|
137
|
+
const sessionId = typeof body.sessionId === 'string'
|
|
138
|
+
? body.sessionId
|
|
139
|
+
: typeof req.headers['x-session-id'] === 'string'
|
|
140
|
+
? req.headers['x-session-id']
|
|
141
|
+
: undefined;
|
|
142
|
+
if (wantsStream) {
|
|
143
|
+
res.writeHead(200, {
|
|
144
|
+
'content-type': 'text/event-stream',
|
|
145
|
+
'cache-control': 'no-cache',
|
|
146
|
+
connection: 'keep-alive',
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
let settled = false;
|
|
150
|
+
// The caller hung up before we answered — tell the handler so it can stop
|
|
151
|
+
// paying for work nobody is waiting for.
|
|
152
|
+
res.once('close', () => {
|
|
153
|
+
if (!settled)
|
|
154
|
+
controller.abort();
|
|
155
|
+
});
|
|
156
|
+
const reply = {
|
|
157
|
+
emit(chunk) {
|
|
158
|
+
// Not streaming? The chunk is a preview of text `complete` will deliver
|
|
159
|
+
// in full, so there is nothing to send and nothing to keep.
|
|
160
|
+
if (settled || !wantsStream)
|
|
161
|
+
return;
|
|
162
|
+
res.write(encodeSSE('chunk', { text: chunk }));
|
|
163
|
+
},
|
|
164
|
+
complete(output) {
|
|
165
|
+
if (settled)
|
|
166
|
+
return;
|
|
167
|
+
settled = true;
|
|
168
|
+
if (wantsStream) {
|
|
169
|
+
res.write(encodeSSE('complete', { output }));
|
|
170
|
+
res.end();
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
sendJson(res, 200, { output });
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
fail(error) {
|
|
177
|
+
if (settled)
|
|
178
|
+
return;
|
|
179
|
+
settled = true;
|
|
180
|
+
const code = error.code;
|
|
181
|
+
const payload = { error: error.message, ...(code !== undefined && { code }) };
|
|
182
|
+
if (wantsStream) {
|
|
183
|
+
res.write(encodeSSE('error', payload));
|
|
184
|
+
res.end();
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
sendJson(res, code !== undefined ? STATUS_BY_CODE[code] ?? 500 : 500, payload);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
try {
|
|
192
|
+
await handler({
|
|
193
|
+
input,
|
|
194
|
+
...(sessionId !== undefined && { sessionId }),
|
|
195
|
+
headers: lowerCased(req.headers),
|
|
196
|
+
signal: controller.signal,
|
|
197
|
+
}, reply);
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
// A handler that throws is a failed request, never a hung one.
|
|
201
|
+
reply.fail(asError(err));
|
|
202
|
+
}
|
|
203
|
+
// A handler that returned without answering gets one authored answer rather
|
|
204
|
+
// than a socket the caller waits on until it times out.
|
|
205
|
+
if (!settled) {
|
|
206
|
+
reply.fail(new Error('[hosting] the handler returned without calling complete() or fail().'));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function readJson(req) {
|
|
210
|
+
return new Promise((resolve, reject) => {
|
|
211
|
+
const chunks = [];
|
|
212
|
+
req.on('data', (c) => chunks.push(c));
|
|
213
|
+
req.on('error', reject);
|
|
214
|
+
req.on('end', () => {
|
|
215
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
216
|
+
if (!raw)
|
|
217
|
+
return resolve({});
|
|
218
|
+
try {
|
|
219
|
+
const parsed = JSON.parse(raw);
|
|
220
|
+
resolve(parsed && typeof parsed === 'object' ? parsed : {});
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
reject(err);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function sendJson(res, status, body) {
|
|
229
|
+
res.writeHead(status, { 'content-type': 'application/json' });
|
|
230
|
+
res.end(JSON.stringify(body));
|
|
231
|
+
}
|
|
232
|
+
function lowerCased(headers) {
|
|
233
|
+
const out = {};
|
|
234
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
235
|
+
if (typeof value === 'string')
|
|
236
|
+
out[name.toLowerCase()] = value;
|
|
237
|
+
else if (Array.isArray(value))
|
|
238
|
+
out[name.toLowerCase()] = value.join(', ');
|
|
239
|
+
}
|
|
240
|
+
return out;
|
|
241
|
+
}
|
|
242
|
+
function asError(err) {
|
|
243
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=nodeHost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodeHost.js","sourceRoot":"","sources":["../../../src/hosting/nodeHost.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hosting/standingAgent — an agent that stays up and remembers.
|
|
3
|
+
*
|
|
4
|
+
* await standingAgent({
|
|
5
|
+
* agent,
|
|
6
|
+
* sessions: memorySessions(),
|
|
7
|
+
* host: nodeHost({ port: 8080 }),
|
|
8
|
+
* });
|
|
9
|
+
*
|
|
10
|
+
* One request at a time it does four things: wake and hydrate the session,
|
|
11
|
+
* resume that conversation or start a fresh one, persist what the run leaves
|
|
12
|
+
* behind, then reply. Everything else is somebody else's job — the host carries
|
|
13
|
+
* bytes, the store keeps them, the agent thinks.
|
|
14
|
+
*
|
|
15
|
+
* ── Resuming is a REPLAY, and that has a cost you must know about ────────────
|
|
16
|
+
* A stored conversation is restored through `agent.resumeOnError(...)`, and
|
|
17
|
+
* this is its caveat, stated here in the words the Agent states it in, because
|
|
18
|
+
* a composition that hides the caveat of the thing it composes is worse than no
|
|
19
|
+
* composition at all:
|
|
20
|
+
*
|
|
21
|
+
* > **Tool re-execution / idempotency**: tool side effects from the FAILED
|
|
22
|
+
* > iteration are not in the checkpoint. The model re-decides from the
|
|
23
|
+
* > restored history and may re-issue those tool calls — they WILL execute
|
|
24
|
+
* > again (there is no built-in toolCallId dedup). Mutating tools (payments,
|
|
25
|
+
* > emails, DB writes) must be idempotent — key on stable call content, not
|
|
26
|
+
* > `ctx.toolCallId` (a re-issued call gets a new id).
|
|
27
|
+
*
|
|
28
|
+
* ── Why one run at a time ───────────────────────────────────────────────────
|
|
29
|
+
* An Agent instance holds per-run state on itself, and this composer shares ONE
|
|
30
|
+
* instance across every session. Two runs overlapping on it do not crash —
|
|
31
|
+
* which is precisely the danger. They both finish, and the state the composer
|
|
32
|
+
* reads afterwards belongs to whichever started last, so one session's envelope
|
|
33
|
+
* can end up holding another session's conversation. Nothing in the recording
|
|
34
|
+
* would say so. Runs are therefore serialized, globally, and that is a
|
|
35
|
+
* correctness requirement rather than a tuning choice.
|
|
36
|
+
*
|
|
37
|
+
* `onConcurrentInvoke` is the separate question of what to do when a second
|
|
38
|
+
* turn of the SAME conversation arrives while the first is running: refuse it
|
|
39
|
+
* (default) or queue it. A request for a DIFFERENT session is never refused —
|
|
40
|
+
* there is nothing wrong with it; it simply waits its turn.
|
|
41
|
+
*
|
|
42
|
+
* Pattern: Composition root. It owns wiring and ordering; it invents no
|
|
43
|
+
* mechanism of its own.
|
|
44
|
+
*/
|
|
45
|
+
import type { HostHandle, StandingAgentOptions } from './types.js';
|
|
46
|
+
/**
|
|
47
|
+
* Serve one agent, with per-session conversation memory, on any
|
|
48
|
+
* {@link AgentHost}.
|
|
49
|
+
*
|
|
50
|
+
* Resolves once the host is live. Closing the returned handle closes the host
|
|
51
|
+
* and detaches the listeners this composer added to the agent.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* const handle = await standingAgent({
|
|
55
|
+
* agent,
|
|
56
|
+
* sessions: memorySessions(),
|
|
57
|
+
* host: nodeHost({ port: 0 }),
|
|
58
|
+
* onConcurrentInvoke: 'enqueue',
|
|
59
|
+
* });
|
|
60
|
+
* process.on('SIGTERM', () => void handle.close());
|
|
61
|
+
*/
|
|
62
|
+
export declare function standingAgent<TH extends HostHandle>(options: StandingAgentOptions<TH>): Promise<TH>;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hosting/standingAgent — an agent that stays up and remembers.
|
|
3
|
+
*
|
|
4
|
+
* await standingAgent({
|
|
5
|
+
* agent,
|
|
6
|
+
* sessions: memorySessions(),
|
|
7
|
+
* host: nodeHost({ port: 8080 }),
|
|
8
|
+
* });
|
|
9
|
+
*
|
|
10
|
+
* One request at a time it does four things: wake and hydrate the session,
|
|
11
|
+
* resume that conversation or start a fresh one, persist what the run leaves
|
|
12
|
+
* behind, then reply. Everything else is somebody else's job — the host carries
|
|
13
|
+
* bytes, the store keeps them, the agent thinks.
|
|
14
|
+
*
|
|
15
|
+
* ── Resuming is a REPLAY, and that has a cost you must know about ────────────
|
|
16
|
+
* A stored conversation is restored through `agent.resumeOnError(...)`, and
|
|
17
|
+
* this is its caveat, stated here in the words the Agent states it in, because
|
|
18
|
+
* a composition that hides the caveat of the thing it composes is worse than no
|
|
19
|
+
* composition at all:
|
|
20
|
+
*
|
|
21
|
+
* > **Tool re-execution / idempotency**: tool side effects from the FAILED
|
|
22
|
+
* > iteration are not in the checkpoint. The model re-decides from the
|
|
23
|
+
* > restored history and may re-issue those tool calls — they WILL execute
|
|
24
|
+
* > again (there is no built-in toolCallId dedup). Mutating tools (payments,
|
|
25
|
+
* > emails, DB writes) must be idempotent — key on stable call content, not
|
|
26
|
+
* > `ctx.toolCallId` (a re-issued call gets a new id).
|
|
27
|
+
*
|
|
28
|
+
* ── Why one run at a time ───────────────────────────────────────────────────
|
|
29
|
+
* An Agent instance holds per-run state on itself, and this composer shares ONE
|
|
30
|
+
* instance across every session. Two runs overlapping on it do not crash —
|
|
31
|
+
* which is precisely the danger. They both finish, and the state the composer
|
|
32
|
+
* reads afterwards belongs to whichever started last, so one session's envelope
|
|
33
|
+
* can end up holding another session's conversation. Nothing in the recording
|
|
34
|
+
* would say so. Runs are therefore serialized, globally, and that is a
|
|
35
|
+
* correctness requirement rather than a tuning choice.
|
|
36
|
+
*
|
|
37
|
+
* `onConcurrentInvoke` is the separate question of what to do when a second
|
|
38
|
+
* turn of the SAME conversation arrives while the first is running: refuse it
|
|
39
|
+
* (default) or queue it. A request for a DIFFERENT session is never refused —
|
|
40
|
+
* there is nothing wrong with it; it simply waits its turn.
|
|
41
|
+
*
|
|
42
|
+
* Pattern: Composition root. It owns wiring and ordering; it invents no
|
|
43
|
+
* mechanism of its own.
|
|
44
|
+
*/
|
|
45
|
+
import { isPaused } from '../core/pause.js';
|
|
46
|
+
import { toEnvelope, readEnvelope } from './envelope.js';
|
|
47
|
+
import { ConcurrentRunError, PauseNotCarriedError } from './errors.js';
|
|
48
|
+
/**
|
|
49
|
+
* Serve one agent, with per-session conversation memory, on any
|
|
50
|
+
* {@link AgentHost}.
|
|
51
|
+
*
|
|
52
|
+
* Resolves once the host is live. Closing the returned handle closes the host
|
|
53
|
+
* and detaches the listeners this composer added to the agent.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* const handle = await standingAgent({
|
|
57
|
+
* agent,
|
|
58
|
+
* sessions: memorySessions(),
|
|
59
|
+
* host: nodeHost({ port: 0 }),
|
|
60
|
+
* onConcurrentInvoke: 'enqueue',
|
|
61
|
+
* });
|
|
62
|
+
* process.on('SIGTERM', () => void handle.close());
|
|
63
|
+
*/
|
|
64
|
+
export async function standingAgent(options) {
|
|
65
|
+
const { agent, sessions, host } = options;
|
|
66
|
+
const policy = options.onConcurrentInvoke ?? 'reject';
|
|
67
|
+
// Runs are serialized, so at any moment there is at most one active reply and
|
|
68
|
+
// at most one active run to name in a refusal.
|
|
69
|
+
let activeReply;
|
|
70
|
+
let activeRunId;
|
|
71
|
+
let activeSession;
|
|
72
|
+
const queued = [];
|
|
73
|
+
let chain = Promise.resolve();
|
|
74
|
+
let anonymous = 0;
|
|
75
|
+
const offTurnStart = agent.on('agentfootprint.agent.turn_start', (event) => {
|
|
76
|
+
activeRunId = event.meta?.runId;
|
|
77
|
+
});
|
|
78
|
+
// Tokens reach the caller only if the host streams; `emit` on a host that
|
|
79
|
+
// does not is a no-op by design, so this needs no capability check.
|
|
80
|
+
const offToken = agent.on('agentfootprint.stream.token', (event) => {
|
|
81
|
+
const content = event.payload?.content;
|
|
82
|
+
if (typeof content === 'string' && content.length > 0)
|
|
83
|
+
activeReply?.emit?.(content);
|
|
84
|
+
});
|
|
85
|
+
/** Queue `work` behind everything already waiting, FIFO. */
|
|
86
|
+
function serialize(sessionKey, work) {
|
|
87
|
+
if (policy === 'reject' && (activeSession === sessionKey || queued.includes(sessionKey))) {
|
|
88
|
+
return Promise.reject(new ConcurrentRunError(sessionKey, activeRunId));
|
|
89
|
+
}
|
|
90
|
+
queued.push(sessionKey);
|
|
91
|
+
const mine = chain.then(async () => {
|
|
92
|
+
queued.splice(queued.indexOf(sessionKey), 1);
|
|
93
|
+
activeSession = sessionKey;
|
|
94
|
+
try {
|
|
95
|
+
await work();
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
activeSession = undefined;
|
|
99
|
+
activeRunId = undefined;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
// The chain must never reject, or one failed request would wedge every
|
|
103
|
+
// request behind it.
|
|
104
|
+
chain = mine.then(() => undefined, () => undefined);
|
|
105
|
+
return mine;
|
|
106
|
+
}
|
|
107
|
+
const handler = async (request, reply) => {
|
|
108
|
+
const sessionId = request.sessionId;
|
|
109
|
+
// A request with no session has nothing to hydrate and nowhere to persist
|
|
110
|
+
// that the caller could ask for again, so it gets its own key and can never
|
|
111
|
+
// collide with anyone.
|
|
112
|
+
const sessionKey = sessionId ?? `#anonymous-${++anonymous}`;
|
|
113
|
+
try {
|
|
114
|
+
await serialize(sessionKey, () => answerOne(agent, sessions, request, reply, sessionId));
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
reply.fail(err instanceof Error ? err : new Error(String(err)));
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
async function answerOne(runner, store, request, reply, sessionId) {
|
|
121
|
+
activeReply = reply;
|
|
122
|
+
try {
|
|
123
|
+
let prior;
|
|
124
|
+
if (sessionId !== undefined) {
|
|
125
|
+
await store.onWake?.(sessionId, 'invoke');
|
|
126
|
+
const stored = await store.hydrate(sessionId);
|
|
127
|
+
// Throws by name on a format this runtime cannot read — better a loud
|
|
128
|
+
// refusal than an agent answering from half a conversation.
|
|
129
|
+
if (stored !== undefined)
|
|
130
|
+
prior = readEnvelope(stored);
|
|
131
|
+
}
|
|
132
|
+
// The signal reaches tool execution, tool discovery and skill-entry
|
|
133
|
+
// scoring. It does NOT currently reach the LLM call, so a caller who
|
|
134
|
+
// hangs up mid-generation stops the tools, not the token stream.
|
|
135
|
+
const runOptions = request.signal ? { env: { signal: request.signal } } : undefined;
|
|
136
|
+
const output = prior
|
|
137
|
+
? await runner.resumeOnError(continueConversation(prior, request.input), runOptions)
|
|
138
|
+
: await runner.run({ message: request.input }, runOptions);
|
|
139
|
+
if (isPaused(output)) {
|
|
140
|
+
reply.fail(new PauseNotCarriedError(pausedToolName(runner), sessionId));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (sessionId !== undefined) {
|
|
144
|
+
const conversation = runner.checkpoint();
|
|
145
|
+
// Persist BEFORE answering: the caller learns the answer only once the
|
|
146
|
+
// conversation that produced it is durable, so a queued next turn can
|
|
147
|
+
// never read state older than the answer already given.
|
|
148
|
+
if (conversation)
|
|
149
|
+
await store.persist(sessionId, toEnvelope(conversation));
|
|
150
|
+
}
|
|
151
|
+
reply.complete(typeof output === 'string' ? output : String(output));
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
activeReply = undefined;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const handle = await host.serve(handler);
|
|
158
|
+
// Keep whatever the adapter put on its own handle (nodeHost's bound `url`,
|
|
159
|
+
// say) and replace only `close`, which now also detaches this composer's
|
|
160
|
+
// listeners. The cast is the one place TypeScript cannot see that a spread
|
|
161
|
+
// plus one override is still the adapter's handle type.
|
|
162
|
+
return {
|
|
163
|
+
...handle,
|
|
164
|
+
async close() {
|
|
165
|
+
await handle.close();
|
|
166
|
+
offTurnStart();
|
|
167
|
+
offToken();
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The stored conversation plus this turn's message.
|
|
173
|
+
*
|
|
174
|
+
* The new message has to be appended by hand: `resumeOnError` restores the
|
|
175
|
+
* history it is given and the LLM stage reads that history directly, so a
|
|
176
|
+
* message left out here is a message the model never sees.
|
|
177
|
+
*/
|
|
178
|
+
function continueConversation(prior, input) {
|
|
179
|
+
return {
|
|
180
|
+
...prior,
|
|
181
|
+
history: [...prior.history, { role: 'user', content: input }],
|
|
182
|
+
originalInput: { message: input },
|
|
183
|
+
checkpointedAt: Date.now(),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/** Which tool asked for a human, when the paused run recorded one. */
|
|
187
|
+
function pausedToolName(runner) {
|
|
188
|
+
const state = runner.getLastSnapshot()?.sharedState;
|
|
189
|
+
const name = state?.pausedToolName;
|
|
190
|
+
return typeof name === 'string' && name.length > 0 ? name : undefined;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=standingAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standingAgent.js","sourceRoot":"","sources":["../../../src/hosting/standingAgent.ts"],"names":[],"mappings":"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"}
|