@polpo-ai/server 0.10.7 → 0.10.9
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/loop-contract.test.js +3 -12
- package/dist/loop-contract.test.js.map +1 -1
- package/dist/loop-dsl-compiler.d.ts +6 -0
- package/dist/loop-dsl-compiler.d.ts.map +1 -0
- package/dist/loop-dsl-compiler.js +135 -0
- package/dist/loop-dsl-compiler.js.map +1 -0
- package/dist/loop-dsl-compiler.test.d.ts +2 -0
- package/dist/loop-dsl-compiler.test.d.ts.map +1 -0
- package/dist/loop-dsl-compiler.test.js +136 -0
- package/dist/loop-dsl-compiler.test.js.map +1 -0
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +0 -4
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/completions-provider-tools.test.d.ts +2 -0
- package/dist/routes/completions-provider-tools.test.d.ts.map +1 -0
- package/dist/routes/completions-provider-tools.test.js +148 -0
- package/dist/routes/completions-provider-tools.test.js.map +1 -0
- package/dist/routes/completions.d.ts.map +1 -1
- package/dist/routes/completions.js +65 -107
- package/dist/routes/completions.js.map +1 -1
- package/dist/routes/loops.d.ts.map +1 -1
- package/dist/routes/loops.js +31 -1
- package/dist/routes/loops.js.map +1 -1
- package/dist/schemas.d.ts +0 -72
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +0 -17
- package/dist/schemas.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
const { generateTextMock } = vi.hoisted(() => ({
|
|
3
|
+
generateTextMock: vi.fn(),
|
|
4
|
+
}));
|
|
5
|
+
vi.mock("ai", () => ({
|
|
6
|
+
generateText: generateTextMock,
|
|
7
|
+
streamText: vi.fn(),
|
|
8
|
+
jsonSchema: (schema) => schema,
|
|
9
|
+
}));
|
|
10
|
+
import { completionRoutes } from "./completions.js";
|
|
11
|
+
describe("completionRoutes provider-executed tools", () => {
|
|
12
|
+
function makeDeps() {
|
|
13
|
+
return {
|
|
14
|
+
getAgents: async () => [{
|
|
15
|
+
name: "researcher",
|
|
16
|
+
model: "test",
|
|
17
|
+
assignedLoops: ["research-loop"],
|
|
18
|
+
defaultLoop: "research-loop",
|
|
19
|
+
allowedTools: ["search_web"],
|
|
20
|
+
}],
|
|
21
|
+
getConfig: () => ({}),
|
|
22
|
+
getMemoryStore: () => null,
|
|
23
|
+
getSessionStore: () => null,
|
|
24
|
+
getStore: () => null,
|
|
25
|
+
emit: () => { },
|
|
26
|
+
buildAgentPrompt: () => "You are a researcher.",
|
|
27
|
+
resolveAgentModel: async () => ({
|
|
28
|
+
model: {
|
|
29
|
+
id: "test",
|
|
30
|
+
provider: "test",
|
|
31
|
+
aiModel: "test-model",
|
|
32
|
+
contextWindow: 100_000,
|
|
33
|
+
maxTokens: 1024,
|
|
34
|
+
},
|
|
35
|
+
providerOptions: undefined,
|
|
36
|
+
}),
|
|
37
|
+
resolveAgentTools: async () => ({
|
|
38
|
+
tools: [],
|
|
39
|
+
extraAiTools: {
|
|
40
|
+
search_web: { type: "provider-defined", id: "gateway.perplexity_search" },
|
|
41
|
+
},
|
|
42
|
+
executor: async (name) => {
|
|
43
|
+
throw new Error(`provider tool "${name}" should not be executed locally`);
|
|
44
|
+
},
|
|
45
|
+
}),
|
|
46
|
+
getProjectLoop: async (name) => ({
|
|
47
|
+
name,
|
|
48
|
+
context: "shared",
|
|
49
|
+
start: "research",
|
|
50
|
+
steps: {
|
|
51
|
+
research: {
|
|
52
|
+
type: "agent",
|
|
53
|
+
systemPrompt: "Search the web, then summarize the result.",
|
|
54
|
+
tools: ["search_web"],
|
|
55
|
+
maxTurns: 3,
|
|
56
|
+
next: "end",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
it("feeds provider-executed tool results back through AI SDK responseMessages", async () => {
|
|
63
|
+
let secondTurnMessages;
|
|
64
|
+
const searchOutput = {
|
|
65
|
+
results: [{ title: "Polpo", url: "https://polpo.sh", snippet: "Agent backend" }],
|
|
66
|
+
id: "search_1",
|
|
67
|
+
};
|
|
68
|
+
generateTextMock
|
|
69
|
+
.mockResolvedValueOnce({
|
|
70
|
+
text: "",
|
|
71
|
+
usage: { inputTokens: 10, outputTokens: 2, totalTokens: 12 },
|
|
72
|
+
providerMetadata: undefined,
|
|
73
|
+
toolCalls: [{
|
|
74
|
+
toolCallId: "call_search",
|
|
75
|
+
toolName: "search_web",
|
|
76
|
+
input: { query: "Polpo agent backend" },
|
|
77
|
+
providerExecuted: true,
|
|
78
|
+
}],
|
|
79
|
+
toolResults: [{
|
|
80
|
+
type: "tool-result",
|
|
81
|
+
toolCallId: "call_search",
|
|
82
|
+
toolName: "search_web",
|
|
83
|
+
output: searchOutput,
|
|
84
|
+
providerExecuted: true,
|
|
85
|
+
}],
|
|
86
|
+
responseMessages: [{
|
|
87
|
+
role: "assistant",
|
|
88
|
+
content: [
|
|
89
|
+
{
|
|
90
|
+
type: "tool-call",
|
|
91
|
+
toolCallId: "call_search",
|
|
92
|
+
toolName: "search_web",
|
|
93
|
+
input: { query: "Polpo agent backend" },
|
|
94
|
+
providerExecuted: true,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "tool-result",
|
|
98
|
+
toolCallId: "call_search",
|
|
99
|
+
toolName: "search_web",
|
|
100
|
+
output: { type: "json", value: searchOutput },
|
|
101
|
+
providerExecuted: true,
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
}],
|
|
105
|
+
})
|
|
106
|
+
.mockImplementationOnce(async (args) => {
|
|
107
|
+
secondTurnMessages = args.messages;
|
|
108
|
+
return {
|
|
109
|
+
text: "Polpo is an agent backend.",
|
|
110
|
+
usage: { inputTokens: 20, outputTokens: 5, totalTokens: 25 },
|
|
111
|
+
providerMetadata: undefined,
|
|
112
|
+
toolCalls: [],
|
|
113
|
+
toolResults: [],
|
|
114
|
+
responseMessages: [{
|
|
115
|
+
role: "assistant",
|
|
116
|
+
content: "Polpo is an agent backend.",
|
|
117
|
+
}],
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
const app = completionRoutes(() => makeDeps());
|
|
121
|
+
const res = await app.request("/", {
|
|
122
|
+
method: "POST",
|
|
123
|
+
headers: { "content-type": "application/json" },
|
|
124
|
+
body: JSON.stringify({
|
|
125
|
+
agent: "researcher",
|
|
126
|
+
messages: [{ role: "user", content: "Research Polpo" }],
|
|
127
|
+
}),
|
|
128
|
+
});
|
|
129
|
+
expect(res.status).toBe(200);
|
|
130
|
+
const json = await res.json();
|
|
131
|
+
expect(json.choices[0].message.content).toBe("Polpo is an agent backend.");
|
|
132
|
+
expect(generateTextMock).toHaveBeenCalledTimes(2);
|
|
133
|
+
expect(secondTurnMessages).toEqual(expect.arrayContaining([
|
|
134
|
+
expect.objectContaining({
|
|
135
|
+
role: "assistant",
|
|
136
|
+
content: expect.arrayContaining([
|
|
137
|
+
expect.objectContaining({
|
|
138
|
+
type: "tool-result",
|
|
139
|
+
toolName: "search_web",
|
|
140
|
+
providerExecuted: true,
|
|
141
|
+
}),
|
|
142
|
+
]),
|
|
143
|
+
}),
|
|
144
|
+
]));
|
|
145
|
+
expect(secondTurnMessages?.filter((message) => message.role === "tool" && JSON.stringify(message).includes("search_web"))).toEqual([]);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=completions-provider-tools.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completions-provider-tools.test.js","sourceRoot":"","sources":["../../src/routes/completions-provider-tools.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7C,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC1B,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IACnB,YAAY,EAAE,gBAAgB;IAC9B,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,UAAU,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM;CACxC,CAAC,CAAC,CAAC;AAEJ,OAAO,EAAE,gBAAgB,EAA4B,MAAM,kBAAkB,CAAC;AAE9E,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACxD,SAAS,QAAQ;QACf,OAAO;YACL,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;oBACtB,IAAI,EAAE,YAAY;oBAClB,KAAK,EAAE,MAAM;oBACb,aAAa,EAAE,CAAC,eAAe,CAAC;oBAChC,WAAW,EAAE,eAAe;oBAC5B,YAAY,EAAE,CAAC,YAAY,CAAC;iBAC7B,CAAC;YACF,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;YACrB,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;YAC1B,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI;YAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI;YACpB,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;YACd,gBAAgB,EAAE,GAAG,EAAE,CAAC,uBAAuB;YAC/C,iBAAiB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;gBAC9B,KAAK,EAAE;oBACL,EAAE,EAAE,MAAM;oBACV,QAAQ,EAAE,MAAM;oBAChB,OAAO,EAAE,YAAY;oBACrB,aAAa,EAAE,OAAO;oBACtB,SAAS,EAAE,IAAI;iBAChB;gBACD,eAAe,EAAE,SAAS;aAC3B,CAAC;YACF,iBAAiB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;gBAC9B,KAAK,EAAE,EAAE;gBACT,YAAY,EAAE;oBACZ,UAAU,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,2BAA2B,EAAE;iBAC1E;gBACD,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;oBACvB,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,kCAAkC,CAAC,CAAC;gBAC5E,CAAC;aACF,CAAC;YACF,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC/B,IAAI;gBACJ,OAAO,EAAE,QAAQ;gBACjB,KAAK,EAAE,UAAU;gBACjB,KAAK,EAAE;oBACL,QAAQ,EAAE;wBACR,IAAI,EAAE,OAAO;wBACb,YAAY,EAAE,4CAA4C;wBAC1D,KAAK,EAAE,CAAC,YAAY,CAAC;wBACrB,QAAQ,EAAE,CAAC;wBACX,IAAI,EAAE,KAAK;qBACZ;iBACF;aACF,CAAC;SACH,CAAC;IACJ,CAAC;IAED,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,IAAI,kBAAqC,CAAC;QAC1C,MAAM,YAAY,GAAG;YACnB,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;YAChF,EAAE,EAAE,UAAU;SACf,CAAC;QAEF,gBAAgB;aACb,qBAAqB,CAAC;YACrB,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE;YAC5D,gBAAgB,EAAE,SAAS;YAC3B,SAAS,EAAE,CAAC;oBACV,UAAU,EAAE,aAAa;oBACzB,QAAQ,EAAE,YAAY;oBACtB,KAAK,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE;oBACvC,gBAAgB,EAAE,IAAI;iBACvB,CAAC;YACF,WAAW,EAAE,CAAC;oBACZ,IAAI,EAAE,aAAa;oBACnB,UAAU,EAAE,aAAa;oBACzB,QAAQ,EAAE,YAAY;oBACtB,MAAM,EAAE,YAAY;oBACpB,gBAAgB,EAAE,IAAI;iBACvB,CAAC;YACF,gBAAgB,EAAE,CAAC;oBACjB,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,WAAW;4BACjB,UAAU,EAAE,aAAa;4BACzB,QAAQ,EAAE,YAAY;4BACtB,KAAK,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE;4BACvC,gBAAgB,EAAE,IAAI;yBACvB;wBACD;4BACE,IAAI,EAAE,aAAa;4BACnB,UAAU,EAAE,aAAa;4BACzB,QAAQ,EAAE,YAAY;4BACtB,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE;4BAC7C,gBAAgB,EAAE,IAAI;yBACvB;qBACF;iBACF,CAAC;SACH,CAAC;aACD,sBAAsB,CAAC,KAAK,EAAE,IAAS,EAAE,EAAE;YAC1C,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC;YACnC,OAAO;gBACL,IAAI,EAAE,4BAA4B;gBAClC,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE;gBAC5D,gBAAgB,EAAE,SAAS;gBAC3B,SAAS,EAAE,EAAE;gBACb,WAAW,EAAE,EAAE;gBACf,gBAAgB,EAAE,CAAC;wBACjB,IAAI,EAAE,WAAW;wBACjB,OAAO,EAAE,4BAA4B;qBACtC,CAAC;aACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEL,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE;YACjC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,YAAY;gBACnB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;aACxD,CAAC;SACH,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAS,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC3E,MAAM,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAElD,MAAM,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAChC,MAAM,CAAC,eAAe,CAAC;YACrB,MAAM,CAAC,gBAAgB,CAAC;gBACtB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,MAAM,CAAC,eAAe,CAAC;oBAC9B,MAAM,CAAC,gBAAgB,CAAC;wBACtB,IAAI,EAAE,aAAa;wBACnB,QAAQ,EAAE,YAAY;wBACtB,gBAAgB,EAAE,IAAI;qBACvB,CAAC;iBACH,CAAC;aACH,CAAC;SACH,CAAC,CACH,CAAC;QACF,MAAM,CACJ,kBAAkB,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CACrC,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAC1E,CACF,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completions.d.ts","sourceRoot":"","sources":["../../src/routes/completions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAGhE,OAAO,EAcL,KAAK,aAAa,EAGlB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EAEvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAwC,KAAK,aAAa,EAA2B,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"completions.d.ts","sourceRoot":"","sources":["../../src/routes/completions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAGhE,OAAO,EAcL,KAAK,aAAa,EAGlB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EAEvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAwC,KAAK,aAAa,EAA2B,MAAM,IAAI,CAAC;AA+kBvG;;;GAGG;AACH,UAAU,iBAAiB;IACzB,mFAAmF;IACnF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,CAAC;IACrB,cAAc,EAAE,MAAM,GAAG,CAAC;IAC1B,eAAe,EAAE,MAAM,GAAG,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,CAAC;IACpB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IACzC,wIAAwI;IACxI,iBAAiB,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,iBAAiB,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;QAC3E,KAAK,EAAE,iBAAiB,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACvC,CAAC,CAAC;IACH,yDAAyD;IACzD,gBAAgB,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjE;;;;;;;;;gEAS4D;IAC5D,iBAAiB,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC;QAC/C,KAAK,EAAE,GAAG,EAAE,CAAC;QACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3E,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACpC,CAAC,CAAC;IACH,uHAAuH;IACvH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACrE,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,YAAY,GAAG,SAAS,CAAC;IACjD,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,aAAa,GAAG,SAAS,CAAC;IACnD,4KAA4K;IAC5K,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC5B,KAAK,EAAE;YAAE,WAAW,CAAC,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7E,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB;mFAC2E;QAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC5C,KAAK,IAAI,CAAC;IACX,0EAA0E;IAC1E,0BAA0B,CAAC,EAAE,MAAM,OAAO,CAAC;QACzC,YAAY,EAAE,MAAM,CAAC;QACrB,KAAK,EAAE,iBAAiB,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACtC,KAAK,EAAE,GAAG,EAAE,CAAC;QACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3E,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;KAC1C,CAAC,CAAC;CACJ;AAmgBD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,IAAI,EAAE,mBAAmB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,aAAa,CAAC,CAuCzB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,mBAAmB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,WAAW,CA8/BpG"}
|
|
@@ -61,6 +61,55 @@ function redactVaultToolCalls(toolCalls) {
|
|
|
61
61
|
return { ...tc, arguments: args };
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
|
+
async function appendModelResponseMessages(messages, result, turnText, toolCalls) {
|
|
65
|
+
try {
|
|
66
|
+
const responseMessages = await result.responseMessages;
|
|
67
|
+
if (Array.isArray(responseMessages) && responseMessages.length > 0) {
|
|
68
|
+
messages.push(...responseMessages);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Older/partial AI SDK results can still be represented manually below.
|
|
74
|
+
}
|
|
75
|
+
const assistantContent = [];
|
|
76
|
+
if (turnText)
|
|
77
|
+
assistantContent.push({ type: "text", text: turnText });
|
|
78
|
+
for (const tc of toolCalls) {
|
|
79
|
+
assistantContent.push({
|
|
80
|
+
type: "tool-call",
|
|
81
|
+
toolCallId: tc.toolCallId,
|
|
82
|
+
toolName: tc.toolName,
|
|
83
|
+
input: tc.input,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
messages.push({
|
|
87
|
+
role: "assistant",
|
|
88
|
+
content: assistantContent.length === 1 && assistantContent[0].type === "text"
|
|
89
|
+
? turnText
|
|
90
|
+
: assistantContent,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function indexToolResultsByCallId(toolResults) {
|
|
94
|
+
const indexed = new Map();
|
|
95
|
+
for (const result of toolResults ?? []) {
|
|
96
|
+
if (result?.toolCallId)
|
|
97
|
+
indexed.set(result.toolCallId, result);
|
|
98
|
+
}
|
|
99
|
+
return indexed;
|
|
100
|
+
}
|
|
101
|
+
function recordProviderToolCall(toolCallsAccum, call, toolResults) {
|
|
102
|
+
const toolResult = toolResults.get(call.toolCallId);
|
|
103
|
+
const output = toolResult?.output ?? toolResult?.result ?? toolResult?.error;
|
|
104
|
+
toolCallsAccum.push({
|
|
105
|
+
id: call.toolCallId,
|
|
106
|
+
name: call.toolName,
|
|
107
|
+
arguments: call.input,
|
|
108
|
+
result: output === undefined ? undefined : typeof output === "string" ? output : JSON.stringify(output),
|
|
109
|
+
state: toolResult?.type === "tool-error" || toolResult?.error ? "error" : "completed",
|
|
110
|
+
providerExecuted: true,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
64
113
|
// ── Zod Schemas ────────────────────────────────────────────────────────
|
|
65
114
|
/** OpenAI-compatible content part (text, image_url, or file reference). */
|
|
66
115
|
const contentPartSchema = z.discriminatedUnion("type", [
|
|
@@ -651,44 +700,15 @@ async function runAgentStepCompletion(options) {
|
|
|
651
700
|
lastProviderMetadata = genResult.providerMetadata;
|
|
652
701
|
}
|
|
653
702
|
catch { /* best effort */ }
|
|
654
|
-
|
|
655
|
-
if (turnText)
|
|
656
|
-
assistantContent.push({ type: "text", text: turnText });
|
|
657
|
-
for (const tc of genResult.toolCalls) {
|
|
658
|
-
assistantContent.push({
|
|
659
|
-
type: "tool-call",
|
|
660
|
-
toolCallId: tc.toolCallId,
|
|
661
|
-
toolName: tc.toolName,
|
|
662
|
-
input: tc.input,
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
messages.push({
|
|
666
|
-
role: "assistant",
|
|
667
|
-
content: assistantContent.length === 1 && assistantContent[0].type === "text"
|
|
668
|
-
? turnText
|
|
669
|
-
: assistantContent,
|
|
670
|
-
});
|
|
703
|
+
await appendModelResponseMessages(messages, genResult, turnText, genResult.toolCalls);
|
|
671
704
|
finalText += turnText;
|
|
672
705
|
if (genResult.toolCalls.length === 0)
|
|
673
706
|
break;
|
|
674
|
-
const providerToolResults =
|
|
675
|
-
for (const tr of genResult.toolResults ?? []) {
|
|
676
|
-
providerToolResults.set(tr.toolCallId, tr);
|
|
677
|
-
}
|
|
707
|
+
const providerToolResults = indexToolResultsByCallId(genResult.toolResults);
|
|
678
708
|
for (const call of genResult.toolCalls) {
|
|
679
709
|
const callArgs = call.input;
|
|
680
710
|
if (providerToolNames.has(call.toolName)) {
|
|
681
|
-
|
|
682
|
-
const value = tr?.output ?? tr?.result ?? null;
|
|
683
|
-
messages.push({
|
|
684
|
-
role: "tool",
|
|
685
|
-
content: [{
|
|
686
|
-
type: "tool-result",
|
|
687
|
-
toolCallId: call.toolCallId,
|
|
688
|
-
toolName: call.toolName,
|
|
689
|
-
output: { type: "json", value },
|
|
690
|
-
}],
|
|
691
|
-
});
|
|
711
|
+
recordProviderToolCall(toolCallsAccum, call, providerToolResults);
|
|
692
712
|
continue;
|
|
693
713
|
}
|
|
694
714
|
const result = await resolvedTools.executor(call.toolName, callArgs);
|
|
@@ -1484,26 +1504,7 @@ export function completionRoutes(getDeps, apiKeys) {
|
|
|
1484
1504
|
lastProviderMetadata = (await result.providerMetadata);
|
|
1485
1505
|
}
|
|
1486
1506
|
catch { /* best effort */ }
|
|
1487
|
-
|
|
1488
|
-
// AI SDK format: assistant message with text + tool calls
|
|
1489
|
-
const assistantContent = [];
|
|
1490
|
-
if (turnText) {
|
|
1491
|
-
assistantContent.push({ type: "text", text: turnText });
|
|
1492
|
-
}
|
|
1493
|
-
for (const tc of toolCalls) {
|
|
1494
|
-
assistantContent.push({
|
|
1495
|
-
type: "tool-call",
|
|
1496
|
-
toolCallId: tc.toolCallId,
|
|
1497
|
-
toolName: tc.toolName,
|
|
1498
|
-
input: tc.input,
|
|
1499
|
-
});
|
|
1500
|
-
}
|
|
1501
|
-
messages.push({
|
|
1502
|
-
role: "assistant",
|
|
1503
|
-
content: assistantContent.length === 1 && assistantContent[0].type === "text"
|
|
1504
|
-
? turnText
|
|
1505
|
-
: assistantContent,
|
|
1506
|
-
});
|
|
1507
|
+
await appendModelResponseMessages(messages, result, turnText, toolCalls);
|
|
1507
1508
|
finalText += turnText;
|
|
1508
1509
|
if (toolCalls.length === 0)
|
|
1509
1510
|
break;
|
|
@@ -1630,16 +1631,14 @@ export function completionRoutes(getDeps, apiKeys) {
|
|
|
1630
1631
|
await stream.writeSSE({ data: "[DONE]" });
|
|
1631
1632
|
return; // finally block will persist whatever finalText we have
|
|
1632
1633
|
}
|
|
1633
|
-
// Provider tools (extraAiTools) are executed by the SDK / gateway
|
|
1634
|
-
//
|
|
1635
|
-
//
|
|
1636
|
-
// forward the result message into history for the next turn.
|
|
1634
|
+
// Provider tools (extraAiTools) are executed by the SDK / gateway.
|
|
1635
|
+
// Their tool results are already preserved in responseMessages,
|
|
1636
|
+
// so only record them for observability and skip local dispatch.
|
|
1637
1637
|
const providerToolNames = new Set(Object.keys(extraAiTools ?? {}));
|
|
1638
|
-
|
|
1638
|
+
let providerToolResults = new Map();
|
|
1639
1639
|
try {
|
|
1640
1640
|
const settled = (await result.toolResults);
|
|
1641
|
-
|
|
1642
|
-
providerToolResults.set(tr.toolCallId, tr);
|
|
1641
|
+
providerToolResults = indexToolResultsByCallId(settled);
|
|
1643
1642
|
}
|
|
1644
1643
|
catch { /* best effort */ }
|
|
1645
1644
|
for (const call of toolCalls) {
|
|
@@ -1648,17 +1647,7 @@ export function completionRoutes(getDeps, apiKeys) {
|
|
|
1648
1647
|
break;
|
|
1649
1648
|
const callArgs = call.input;
|
|
1650
1649
|
if (providerToolNames.has(call.toolName)) {
|
|
1651
|
-
|
|
1652
|
-
const value = tr?.output ?? tr?.result ?? null;
|
|
1653
|
-
messages.push({
|
|
1654
|
-
role: "tool",
|
|
1655
|
-
content: [{
|
|
1656
|
-
type: "tool-result",
|
|
1657
|
-
toolCallId: call.toolCallId,
|
|
1658
|
-
toolName: call.toolName,
|
|
1659
|
-
output: { type: "json", value },
|
|
1660
|
-
}],
|
|
1661
|
-
});
|
|
1650
|
+
recordProviderToolCall(toolCallsAccum, call, providerToolResults);
|
|
1662
1651
|
continue;
|
|
1663
1652
|
}
|
|
1664
1653
|
// Notify client that a tool is being called
|
|
@@ -1812,25 +1801,7 @@ export function completionRoutes(getDeps, apiKeys) {
|
|
|
1812
1801
|
lastProviderMetadata = genResult.providerMetadata;
|
|
1813
1802
|
}
|
|
1814
1803
|
catch { /* best effort */ }
|
|
1815
|
-
|
|
1816
|
-
const assistantContent = [];
|
|
1817
|
-
if (turnText) {
|
|
1818
|
-
assistantContent.push({ type: "text", text: turnText });
|
|
1819
|
-
}
|
|
1820
|
-
for (const tc of genResult.toolCalls) {
|
|
1821
|
-
assistantContent.push({
|
|
1822
|
-
type: "tool-call",
|
|
1823
|
-
toolCallId: tc.toolCallId,
|
|
1824
|
-
toolName: tc.toolName,
|
|
1825
|
-
input: tc.input,
|
|
1826
|
-
});
|
|
1827
|
-
}
|
|
1828
|
-
messages.push({
|
|
1829
|
-
role: "assistant",
|
|
1830
|
-
content: assistantContent.length === 1 && assistantContent[0].type === "text"
|
|
1831
|
-
? turnText
|
|
1832
|
-
: assistantContent,
|
|
1833
|
-
});
|
|
1804
|
+
await appendModelResponseMessages(messages, genResult, turnText, genResult.toolCalls);
|
|
1834
1805
|
finalText += turnText;
|
|
1835
1806
|
const toolCalls = genResult.toolCalls;
|
|
1836
1807
|
if (toolCalls.length === 0)
|
|
@@ -2002,28 +1973,15 @@ export function completionRoutes(getDeps, apiKeys) {
|
|
|
2002
1973
|
}
|
|
2003
1974
|
// Note: finally block persists finalText + toolCallsAccum
|
|
2004
1975
|
}
|
|
2005
|
-
// Provider tools (extraAiTools) are executed by the SDK / gateway
|
|
2006
|
-
//
|
|
2007
|
-
//
|
|
1976
|
+
// Provider tools (extraAiTools) are executed by the SDK / gateway.
|
|
1977
|
+
// Their tool results are already preserved in responseMessages,
|
|
1978
|
+
// so only record them for observability and skip local dispatch.
|
|
2008
1979
|
const providerToolNames = new Set(Object.keys(extraAiTools ?? {}));
|
|
2009
|
-
const providerToolResults =
|
|
2010
|
-
for (const tr of genResult.toolResults ?? []) {
|
|
2011
|
-
providerToolResults.set(tr.toolCallId, tr);
|
|
2012
|
-
}
|
|
1980
|
+
const providerToolResults = indexToolResultsByCallId(genResult.toolResults);
|
|
2013
1981
|
for (const call of toolCalls) {
|
|
2014
1982
|
const callArgs = call.input;
|
|
2015
1983
|
if (providerToolNames.has(call.toolName)) {
|
|
2016
|
-
|
|
2017
|
-
const value = tr?.output ?? tr?.result ?? null;
|
|
2018
|
-
messages.push({
|
|
2019
|
-
role: "tool",
|
|
2020
|
-
content: [{
|
|
2021
|
-
type: "tool-result",
|
|
2022
|
-
toolCallId: call.toolCallId,
|
|
2023
|
-
toolName: call.toolName,
|
|
2024
|
-
output: { type: "json", value },
|
|
2025
|
-
}],
|
|
2026
|
-
});
|
|
1984
|
+
recordProviderToolCall(toolCallsAccum, call, providerToolResults);
|
|
2027
1985
|
continue;
|
|
2028
1986
|
}
|
|
2029
1987
|
const result = await effectiveToolExecutor(call.toolName, callArgs);
|