agentfootprint 7.14.0 → 7.15.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.
Files changed (94) hide show
  1. package/dist/adapters/hosting/agentcore.js +350 -0
  2. package/dist/adapters/hosting/agentcore.js.map +1 -0
  3. package/dist/adapters/memory/agentcore.js +125 -1
  4. package/dist/adapters/memory/agentcore.js.map +1 -1
  5. package/dist/adapters/security/agentcore.js +0 -0
  6. package/dist/adapters/security/agentcore.js.map +1 -0
  7. package/dist/esm/adapters/hosting/agentcore.d.ts +199 -0
  8. package/dist/esm/adapters/hosting/agentcore.js +321 -0
  9. package/dist/esm/adapters/hosting/agentcore.js.map +1 -0
  10. package/dist/esm/adapters/memory/agentcore.d.ts +88 -2
  11. package/dist/esm/adapters/memory/agentcore.js +125 -1
  12. package/dist/esm/adapters/memory/agentcore.js.map +1 -1
  13. package/dist/esm/adapters/security/agentcore.d.ts +157 -0
  14. package/dist/esm/adapters/security/agentcore.js +0 -0
  15. package/dist/esm/adapters/security/agentcore.js.map +1 -0
  16. package/dist/esm/hosting/httpHost.d.ts +121 -0
  17. package/dist/esm/hosting/httpHost.js +248 -0
  18. package/dist/esm/hosting/httpHost.js.map +1 -0
  19. package/dist/esm/hosting/index.d.ts +8 -1
  20. package/dist/esm/hosting/index.js +7 -1
  21. package/dist/esm/hosting/index.js.map +1 -1
  22. package/dist/esm/hosting/nodeHost.d.ts +23 -16
  23. package/dist/esm/hosting/nodeHost.js +32 -199
  24. package/dist/esm/hosting/nodeHost.js.map +1 -1
  25. package/dist/esm/hosting-providers.d.ts +50 -0
  26. package/dist/esm/hosting-providers.js +50 -0
  27. package/dist/esm/hosting-providers.js.map +1 -0
  28. package/dist/esm/lib/mcp/gatewayTransport.d.ts +103 -0
  29. package/dist/esm/lib/mcp/gatewayTransport.js +123 -0
  30. package/dist/esm/lib/mcp/gatewayTransport.js.map +1 -0
  31. package/dist/esm/lib/mcp/index.d.ts +2 -1
  32. package/dist/esm/lib/mcp/index.js +1 -0
  33. package/dist/esm/lib/mcp/index.js.map +1 -1
  34. package/dist/esm/lib/mcp/mcpClient.js +10 -2
  35. package/dist/esm/lib/mcp/mcpClient.js.map +1 -1
  36. package/dist/esm/lib/mcp/types.d.ts +45 -1
  37. package/dist/esm/memory/store/types.d.ts +22 -0
  38. package/dist/esm/memory-providers.d.ts +1 -1
  39. package/dist/esm/memory-providers.js.map +1 -1
  40. package/dist/esm/security/index.d.ts +10 -1
  41. package/dist/esm/security/index.js +14 -1
  42. package/dist/esm/security/index.js.map +1 -1
  43. package/dist/esm/tool-providers/index.d.ts +6 -2
  44. package/dist/esm/tool-providers/index.js +5 -1
  45. package/dist/esm/tool-providers/index.js.map +1 -1
  46. package/dist/hosting/httpHost.js +276 -0
  47. package/dist/hosting/httpHost.js.map +1 -0
  48. package/dist/hosting/index.js +10 -1
  49. package/dist/hosting/index.js.map +1 -1
  50. package/dist/hosting/nodeHost.js +34 -224
  51. package/dist/hosting/nodeHost.js.map +1 -1
  52. package/dist/hosting-providers.js +57 -0
  53. package/dist/hosting-providers.js.map +1 -0
  54. package/dist/lib/mcp/gatewayTransport.js +129 -0
  55. package/dist/lib/mcp/gatewayTransport.js.map +1 -0
  56. package/dist/lib/mcp/index.js +4 -1
  57. package/dist/lib/mcp/index.js.map +1 -1
  58. package/dist/lib/mcp/mcpClient.js +10 -2
  59. package/dist/lib/mcp/mcpClient.js.map +1 -1
  60. package/dist/memory-providers.js.map +1 -1
  61. package/dist/security/index.js +16 -2
  62. package/dist/security/index.js.map +1 -1
  63. package/dist/tool-providers/index.js +7 -1
  64. package/dist/tool-providers/index.js.map +1 -1
  65. package/dist/types/adapters/hosting/agentcore.d.ts +200 -0
  66. package/dist/types/adapters/hosting/agentcore.d.ts.map +1 -0
  67. package/dist/types/adapters/memory/agentcore.d.ts +88 -2
  68. package/dist/types/adapters/memory/agentcore.d.ts.map +1 -1
  69. package/dist/types/adapters/security/agentcore.d.ts +158 -0
  70. package/dist/types/adapters/security/agentcore.d.ts.map +1 -0
  71. package/dist/types/hosting/httpHost.d.ts +122 -0
  72. package/dist/types/hosting/httpHost.d.ts.map +1 -0
  73. package/dist/types/hosting/index.d.ts +8 -1
  74. package/dist/types/hosting/index.d.ts.map +1 -1
  75. package/dist/types/hosting/nodeHost.d.ts +23 -16
  76. package/dist/types/hosting/nodeHost.d.ts.map +1 -1
  77. package/dist/types/hosting-providers.d.ts +51 -0
  78. package/dist/types/hosting-providers.d.ts.map +1 -0
  79. package/dist/types/lib/mcp/gatewayTransport.d.ts +104 -0
  80. package/dist/types/lib/mcp/gatewayTransport.d.ts.map +1 -0
  81. package/dist/types/lib/mcp/index.d.ts +2 -1
  82. package/dist/types/lib/mcp/index.d.ts.map +1 -1
  83. package/dist/types/lib/mcp/mcpClient.d.ts.map +1 -1
  84. package/dist/types/lib/mcp/types.d.ts +45 -1
  85. package/dist/types/lib/mcp/types.d.ts.map +1 -1
  86. package/dist/types/memory/store/types.d.ts +22 -0
  87. package/dist/types/memory/store/types.d.ts.map +1 -1
  88. package/dist/types/memory-providers.d.ts +1 -1
  89. package/dist/types/memory-providers.d.ts.map +1 -1
  90. package/dist/types/security/index.d.ts +10 -1
  91. package/dist/types/security/index.d.ts.map +1 -1
  92. package/dist/types/tool-providers/index.d.ts +6 -2
  93. package/dist/types/tool-providers/index.d.ts.map +1 -1
  94. package/package.json +14 -1
