@polpo-ai/server 0.15.76 → 0.15.77
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.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/completions/chat-handler.d.ts +10 -0
- package/dist/routes/completions/chat-handler.d.ts.map +1 -1
- package/dist/routes/completions/chat-handler.js +436 -436
- package/dist/routes/completions/chat-handler.js.map +1 -1
- package/dist/routes/completions/chat-via-run-handler.d.ts +2 -1
- package/dist/routes/completions/chat-via-run-handler.d.ts.map +1 -1
- package/dist/routes/completions/chat-via-run-handler.js +102 -91
- package/dist/routes/completions/chat-via-run-handler.js.map +1 -1
- package/dist/routes/completions/durable-stream.d.ts +39 -0
- package/dist/routes/completions/durable-stream.d.ts.map +1 -0
- package/dist/routes/completions/durable-stream.js +83 -0
- package/dist/routes/completions/durable-stream.js.map +1 -0
- package/dist/routes/completions/durable-stream.test.d.ts +2 -0
- package/dist/routes/completions/durable-stream.test.d.ts.map +1 -0
- package/dist/routes/completions/durable-stream.test.js +140 -0
- package/dist/routes/completions/durable-stream.test.js.map +1 -0
- package/dist/routes/completions/project-loop-runner.d.ts +6 -2
- package/dist/routes/completions/project-loop-runner.d.ts.map +1 -1
- package/dist/routes/completions/project-loop-runner.js +121 -113
- package/dist/routes/completions/project-loop-runner.js.map +1 -1
- package/dist/routes/completions/schemas.d.ts +12 -0
- package/dist/routes/completions/schemas.d.ts.map +1 -1
- package/dist/routes/completions/schemas.js +5 -0
- package/dist/routes/completions/schemas.js.map +1 -1
- package/dist/routes/completions/schemas.test.js +20 -0
- package/dist/routes/completions/schemas.test.js.map +1 -1
- package/dist/routes/completions-durable-delivery.test.d.ts +2 -0
- package/dist/routes/completions-durable-delivery.test.d.ts.map +1 -0
- package/dist/routes/completions-durable-delivery.test.js +154 -0
- package/dist/routes/completions-durable-delivery.test.js.map +1 -0
- package/dist/routes/completions.d.ts +13 -0
- package/dist/routes/completions.d.ts.map +1 -1
- package/dist/routes/completions.js +107 -5
- package/dist/routes/completions.js.map +1 -1
- package/dist/routes/run-delivery.d.ts +15 -0
- package/dist/routes/run-delivery.d.ts.map +1 -0
- package/dist/routes/run-delivery.js +202 -0
- package/dist/routes/run-delivery.js.map +1 -0
- package/dist/routes/run-delivery.test.d.ts +2 -0
- package/dist/routes/run-delivery.test.d.ts.map +1 -0
- package/dist/routes/run-delivery.test.js +124 -0
- package/dist/routes/run-delivery.test.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { RunEventJournal, followRunEvents, } from "@polpo-ai/core/run-delivery-follower";
|
|
2
|
+
import { executeOwnedRun, } from "@polpo-ai/core/run-delivery-owner";
|
|
3
|
+
export function createDurableCompletionWriter(runId, scope) {
|
|
4
|
+
const journal = new RunEventJournal(scope.eventStore, scope.notifier);
|
|
5
|
+
let writeChain = Promise.resolve();
|
|
6
|
+
return {
|
|
7
|
+
write: async () => undefined,
|
|
8
|
+
writeSSE: (message) => {
|
|
9
|
+
writeChain = writeChain.then(() => journal.append(runId, {
|
|
10
|
+
type: message.data === "[DONE]" ? "response.done" : "response.chunk",
|
|
11
|
+
data: {
|
|
12
|
+
data: message.data,
|
|
13
|
+
...(message.event === undefined ? {} : { event: message.event }),
|
|
14
|
+
...(message.id === undefined ? {} : { id: message.id }),
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
return writeChain;
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function startDurableCompletion(options) {
|
|
22
|
+
const journal = new RunEventJournal(options.scope.eventStore, options.scope.notifier);
|
|
23
|
+
return executeOwnedRun({
|
|
24
|
+
runId: options.runId,
|
|
25
|
+
owner: options.scope.owner,
|
|
26
|
+
token: options.scope.token,
|
|
27
|
+
journal,
|
|
28
|
+
leaseStore: options.scope.leaseStore,
|
|
29
|
+
cancellationStore: options.scope.cancellationStore,
|
|
30
|
+
producer: async ({ signal }) => {
|
|
31
|
+
await options.producer({
|
|
32
|
+
signal,
|
|
33
|
+
writer: createDurableCompletionWriter(options.runId, options.scope),
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export async function streamDurableCompletionFrames(options) {
|
|
39
|
+
let responseDone = false;
|
|
40
|
+
for await (const event of followRunEvents({
|
|
41
|
+
runId: options.runId,
|
|
42
|
+
store: options.scope.eventStore,
|
|
43
|
+
notifier: options.scope.notifier,
|
|
44
|
+
cursor: options.cursor,
|
|
45
|
+
signal: options.signal,
|
|
46
|
+
})) {
|
|
47
|
+
if (event.type === "response.chunk" || event.type === "response.done") {
|
|
48
|
+
const data = typeof event.data.data === "string" ? event.data.data : undefined;
|
|
49
|
+
if (data === undefined)
|
|
50
|
+
continue;
|
|
51
|
+
responseDone ||= event.type === "response.done";
|
|
52
|
+
await options.write({
|
|
53
|
+
data,
|
|
54
|
+
cursor: String(event.sequence),
|
|
55
|
+
...(typeof event.data.event === "string" ? { event: event.data.event } : {}),
|
|
56
|
+
...(typeof event.data.id === "string" ? { id: event.data.id } : {}),
|
|
57
|
+
});
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (event.type === "run.failed") {
|
|
61
|
+
const message = typeof event.data.message === "string"
|
|
62
|
+
? event.data.message
|
|
63
|
+
: "Run execution failed";
|
|
64
|
+
await options.write({
|
|
65
|
+
event: "error",
|
|
66
|
+
cursor: String(event.sequence),
|
|
67
|
+
data: JSON.stringify({
|
|
68
|
+
error: {
|
|
69
|
+
message,
|
|
70
|
+
type: "model_error",
|
|
71
|
+
code: "model_request_failed",
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (!responseDone && (event.type === "run.completed" || event.type === "run.cancelled")) {
|
|
78
|
+
responseDone = true;
|
|
79
|
+
await options.write({ data: "[DONE]", cursor: String(event.sequence) });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=durable-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-stream.js","sourceRoot":"","sources":["../../../src/routes/completions/durable-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-stream.test.d.ts","sourceRoot":"","sources":["../../../src/routes/completions/durable-stream.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { InMemoryRunCancellationStore, InMemoryRunEventStore, InMemoryRunExecutionLeaseStore, } from "@polpo-ai/core/run-delivery";
|
|
3
|
+
import { InMemoryRunEventNotifier } from "@polpo-ai/core/run-delivery-follower";
|
|
4
|
+
import { createDurableCompletionWriter, startDurableCompletion, streamDurableCompletionFrames, } from "./durable-stream.js";
|
|
5
|
+
function scope() {
|
|
6
|
+
return {
|
|
7
|
+
eventStore: new InMemoryRunEventStore(),
|
|
8
|
+
leaseStore: new InMemoryRunExecutionLeaseStore(),
|
|
9
|
+
cancellationStore: new InMemoryRunCancellationStore(),
|
|
10
|
+
notifier: new InMemoryRunEventNotifier(),
|
|
11
|
+
owner: "worker-a",
|
|
12
|
+
token: "token-a",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
describe("durable completion stream", () => {
|
|
16
|
+
it("persists OpenAI frames and replays them without lifecycle internals", async () => {
|
|
17
|
+
const delivery = scope();
|
|
18
|
+
const execution = startDurableCompletion({
|
|
19
|
+
runId: "run-a",
|
|
20
|
+
scope: delivery,
|
|
21
|
+
producer: async ({ writer }) => {
|
|
22
|
+
await writer.writeSSE({ data: '{"choices":[{"delta":{"content":"hello"}}]}' });
|
|
23
|
+
await writer.writeSSE({ data: "[DONE]" });
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
const frames = [];
|
|
27
|
+
await streamDurableCompletionFrames({
|
|
28
|
+
runId: "run-a",
|
|
29
|
+
scope: delivery,
|
|
30
|
+
write: async (frame) => { frames.push(frame.data); },
|
|
31
|
+
});
|
|
32
|
+
await expect(execution).resolves.toEqual({ status: "completed" });
|
|
33
|
+
expect(frames).toEqual([
|
|
34
|
+
'{"choices":[{"delta":{"content":"hello"}}]}',
|
|
35
|
+
"[DONE]",
|
|
36
|
+
]);
|
|
37
|
+
expect((await delivery.eventStore.listAfter("run-a")).events.map((event) => event.type)).toEqual([
|
|
38
|
+
"run.started",
|
|
39
|
+
"response.chunk",
|
|
40
|
+
"response.done",
|
|
41
|
+
"run.completed",
|
|
42
|
+
]);
|
|
43
|
+
});
|
|
44
|
+
it("subscriber disconnect aborts only the follower while the producer completes", async () => {
|
|
45
|
+
const delivery = scope();
|
|
46
|
+
let releaseProducer;
|
|
47
|
+
const producerGate = new Promise((resolve) => { releaseProducer = resolve; });
|
|
48
|
+
let producerSignal;
|
|
49
|
+
const execution = startDurableCompletion({
|
|
50
|
+
runId: "run-a",
|
|
51
|
+
scope: delivery,
|
|
52
|
+
producer: async ({ writer, signal }) => {
|
|
53
|
+
producerSignal = signal;
|
|
54
|
+
await writer.writeSSE({ data: '{"chunk":1}' });
|
|
55
|
+
await producerGate;
|
|
56
|
+
await writer.writeSSE({ data: "[DONE]" });
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
const follower = new AbortController();
|
|
60
|
+
const frames = [];
|
|
61
|
+
const streaming = streamDurableCompletionFrames({
|
|
62
|
+
runId: "run-a",
|
|
63
|
+
scope: delivery,
|
|
64
|
+
signal: follower.signal,
|
|
65
|
+
write: async (frame) => {
|
|
66
|
+
frames.push(frame.data);
|
|
67
|
+
follower.abort();
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
await streaming;
|
|
71
|
+
expect(producerSignal?.aborted).toBe(false);
|
|
72
|
+
releaseProducer();
|
|
73
|
+
await expect(execution).resolves.toEqual({ status: "completed" });
|
|
74
|
+
expect(producerSignal?.aborted).toBe(false);
|
|
75
|
+
expect(frames).toEqual(['{"chunk":1}']);
|
|
76
|
+
});
|
|
77
|
+
it("serializes concurrent writer calls in invocation order", async () => {
|
|
78
|
+
const delivery = scope();
|
|
79
|
+
const writer = createDurableCompletionWriter("run-a", delivery);
|
|
80
|
+
await Promise.all([
|
|
81
|
+
writer.writeSSE({ data: "one" }),
|
|
82
|
+
writer.writeSSE({ data: "two" }),
|
|
83
|
+
writer.writeSSE({ data: "[DONE]" }),
|
|
84
|
+
]);
|
|
85
|
+
const events = (await delivery.eventStore.listAfter("run-a")).events;
|
|
86
|
+
expect(events.map((event) => event.data.data)).toEqual(["one", "two", "[DONE]"]);
|
|
87
|
+
});
|
|
88
|
+
it("projects unexpected producer failures to the initial subscriber", async () => {
|
|
89
|
+
const delivery = scope();
|
|
90
|
+
const execution = startDurableCompletion({
|
|
91
|
+
runId: "run-a",
|
|
92
|
+
scope: delivery,
|
|
93
|
+
producer: async () => { throw new Error("provider unavailable"); },
|
|
94
|
+
});
|
|
95
|
+
const frames = [];
|
|
96
|
+
await streamDurableCompletionFrames({
|
|
97
|
+
runId: "run-a",
|
|
98
|
+
scope: delivery,
|
|
99
|
+
write: async (frame) => {
|
|
100
|
+
frames.push({
|
|
101
|
+
data: frame.data,
|
|
102
|
+
...(frame.event === undefined ? {} : { event: frame.event }),
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
await expect(execution).resolves.toEqual({
|
|
107
|
+
status: "failed",
|
|
108
|
+
error: "provider unavailable",
|
|
109
|
+
});
|
|
110
|
+
expect(frames).toEqual([{
|
|
111
|
+
event: "error",
|
|
112
|
+
data: JSON.stringify({
|
|
113
|
+
error: {
|
|
114
|
+
message: "provider unavailable",
|
|
115
|
+
type: "model_error",
|
|
116
|
+
code: "model_request_failed",
|
|
117
|
+
},
|
|
118
|
+
}),
|
|
119
|
+
}]);
|
|
120
|
+
});
|
|
121
|
+
it("emits a terminal frame when a producer completes without writing DONE", async () => {
|
|
122
|
+
const delivery = scope();
|
|
123
|
+
const execution = startDurableCompletion({
|
|
124
|
+
runId: "run-a",
|
|
125
|
+
scope: delivery,
|
|
126
|
+
producer: async ({ writer }) => {
|
|
127
|
+
await writer.writeSSE({ data: '{"choices":[]}' });
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
const frames = [];
|
|
131
|
+
await streamDurableCompletionFrames({
|
|
132
|
+
runId: "run-a",
|
|
133
|
+
scope: delivery,
|
|
134
|
+
write: async (frame) => { frames.push(frame.data); },
|
|
135
|
+
});
|
|
136
|
+
await expect(execution).resolves.toEqual({ status: "completed" });
|
|
137
|
+
expect(frames).toEqual(['{"choices":[]}', "[DONE]"]);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
//# sourceMappingURL=durable-stream.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-stream.test.js","sourceRoot":"","sources":["../../../src/routes/completions/durable-stream.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ import type { LanguageModelUsage } from "ai";
|
|
|
11
11
|
import type { CompletionRouteDeps, CompletionRuntimeInvocation } from "../completions.js";
|
|
12
12
|
import { type CompletionResolvedModelInfo } from "./agent-step-runner.js";
|
|
13
13
|
import { type LoopRuntimeToolCall } from "./tool-mapping.js";
|
|
14
|
+
import type { CompletionSseWriter } from "./chat-handler.js";
|
|
14
15
|
export interface ProjectLoopRunResult {
|
|
15
16
|
text: string;
|
|
16
17
|
usage: LanguageModelUsage;
|
|
@@ -63,7 +64,7 @@ export declare function resumeProjectLoopRun(options: {
|
|
|
63
64
|
* pipeline and adapts it to the OpenAI response surface (SSE stream with
|
|
64
65
|
* tool_call / loop_trace chunks, or a single JSON body).
|
|
65
66
|
*/
|
|
66
|
-
export
|
|
67
|
+
export interface ProjectLoopCompletionOptions {
|
|
67
68
|
deps: CompletionRouteDeps;
|
|
68
69
|
body: {
|
|
69
70
|
stream?: boolean;
|
|
@@ -84,5 +85,8 @@ export declare function handleProjectLoopCompletion(c: any, options: {
|
|
|
84
85
|
runtimePlan?: RuntimePlan;
|
|
85
86
|
executionRoute?: ResolvedExecutionRoute;
|
|
86
87
|
activatedSkills?: readonly string[];
|
|
87
|
-
}
|
|
88
|
+
}
|
|
89
|
+
export declare function handleProjectLoopCompletion(c: any, options: ProjectLoopCompletionOptions): Promise<any>;
|
|
90
|
+
/** Transport-independent loop producer used by attached and durable followers. */
|
|
91
|
+
export declare function executeStreamingProjectLoopCompletion(stream: CompletionSseWriter, options: ProjectLoopCompletionOptions, signal: AbortSignal): Promise<void>;
|
|
88
92
|
//# sourceMappingURL=project-loop-runner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-loop-runner.d.ts","sourceRoot":"","sources":["../../../src/routes/completions/project-loop-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAcL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAE3B,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC;AAC7C,OAAO,KAAK,EACV,mBAAmB,EACnB,2BAA2B,EAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAIL,KAAK,2BAA2B,EACjC,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EAA4C,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"project-loop-runner.d.ts","sourceRoot":"","sources":["../../../src/routes/completions/project-loop-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -628,15 +628,8 @@ export async function resumeProjectLoopRun(options) {
|
|
|
628
628
|
throw new Error(`Loop run "${run.id}" disappeared after resume`);
|
|
629
629
|
return updated;
|
|
630
630
|
}
|
|
631
|
-
/**
|
|
632
|
-
* HTTP wiring for loop-mode completion requests: runs the project loop
|
|
633
|
-
* pipeline and adapts it to the OpenAI response surface (SSE stream with
|
|
634
|
-
* tool_call / loop_trace chunks, or a single JSON body).
|
|
635
|
-
*/
|
|
636
631
|
export async function handleProjectLoopCompletion(c, options) {
|
|
637
|
-
|
|
638
|
-
const contextTrust = normalizeRuntimeContextTrustMode(options.contextTrust ?? deps.getConfig()?.settings?.contextTrust);
|
|
639
|
-
if (body.stream) {
|
|
632
|
+
if (options.body.stream) {
|
|
640
633
|
return streamSSE(c, async (stream) => {
|
|
641
634
|
const abortController = new AbortController();
|
|
642
635
|
stream.onAbort(() => { abortController.abort(); });
|
|
@@ -649,118 +642,133 @@ export async function handleProjectLoopCompletion(c, options) {
|
|
|
649
642
|
clearInterval(heartbeatInterval);
|
|
650
643
|
});
|
|
651
644
|
}, 20_000);
|
|
652
|
-
let assistantMsgId = null;
|
|
653
|
-
let finalText = "";
|
|
654
|
-
let runUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
655
|
-
let runModel = agentConfigForModelPrimary(agentConfig, deps.getConfig()?.settings).model ?? "polpo";
|
|
656
|
-
let resolvedModel;
|
|
657
|
-
let providerMetadata;
|
|
658
|
-
let toolCalls = [];
|
|
659
|
-
const outputMode = streamingOutputPolicyMode(deps.runOutputPolicy);
|
|
660
645
|
try {
|
|
661
|
-
await stream
|
|
662
|
-
if (sessionStore && sessionId) {
|
|
663
|
-
const placeholder = await sessionStore.addMessage(sessionId, "assistant", "");
|
|
664
|
-
assistantMsgId = placeholder.id;
|
|
665
|
-
}
|
|
666
|
-
const run = await runProjectLoopCompletion({
|
|
667
|
-
deps,
|
|
668
|
-
agentConfig,
|
|
669
|
-
projectLoop,
|
|
670
|
-
aiMessages,
|
|
671
|
-
extraSystemParts,
|
|
672
|
-
contextTrust,
|
|
673
|
-
runtimeContext,
|
|
674
|
-
runtimeInvocation,
|
|
675
|
-
sessionId,
|
|
676
|
-
user: body.user,
|
|
677
|
-
requestMetadata: body.metadata,
|
|
678
|
-
runtimePlan,
|
|
679
|
-
signal: abortController.signal,
|
|
680
|
-
executionRoute,
|
|
681
|
-
activatedSkills,
|
|
682
|
-
onToolCall: async (toolCall) => {
|
|
683
|
-
if (abortController.signal.aborted)
|
|
684
|
-
return;
|
|
685
|
-
await stream.writeSSE({
|
|
686
|
-
data: sseChunk(completionId, {}, null, { tool_call: toolCall }),
|
|
687
|
-
});
|
|
688
|
-
},
|
|
689
|
-
onTrace: async (event) => {
|
|
690
|
-
if (abortController.signal.aborted)
|
|
691
|
-
return;
|
|
692
|
-
await stream.writeSSE({
|
|
693
|
-
data: sseChunk(completionId, {}, null, { loop_trace: event }),
|
|
694
|
-
});
|
|
695
|
-
},
|
|
696
|
-
});
|
|
697
|
-
finalText = run.text;
|
|
698
|
-
runUsage = run.usage;
|
|
699
|
-
runModel = run.model;
|
|
700
|
-
resolvedModel = run.resolvedModel;
|
|
701
|
-
providerMetadata = run.providerMetadata;
|
|
702
|
-
toolCalls = run.toolCalls;
|
|
703
|
-
finalText = await applyCompletionOutputPolicy({
|
|
704
|
-
outputPolicy: deps.runOutputPolicy,
|
|
705
|
-
text: finalText,
|
|
706
|
-
mode: outputMode === "buffer" ? "enforce" : "audit",
|
|
707
|
-
runtimePlan,
|
|
708
|
-
agent: body.agent,
|
|
709
|
-
runId: run.loopRunId,
|
|
710
|
-
sessionId,
|
|
711
|
-
signal: abortController.signal,
|
|
712
|
-
});
|
|
713
|
-
if (!abortController.signal.aborted && finalText) {
|
|
714
|
-
await stream.writeSSE({ data: sseChunk(completionId, { content: finalText }) });
|
|
715
|
-
}
|
|
716
|
-
if (!abortController.signal.aborted) {
|
|
717
|
-
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop", { loop_run_id: run.loopRunId }) });
|
|
718
|
-
await stream.writeSSE({ data: "[DONE]" });
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
catch (err) {
|
|
722
|
-
if ((err instanceof DOMException && err.name === "AbortError") || abortController.signal.aborted) {
|
|
723
|
-
return;
|
|
724
|
-
}
|
|
725
|
-
const guardrailError = guardrailErrorEnvelope(err);
|
|
726
|
-
const notFound = modelNotFoundEnvelope(err, runModel, body.agent);
|
|
727
|
-
if (guardrailError) {
|
|
728
|
-
finalText = guardrailError.message;
|
|
729
|
-
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop", { error: guardrailError }) });
|
|
730
|
-
await stream.writeSSE({ data: "[DONE]" });
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
if (notFound) {
|
|
734
|
-
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop", { error: notFound }) });
|
|
735
|
-
await stream.writeSSE({ data: "[DONE]" });
|
|
736
|
-
return;
|
|
737
|
-
}
|
|
738
|
-
const loopError = loopRuntimeErrorEnvelope(err);
|
|
739
|
-
if (loopError) {
|
|
740
|
-
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop", { error: loopError }) });
|
|
741
|
-
await stream.writeSSE({ data: "[DONE]" });
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
throw err;
|
|
646
|
+
await executeStreamingProjectLoopCompletion(stream, options, abortController.signal);
|
|
745
647
|
}
|
|
746
648
|
finally {
|
|
747
649
|
clearInterval(heartbeatInterval);
|
|
748
|
-
await persistAssistantMessage(sessionStore, sessionId, assistantMsgId, finalText, toolCalls);
|
|
749
|
-
try {
|
|
750
|
-
deps.onCompletionFinished?.({
|
|
751
|
-
usage: runUsage,
|
|
752
|
-
model: runModel,
|
|
753
|
-
resolvedModel,
|
|
754
|
-
agent: body.agent,
|
|
755
|
-
sessionId: sessionId ?? undefined,
|
|
756
|
-
user: body.user,
|
|
757
|
-
providerMetadata,
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
catch { /* never fail on callback */ }
|
|
761
650
|
}
|
|
762
651
|
});
|
|
763
652
|
}
|
|
653
|
+
return runNonStreamingProjectLoopCompletion(c, options);
|
|
654
|
+
}
|
|
655
|
+
/** Transport-independent loop producer used by attached and durable followers. */
|
|
656
|
+
export async function executeStreamingProjectLoopCompletion(stream, options, signal) {
|
|
657
|
+
const { deps, body, completionId, agentConfig, projectLoop, aiMessages, extraSystemParts, runtimeContext, runtimeInvocation, sessionStore, sessionId, runtimePlan, executionRoute, activatedSkills, } = options;
|
|
658
|
+
const contextTrust = normalizeRuntimeContextTrustMode(options.contextTrust ?? deps.getConfig()?.settings?.contextTrust);
|
|
659
|
+
let assistantMsgId = null;
|
|
660
|
+
let finalText = "";
|
|
661
|
+
let runUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
662
|
+
let runModel = agentConfigForModelPrimary(agentConfig, deps.getConfig()?.settings).model ?? "polpo";
|
|
663
|
+
let resolvedModel;
|
|
664
|
+
let providerMetadata;
|
|
665
|
+
let toolCalls = [];
|
|
666
|
+
const outputMode = streamingOutputPolicyMode(deps.runOutputPolicy);
|
|
667
|
+
try {
|
|
668
|
+
await stream.writeSSE({ data: sseChunk(completionId, { role: "assistant" }) });
|
|
669
|
+
if (sessionStore && sessionId) {
|
|
670
|
+
const placeholder = await sessionStore.addMessage(sessionId, "assistant", "");
|
|
671
|
+
assistantMsgId = placeholder.id;
|
|
672
|
+
}
|
|
673
|
+
const run = await runProjectLoopCompletion({
|
|
674
|
+
deps,
|
|
675
|
+
agentConfig,
|
|
676
|
+
projectLoop,
|
|
677
|
+
aiMessages,
|
|
678
|
+
extraSystemParts,
|
|
679
|
+
contextTrust,
|
|
680
|
+
runtimeContext,
|
|
681
|
+
runtimeInvocation,
|
|
682
|
+
sessionId,
|
|
683
|
+
user: body.user,
|
|
684
|
+
requestMetadata: body.metadata,
|
|
685
|
+
runtimePlan,
|
|
686
|
+
signal,
|
|
687
|
+
executionRoute,
|
|
688
|
+
activatedSkills,
|
|
689
|
+
onToolCall: async (toolCall) => {
|
|
690
|
+
if (signal.aborted)
|
|
691
|
+
return;
|
|
692
|
+
await stream.writeSSE({
|
|
693
|
+
data: sseChunk(completionId, {}, null, { tool_call: toolCall }),
|
|
694
|
+
});
|
|
695
|
+
},
|
|
696
|
+
onTrace: async (event) => {
|
|
697
|
+
if (signal.aborted)
|
|
698
|
+
return;
|
|
699
|
+
await stream.writeSSE({
|
|
700
|
+
data: sseChunk(completionId, {}, null, { loop_trace: event }),
|
|
701
|
+
});
|
|
702
|
+
},
|
|
703
|
+
});
|
|
704
|
+
finalText = run.text;
|
|
705
|
+
runUsage = run.usage;
|
|
706
|
+
runModel = run.model;
|
|
707
|
+
resolvedModel = run.resolvedModel;
|
|
708
|
+
providerMetadata = run.providerMetadata;
|
|
709
|
+
toolCalls = run.toolCalls;
|
|
710
|
+
finalText = await applyCompletionOutputPolicy({
|
|
711
|
+
outputPolicy: deps.runOutputPolicy,
|
|
712
|
+
text: finalText,
|
|
713
|
+
mode: outputMode === "buffer" ? "enforce" : "audit",
|
|
714
|
+
runtimePlan,
|
|
715
|
+
agent: body.agent,
|
|
716
|
+
runId: run.loopRunId,
|
|
717
|
+
sessionId,
|
|
718
|
+
signal,
|
|
719
|
+
});
|
|
720
|
+
if (!signal.aborted && finalText) {
|
|
721
|
+
await stream.writeSSE({ data: sseChunk(completionId, { content: finalText }) });
|
|
722
|
+
}
|
|
723
|
+
if (!signal.aborted) {
|
|
724
|
+
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop", { loop_run_id: run.loopRunId }) });
|
|
725
|
+
await stream.writeSSE({ data: "[DONE]" });
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
catch (err) {
|
|
729
|
+
if ((err instanceof DOMException && err.name === "AbortError") || signal.aborted) {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
const guardrailError = guardrailErrorEnvelope(err);
|
|
733
|
+
const notFound = modelNotFoundEnvelope(err, runModel, body.agent);
|
|
734
|
+
if (guardrailError) {
|
|
735
|
+
finalText = guardrailError.message;
|
|
736
|
+
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop", { error: guardrailError }) });
|
|
737
|
+
await stream.writeSSE({ data: "[DONE]" });
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
if (notFound) {
|
|
741
|
+
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop", { error: notFound }) });
|
|
742
|
+
await stream.writeSSE({ data: "[DONE]" });
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
const loopError = loopRuntimeErrorEnvelope(err);
|
|
746
|
+
if (loopError) {
|
|
747
|
+
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop", { error: loopError }) });
|
|
748
|
+
await stream.writeSSE({ data: "[DONE]" });
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
throw err;
|
|
752
|
+
}
|
|
753
|
+
finally {
|
|
754
|
+
await persistAssistantMessage(sessionStore, sessionId, assistantMsgId, finalText, toolCalls);
|
|
755
|
+
try {
|
|
756
|
+
deps.onCompletionFinished?.({
|
|
757
|
+
usage: runUsage,
|
|
758
|
+
model: runModel,
|
|
759
|
+
resolvedModel,
|
|
760
|
+
agent: body.agent,
|
|
761
|
+
sessionId: sessionId ?? undefined,
|
|
762
|
+
user: body.user,
|
|
763
|
+
providerMetadata,
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
catch { /* never fail on callback */ }
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
async function runNonStreamingProjectLoopCompletion(c, options) {
|
|
770
|
+
const { deps, body, completionId, agentConfig, projectLoop, aiMessages, extraSystemParts, runtimeContext, runtimeInvocation, sessionStore, sessionId, runtimePlan, executionRoute, activatedSkills, } = options;
|
|
771
|
+
const contextTrust = normalizeRuntimeContextTrustMode(options.contextTrust ?? deps.getConfig()?.settings?.contextTrust);
|
|
764
772
|
let assistantMsgId = null;
|
|
765
773
|
let runUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
766
774
|
let runModel = agentConfigForModelPrimary(agentConfig, deps.getConfig()?.settings).model ?? "polpo";
|