

























@@ -1028,6 +1028,85 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
10281028}
10291029});
103010301031+it(
1032+"sends an initial SSE chunk before a streaming agent run settles",
1033+{ timeout: 15_000 },
1034+async () => {
1035+const port = enabledPort;
1036+let serverAbortSignal: AbortSignal | undefined;
1037+1038+agentCommand.mockClear();
1039+agentCommand.mockImplementationOnce(
1040+(opts: unknown) =>
1041+new Promise<undefined>((resolve) => {
1042+const signal = (opts as { abortSignal?: AbortSignal } | undefined)?.abortSignal;
1043+serverAbortSignal = signal;
1044+if (signal?.aborted) {
1045+resolve(undefined);
1046+return;
1047+}
1048+signal?.addEventListener("abort", () => resolve(undefined), { once: true });
1049+}),
1050+);
1051+1052+let settled = false;
1053+const firstChunk = new Promise<string>((resolve, reject) => {
1054+const clientReq = http.request(
1055+{
1056+hostname: "127.0.0.1",
1057+ port,
1058+path: "/v1/chat/completions",
1059+method: "POST",
1060+headers: {
1061+"content-type": "application/json",
1062+authorization: "Bearer secret",
1063+},
1064+},
1065+(res) => {
1066+expect(res.statusCode).toBe(200);
1067+expect(res.headers["content-type"] ?? "").toContain("text/event-stream");
1068+res.setEncoding("utf8");
1069+res.once("data", (chunk) => {
1070+settled = true;
1071+resolve(String(chunk));
1072+clientReq.destroy();
1073+});
1074+},
1075+);
1076+clientReq.on("error", (err) => {
1077+if (!settled) {
1078+reject(err);
1079+}
1080+});
1081+clientReq.setTimeout(2_000, () => {
1082+if (!settled) {
1083+settled = true;
1084+clientReq.destroy(new Error("timed out waiting for first SSE chunk"));
1085+}
1086+});
1087+clientReq.end(
1088+JSON.stringify({
1089+stream: true,
1090+model: "openclaw",
1091+messages: [{ role: "user", content: "hi" }],
1092+}),
1093+);
1094+});
1095+1096+await expect(firstChunk).resolves.toContain('"role":"assistant"');
1097+await vi.waitFor(() => {
1098+expect(agentCommand).toHaveBeenCalledTimes(1);
1099+});
1100+1101+await vi.waitFor(
1102+() => {
1103+expect(serverAbortSignal?.aborted).toBe(true);
1104+},
1105+{ timeout: 5_000, interval: 50 },
1106+);
1107+},
1108+);
1109+10311110it("includes usage in final stream chunk when stream_options.include_usage=true", async () => {
10321111const port = enabledPort;
10331112agentCommand.mockClear();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。