@@ -0,0 +1,248 @@
1
+ /**
2
+ * hosting/httpHost — one HTTP host, parameterised by the JSON dialect it speaks.
3
+ *
4
+ * Everything hard about serving an agent over HTTP happens once, here: draining
5
+ * on close, aborting when the caller hangs up, failing a handler that throws,
6
+ * failing a handler that answers nothing, mapping refusal codes onto status
7
+ * codes, and choosing between one JSON body and Server-Sent Events based on
8
+ * what the caller asked for.
9
+ *
10
+ * Everything a deployment target gets to re-decide is an {@link HttpWire}: the
11
+ * two paths, and the five JSON shapes — how a request names its input and its
12
+ * session, and what a health probe, a completion, a failure and a streamed
13
+ * piece look like on the wire.
14
+ *
15
+ * ── Why this file exists ─────────────────────────────────────────────────────
16
+ * `nodeHost` shipped first and hard-coded its own dialect: `{ input }` in,
17
+ * `{ output }` out, `{ status: 'ok' }` on the health path. That was fine while
18
+ * it was the only HTTP adapter and wrong the moment there was a second one. A
19
+ * container runtime dictates its own body shape as surely as it dictates its
20
+ * paths, and an adapter for it should be a CONFIGURATION of the HTTP work, not
21
+ * a second copy of it — a copy is where the drain semantics of two adapters
22
+ * silently diverge.
23
+ *
24
+ * Note what did NOT have to change for that: the ports. `AgentHost`,
25
+ * `HostRequest` and `HostReply` say exactly what they said before. The gap was
26
+ * in the first adapter, which had no seam, not in the port, which needed none.
27
+ *
28
+ * Pattern: Template method via configuration (Strategy on the wire format).
29
+ * Everything HTTP lives here and in the wires; `types.ts` knows none of it.
30
+ */
31
+ import { encodeSSE } from '../stream.js';
32
+ import { HostClosedError } from './errors.js';
33
+ /**
34
+ * Status codes mapped by refusal code. Anything else is a 500.
35
+ *
36
+ * None of the three is a 5xx: none of them is the agent breaking. A closed host
37
+ * is shutting down (503), a concurrent turn conflicts with the run already
38
+ * going (409), and a paused run conflicts with the state this reply can carry
39
+ * (409) — the run is unfinished, not failed, and a 500 would say otherwise to
40
+ * 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
+ const DEFAULT_CAPABILITIES = ['streaming'];
48
+ /**
49
+ * An HTTP host for one handler, speaking the dialect you hand it.
50
+ *
51
+ * @example The same machinery, two dialects
52
+ * httpHost({ name: 'nodeHost', wire: jsonWire, invokePath: '/invoke', healthPath: '/health' });
53
+ * httpHost({ name: 'myRuntime', wire: myWire, invokePath: '/v1/run', healthPath: '/up' });
54
+ */
55
+ export function httpHost(options) {
56
+ const { name, wire, invokePath, healthPath } = options;
57
+ const port = options.port ?? 8080;
58
+ const hostname = options.hostname ?? '0.0.0.0';
59
+ const capabilities = options.capabilities ?? DEFAULT_CAPABILITIES;
60
+ return {
61
+ name,
62
+ capabilities,
63
+ async serve(handler) {
64
+ const { createServer } = await import('node:http');
65
+ const startedAt = Date.now();
66
+ const inFlight = new Set();
67
+ let accepting = true;
68
+ let closing;
69
+ const server = createServer((req, res) => {
70
+ const path = (req.url ?? '').split('?')[0];
71
+ if (req.method === 'GET' && path === healthPath) {
72
+ sendJson(res, 200, wire.health(Date.now() - startedAt));
73
+ return;
74
+ }
75
+ if (req.method !== 'POST' || path !== invokePath) {
76
+ sendJson(res, 404, wire.failure(`no route for ${req.method ?? '?'} ${path}`));
77
+ return;
78
+ }
79
+ if (!accepting) {
80
+ const refusal = new HostClosedError(name);
81
+ sendJson(res, STATUS_BY_CODE[refusal.code] ?? 500, wire.failure(refusal.message, refusal.code));
82
+ return;
83
+ }
84
+ const served = serveOne(req, res, handler, wire);
85
+ inFlight.add(served);
86
+ void served.finally(() => inFlight.delete(served));
87
+ });
88
+ await new Promise((resolve, reject) => {
89
+ server.once('error', reject);
90
+ server.listen(port, hostname, resolve);
91
+ });
92
+ const address = server.address();
93
+ const boundPort = typeof address === 'object' && address ? address.port : port;
94
+ const displayHost = hostname === '0.0.0.0' || hostname === '::' ? '127.0.0.1' : hostname;
95
+ return {
96
+ url: `http://${displayHost}:${boundPort}`,
97
+ port: boundPort,
98
+ close() {
99
+ // Idempotent: the first call owns the shutdown, later ones await it.
100
+ closing ??= (async () => {
101
+ accepting = false;
102
+ // Drain BEFORE touching sockets — an in-flight request is work the
103
+ // caller is still waiting on, and dropping it would be the exact
104
+ // thing close() promises not to do.
105
+ await Promise.allSettled([...inFlight]);
106
+ server.closeIdleConnections();
107
+ await new Promise((resolve) => server.close(() => resolve()));
108
+ })();
109
+ return closing;
110
+ },
111
+ };
112
+ },
113
+ };
114
+ }
115
+ /** Run one request through the handler and write whatever it decides. */
116
+ async function serveOne(req, res, handler, wire) {
117
+ const wantsStream = (req.headers.accept ?? '').includes('text/event-stream');
118
+ const controller = new AbortController();
119
+ let body;
120
+ try {
121
+ body = await readJson(req);
122
+ }
123
+ catch (err) {
124
+ sendJson(res, 400, wire.failure(`invalid JSON body: ${asError(err).message}`));
125
+ return;
126
+ }
127
+ const headers = lowerCased(req.headers);
128
+ const query = new URLSearchParams((req.url ?? '').split('?')[1] ?? '');
129
+ const { input, sessionId } = wire.readRequest({ body, headers, query });
130
+ if (wantsStream) {
131
+ res.writeHead(200, {
132
+ 'content-type': 'text/event-stream',
133
+ 'cache-control': 'no-cache',
134
+ connection: 'keep-alive',
135
+ });
136
+ }
137
+ let settled = false;
138
+ // The caller hung up before we answered — tell the handler so it can stop
139
+ // paying for work nobody is waiting for.
140
+ res.once('close', () => {
141
+ if (!settled)
142
+ controller.abort();
143
+ });
144
+ const reply = {
145
+ emit(chunk) {
146
+ // Not streaming? The chunk is a preview of text `complete` will deliver
147
+ // in full, so there is nothing to send and nothing to keep.
148
+ if (settled || !wantsStream)
149
+ return;
150
+ res.write(encodeSSE('chunk', wire.chunk(chunk)));
151
+ },
152
+ complete(output) {
153
+ if (settled)
154
+ return;
155
+ settled = true;
156
+ if (wantsStream) {
157
+ res.write(encodeSSE('complete', wire.output(output)));
158
+ res.end();
159
+ }
160
+ else {
161
+ sendJson(res, 200, wire.output(output));
162
+ }
163
+ },
164
+ fail(error) {
165
+ if (settled)
166
+ return;
167
+ settled = true;
168
+ const code = error.code;
169
+ const payload = wire.failure(error.message, code);
170
+ if (wantsStream) {
171
+ res.write(encodeSSE('error', payload));
172
+ res.end();
173
+ }
174
+ else {
175
+ sendJson(res, code !== undefined ? STATUS_BY_CODE[code] ?? 500 : 500, payload);
176
+ }
177
+ },
178
+ };
179
+ try {
180
+ await handler({
181
+ input,
182
+ ...(sessionId !== undefined && { sessionId }),
183
+ headers,
184
+ signal: controller.signal,
185
+ }, reply);
186
+ }
187
+ catch (err) {
188
+ // A handler that throws is a failed request, never a hung one.
189
+ reply.fail(asError(err));
190
+ }
191
+ // A handler that returned without answering gets one authored answer rather
192
+ // than a socket the caller waits on until it times out.
193
+ if (!settled) {
194
+ reply.fail(new Error('[hosting] the handler returned without calling complete() or fail().'));
195
+ }
196
+ }
197
+ function readJson(req) {
198
+ return new Promise((resolve, reject) => {
199
+ const chunks = [];
200
+ req.on('data', (c) => chunks.push(c));
201
+ req.on('error', reject);
202
+ req.on('end', () => {
203
+ const raw = Buffer.concat(chunks).toString('utf8');
204
+ if (!raw)
205
+ return resolve({});
206
+ try {
207
+ const parsed = JSON.parse(raw);
208
+ resolve(parsed && typeof parsed === 'object' ? parsed : {});
209
+ }
210
+ catch (err) {
211
+ reject(err);
212
+ }
213
+ });
214
+ });
215
+ }
216
+ function sendJson(res, status, body) {
217
+ res.writeHead(status, { 'content-type': 'application/json' });
218
+ res.end(JSON.stringify(body));
219
+ }
220
+ function lowerCased(headers) {
221
+ const out = {};
222
+ for (const [name, value] of Object.entries(headers)) {
223
+ if (typeof value === 'string')
224
+ out[name.toLowerCase()] = value;
225
+ else if (Array.isArray(value))
226
+ out[name.toLowerCase()] = value.join(', ');
227
+ }
228
+ return out;
229
+ }
230
+ function asError(err) {
231
+ return err instanceof Error ? err : new Error(String(err));
232
+ }
233
+ /**
234
+ * Read a header case-insensitively from already-lower-cased facts.
235
+ *
236
+ * Exported because every wire that maps a header needs it and re-deriving it
237
+ * per adapter is how one of them ends up matching only the exact casing the
238
+ * author happened to test with.
239
+ */
240
+ export function headerValue(facts, name, ...fallbacks) {
241
+ for (const candidate of [name, ...fallbacks]) {
242
+ const found = facts.headers[candidate.toLowerCase()];
243
+ if (typeof found === 'string' && found.length > 0)
244
+ return found;
245
+ }
246
+ return undefined;
247
+ }
248
+ //# sourceMappingURL=httpHost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpHost.js","sourceRoot":"","sources":["../../../src/hosting/httpHost.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,11 @@
27
27
  * • `nodeHost({ port?, hostname?, invokePath?, healthPath? })` — plain
