@nextclaw/ncp-http-agent-server 0.3.20 → 0.3.21
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/index.js +65 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ async function parseRequestEnvelope(request) {
|
|
|
19
19
|
try {
|
|
20
20
|
const payload = await request.json();
|
|
21
21
|
if (!isRecord$1(payload)) return null;
|
|
22
|
-
if (typeof payload.sessionId !== "string" || !payload.sessionId.trim()) return null;
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(payload, "sessionId") && (typeof payload.sessionId !== "string" || !payload.sessionId.trim())) return null;
|
|
23
23
|
if (!isRecord$1(payload.message)) return null;
|
|
24
24
|
return payload;
|
|
25
25
|
} catch {
|
|
@@ -246,6 +246,61 @@ async function* createForwardSseEvents(options) {
|
|
|
246
246
|
stop();
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
|
+
function createSendStreamResponse(options) {
|
|
250
|
+
const { requestSignal } = options;
|
|
251
|
+
return buildSseResponse(createSseEventStream(createSendStreamSseEvents(options), requestSignal));
|
|
252
|
+
}
|
|
253
|
+
async function* createSendStreamSseEvents(options) {
|
|
254
|
+
const { endpoint, envelope, requestSignal, timeoutMs } = options;
|
|
255
|
+
const queue = createAsyncQueue();
|
|
256
|
+
let timeoutId = null;
|
|
257
|
+
let unsubscribe = null;
|
|
258
|
+
let stopped = false;
|
|
259
|
+
let sessionId = envelope.sessionId?.trim() || null;
|
|
260
|
+
const push = (frame) => {
|
|
261
|
+
if (!stopped) queue.push(frame);
|
|
262
|
+
};
|
|
263
|
+
const stop = () => {
|
|
264
|
+
if (stopped) return;
|
|
265
|
+
stopped = true;
|
|
266
|
+
if (timeoutId) {
|
|
267
|
+
clearTimeout(timeoutId);
|
|
268
|
+
timeoutId = null;
|
|
269
|
+
}
|
|
270
|
+
if (unsubscribe) {
|
|
271
|
+
unsubscribe();
|
|
272
|
+
unsubscribe = null;
|
|
273
|
+
}
|
|
274
|
+
requestSignal.removeEventListener("abort", stop);
|
|
275
|
+
queue.close();
|
|
276
|
+
};
|
|
277
|
+
requestSignal.addEventListener("abort", stop, { once: true });
|
|
278
|
+
if (timeoutMs !== null) timeoutId = setTimeout(() => {
|
|
279
|
+
push(toErrorFrame("TIMEOUT", "NCP HTTP send stream timed out before terminal event."));
|
|
280
|
+
stop();
|
|
281
|
+
}, timeoutMs);
|
|
282
|
+
unsubscribe = endpoint.subscribe((event) => {
|
|
283
|
+
const payload = "payload" in event ? event.payload : null;
|
|
284
|
+
const eventSessionId = payload && typeof payload === "object" && "sessionId" in payload && typeof payload.sessionId === "string" ? payload.sessionId : null;
|
|
285
|
+
if (sessionId && eventSessionId && eventSessionId !== sessionId) return;
|
|
286
|
+
if (!sessionId && eventSessionId) sessionId = eventSessionId;
|
|
287
|
+
push(toNcpEventFrame(event));
|
|
288
|
+
});
|
|
289
|
+
endpoint.emit({
|
|
290
|
+
type: NcpEventType.MessageRequest,
|
|
291
|
+
payload: envelope
|
|
292
|
+
}).catch((error) => {
|
|
293
|
+
push(toErrorFrame("EMIT_FAILED", errorMessage(error)));
|
|
294
|
+
stop();
|
|
295
|
+
}).finally(() => {
|
|
296
|
+
if (!requestSignal.aborted) queueMicrotask(stop);
|
|
297
|
+
});
|
|
298
|
+
try {
|
|
299
|
+
for await (const frame of queue.iterable) yield frame;
|
|
300
|
+
} finally {
|
|
301
|
+
stop();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
249
304
|
function createLiveStreamResponse(options) {
|
|
250
305
|
const { signal } = options;
|
|
251
306
|
return buildSseResponse(createSseEventStream(createLiveStreamSseEvents(options), signal));
|
|
@@ -284,6 +339,12 @@ var NcpHttpAgentController = class {
|
|
|
284
339
|
message: "Invalid NCP request envelope."
|
|
285
340
|
}
|
|
286
341
|
}, 400);
|
|
342
|
+
if (acceptsEventStream(request)) return createSendStreamResponse({
|
|
343
|
+
endpoint: agentClientEndpoint,
|
|
344
|
+
envelope,
|
|
345
|
+
requestSignal: request.signal,
|
|
346
|
+
timeoutMs: this.options.timeoutMs
|
|
347
|
+
});
|
|
287
348
|
await agentClientEndpoint.send(envelope);
|
|
288
349
|
return jsonResponse({ ok: true });
|
|
289
350
|
}
|
|
@@ -327,6 +388,9 @@ var NcpHttpAgentController = class {
|
|
|
327
388
|
return jsonResponse({ ok: true });
|
|
328
389
|
}
|
|
329
390
|
};
|
|
391
|
+
function acceptsEventStream(request) {
|
|
392
|
+
return request.headers.get("accept")?.includes("text/event-stream") ?? false;
|
|
393
|
+
}
|
|
330
394
|
//#endregion
|
|
331
395
|
//#region src/router.ts
|
|
332
396
|
function createNcpHttpAgentRouter(options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/ncp-http-agent-server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.21",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "HTTP/SSE server transport adapter for NCP agent endpoints.",
|
|
6
6
|
"type": "module",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"hono": "^4.9.8",
|
|
19
|
-
"@nextclaw/ncp": "0.5.
|
|
19
|
+
"@nextclaw/ncp": "0.5.9"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^20.17.6",
|