28
28
  * `node:http`, zero dependencies. `POST /invoke`, `GET /health`, and
29
29
  * Server-Sent Events when the caller asks for them.
30
+ * • `httpHost({ name, wire, invokePath, healthPath, ... })` — the HTTP work
31
+ * itself, parameterised by the JSON dialect it speaks. `nodeHost` is one
32
+ * configuration of it; an adapter for someone's container runtime is
33
+ * another. Two paths and five body shapes are all a second HTTP adapter
34
+ * re-decides.
30
35
  * • `memorySessions()` — conversations in a Map, for tests and local dev.
31
36
  * • `standingAgent({ agent, sessions, host })` — the composer.
32
37
  * • `toEnvelope` / `readEnvelope` — pack a conversation, and refuse by name to
@@ -44,8 +49,10 @@
44
49
  * });
45
50
  * process.on('SIGTERM', () => void handle.close());
46
51
  */
47
- export { nodeHost } from './nodeHost.js';
52
+ export { nodeHost, jsonWire } from './nodeHost.js';
48
53
  export type { NodeHost, NodeHostHandle, NodeHostOptions } from './nodeHost.js';
54
+ export { httpHost, headerValue } from './httpHost.js';
55
+ export type { HttpHost, HttpHostHandle, HttpHostOptions, HttpRequestFacts, HttpWire, } from './httpHost.js';
49
56
  export { memorySessions } from './memorySessions.js';
50
57
  export { toEnvelope, readEnvelope } from './envelope.js';
51
58
  export { standingAgent } from './standingAgent.js';
@@ -27,6 +27,11 @@
27
27
  * • `nodeHost({ port?, hostname?, invokePath?, healthPath? })` — plain
28
28
  * `node:http`, zero dependencies. `POST /invoke`, `GET /health`, and
29
29
  * Server-Sent Events when the caller asks for them.
30
+ * • `httpHost({ name, wire, invokePath, healthPath, ... })` — the HTTP work
31
+ * itself, parameterised by the JSON dialect it speaks. `nodeHost` is one
32
+ * configuration of it; an adapter for someone's container runtime is
33
+ * another. Two paths and five body shapes are all a second HTTP adapter
34
+ * re-decides.
30
35
  * • `memorySessions()` — conversations in a Map, for tests and local dev.
31
36
  * • `standingAgent({ agent, sessions, host })` — the composer.
32
37
  * • `toEnvelope` / `readEnvelope` — pack a conversation, and refuse by name to
@@ -44,7 +49,8 @@
44
49
  * });
45
50
  * process.on('SIGTERM', () => void handle.close());
46
51
  */
47
- export { nodeHost } from './nodeHost.js';
52
+ export { nodeHost, jsonWire } from './nodeHost.js';
53
+ export { httpHost, headerValue } from './httpHost.js';
48
54
  export { memorySessions } from './memorySessions.js';
49
55
  export { toEnvelope, readEnvelope } from './envelope.js';
50
56
  export { standingAgent } from './standingAgent.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hosting/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hosting/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGnD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAStD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
@@ -21,12 +21,13 @@
21
21
  * completion settles. The handler cannot tell the difference and does not need
22
22
  * to, which is the property `capabilities` exists to describe.
23
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.
24
+ * Pattern: Adapter. What is specific to THIS adapter is its two paths and its
25
+ * JSON dialect (`jsonWire` below) — nothing else. The HTTP work itself lives in
26
+ * `httpHost.ts` and is shared with every other HTTP adapter, so two of them can
27
+ * never quietly drift apart on what `close()` drains or what a handler that
28
+ * throws does. `types.ts` knows none of it either way.
28
29
  */
29
- import type { AgentHost, HostHandle, HostHandler } from './types.js';
30
+ import { type HttpHost, type HttpHostHandle, type HttpWire } from './httpHost.js';
30
31
  /** Options for {@link nodeHost}. */
31
32
  export interface NodeHostOptions {
32
33
  /** Port to bind. Default `8080`. Pass `0` for an ephemeral port. */
@@ -38,17 +39,23 @@ export interface NodeHostOptions {
38
39
  /** Path that answers a health probe. Default `'/health'`. */
39
40
  readonly healthPath?: string;
40
41
  }
41
- /** What {@link nodeHost}'s `serve()` resolves to — a {@link HostHandle} that also says where it landed. */
42
- export interface NodeHostHandle extends HostHandle {
43
- /** Where it is actually listening, e.g. `http://127.0.0.1:53211`. */
44
- readonly url: string;
45
- /** The port it actually bound — the real one, when you asked for `0`. */
46
- readonly port: number;
47
- }
48
- /** {@link AgentHost} narrowed to this adapter's handle. */
49
- export interface NodeHost extends AgentHost {
50
- serve(handler: HostHandler): Promise<NodeHostHandle>;
51
- }
42
+ /**
43
+ * What {@link nodeHost}'s `serve()` resolves to — a `HostHandle` that also
44
+ * reports the `url` and `port` it actually bound, which is the only way to find
45
+ * out when you asked for port `0`.
46
+ */
47
+ export type NodeHostHandle = HttpHostHandle;
48
+ /** `AgentHost` narrowed to this adapter's handle. */
49
+ export type NodeHost = HttpHost;
50
+ /**
51
+ * This adapter's own JSON dialect: `{ input, sessionId? }` in, `{ output }`
52
+ * out, `{ status: 'ok', uptimeMs }` on the health path.
53
+ *
54
+ * Exported by name so a deployment that has to keep these exact bodies while
55
+ * changing something else about the host reuses them rather than retyping them
56
+ * and getting one field subtly wrong.
57
+ */
58
+ export declare const jsonWire: HttpWire;
52
59
  /**
53
60
  * An HTTP host for one handler.
54
61
  *
@@ -21,28 +21,35 @@
21
21
  * completion settles. The handler cannot tell the difference and does not need
22
22
  * to, which is the property `capabilities` exists to describe.
23
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.
24
+ * Pattern: Adapter. What is specific to THIS adapter is its two paths and its
25
+ * JSON dialect (`jsonWire` below) — nothing else. The HTTP work itself lives in
26
+ * `httpHost.ts` and is shared with every other HTTP adapter, so two of them can
27
+ * never quietly drift apart on what `close()` drains or what a handler that
28
+ * throws does. `types.ts` knows none of it either way.
28
29
  */
29
- import { encodeSSE } from '../stream.js';
30
- import { HostClosedError } from './errors.js';
30
+ import { httpHost } from './httpHost.js';
31
31
  const HOST_NAME = 'nodeHost';
32
- const CAPABILITIES = ['streaming'];
33
32
  /**
34
- * Status codes this adapter maps by error code. Anything else is a 500.
33
+ * This adapter's own JSON dialect: `{ input, sessionId? }` in, `{ output }`
34
+ * out, `{ status: 'ok', uptimeMs }` on the health path.
35
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.
36
+ * Exported by name so a deployment that has to keep these exact bodies while
37
+ * changing something else about the host reuses them rather than retyping them
38
+ * and getting one field subtly wrong.
41
39
  */
42
- const STATUS_BY_CODE = {
43
- ERR_HOST_CLOSED: 503,
44
- ERR_CONCURRENT_RUN: 409,
45
- ERR_PAUSE_NOT_CARRIED: 409,
40
+ export const jsonWire = {
41
+ readRequest(facts) {
42
+ const input = typeof facts.body.input === 'string' ? facts.body.input : '';
43
+ // sessionId is caller data whichever way it arrives; the body wins so a
44
+ // caller that sets both is not surprised by which one the server preferred.
45
+ const fromBody = typeof facts.body.sessionId === 'string' ? facts.body.sessionId : undefined;
46
+ const sessionId = fromBody ?? facts.headers['x-session-id'];
47
+ return sessionId !== undefined ? { input, sessionId } : { input };
48
+ },
49
+ health: (uptimeMs) => ({ status: 'ok', uptimeMs }),
50
+ output: (output) => ({ output }),
51
+ failure: (error, code) => ({ error, ...(code !== undefined && { code }) }),
52
+ chunk: (text) => ({ text }),
46
53
  };
47
54
  /**
48
55
  * An HTTP host for one handler.
@@ -57,189 +64,15 @@ const STATUS_BY_CODE = {
57
64
  * await handle.close();
58
65
  */
59
66
  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 {
67
+ return httpHost({
65
68
  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
- });
69
+ wire: jsonWire,
70
+ // Chosen, not inherited — see the test in this folder that greps for one
71
+ // particular runtime's container-contract path literal.
72
+ invokePath: options.invokePath ?? '/invoke',
73
+ healthPath: options.healthPath ?? '/health',
74
+ ...(options.port !== undefined && { port: options.port }),
75
+ ...(options.hostname !== undefined && { hostname: options.hostname }),
226
76
  });
227
77
  }
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
78
  //# sourceMappingURL=nodeHost.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nodeHost.js","sourceRoot":"","sources":["../../../src/hosting/nodeHost.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nodeHost.js","sourceRoot":"","sources":["../../../src/hosting/nodeHost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,QAAQ,EAAqD,MAAM,eAAe,CAAC;AAwB5F,MAAM,SAAS,GAAG,UAAU,CAAC;AAE7B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAa;IAChC,WAAW,CAAC,KAAK;QACf,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,wEAAwE;QACxE,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7F,MAAM,SAAS,GAAG,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC5D,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;IACpE,CAAC;IACD,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAClD,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC1E,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;CAC5B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CAAC,UAA2B,EAAE;IACpD,OAAO,QAAQ,CAAC;QACd,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,QAAQ;QACd,yEAAyE;QACzE,wDAAwD;QACxD,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;QAC3C,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;QAC3C,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QACzD,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;KACtE,CAAC,CAAC;AACL,CAAC"}