@polpo-ai/server 0.2.2 → 0.2.3
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.d.ts +60 -0
- package/dist/routes/completions.d.ts.map +1 -0
- package/dist/routes/completions.js +798 -0
- package/dist/routes/completions.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export { scheduleRoutes } from "./routes/schedules.js";
|
|
|
19
19
|
export { watcherRoutes } from "./routes/watchers.js";
|
|
20
20
|
export { stateRoutes } from "./routes/state.js";
|
|
21
21
|
export { healthRoutes } from "./routes/health.js";
|
|
22
|
+
export { completionRoutes, type CompletionRouteDeps } from "./routes/completions.js";
|
|
22
23
|
export type { TaskRouteDeps, MissionRouteDeps, PlaybookRouteDeps, ApprovalRouteDeps, ChatRouteDeps, VaultRouteDeps, PeerRouteDeps, NotificationRouteDeps, ScheduleRouteDeps, WatcherRouteDeps, StateRouteDeps, ConfigRouteDeps, AuthRouteDeps, FileRouteDeps, SkillRouteDeps, AgentRouteDeps, } from "./deps.js";
|
|
23
24
|
export { validateParams, instantiatePlaybook } from "./playbook-utils.js";
|
|
24
25
|
export type { PlaybookParameter, PlaybookDefinition, ValidationResult } from "./playbook-utils.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGrF,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,GACf,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ export { scheduleRoutes } from "./routes/schedules.js";
|
|
|
20
20
|
export { watcherRoutes } from "./routes/watchers.js";
|
|
21
21
|
export { stateRoutes } from "./routes/state.js";
|
|
22
22
|
export { healthRoutes } from "./routes/health.js";
|
|
23
|
+
export { completionRoutes } from "./routes/completions.js";
|
|
23
24
|
// Playbook utilities (pure logic, edge-compatible)
|
|
24
25
|
export { validateParams, instantiatePlaybook } from "./playbook-utils.js";
|
|
25
26
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAA4B,MAAM,yBAAyB,CAAC;AAsBrF,mDAAmD;AACnD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI-compatible chat completions endpoint.
|
|
3
|
+
*
|
|
4
|
+
* POST /v1/chat/completions
|
|
5
|
+
*
|
|
6
|
+
* This is Polpo's primary conversational interface. It accepts OpenAI-format
|
|
7
|
+
* messages, runs the full agentic tool loop internally, and returns
|
|
8
|
+
* responses in OpenAI-compatible format — both streaming (SSE) and non-streaming.
|
|
9
|
+
*
|
|
10
|
+
* Supports two modes:
|
|
11
|
+
* - **Orchestrator mode** (default): The caller talks to Polpo. Polpo has 100+
|
|
12
|
+
* orchestration tools (tasks, missions, agents, vault, etc.).
|
|
13
|
+
* - **Agent-direct mode** (`agent` field): The caller talks directly to a
|
|
14
|
+
* specific agent. The agent uses its own model, system prompt, and coding
|
|
15
|
+
* tools — bypassing the orchestrator entirely.
|
|
16
|
+
*/
|
|
17
|
+
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
18
|
+
/**
|
|
19
|
+
* Completion route dependencies.
|
|
20
|
+
*
|
|
21
|
+
* The consumer provides LLM resolution and tool creation — this allows
|
|
22
|
+
* the route to run on any runtime (Node.js with full tools, or edge with no tools).
|
|
23
|
+
*/
|
|
24
|
+
export interface CompletionRouteDeps {
|
|
25
|
+
getAgents: () => Promise<any[]>;
|
|
26
|
+
getConfig: () => any;
|
|
27
|
+
getMemoryStore: () => any;
|
|
28
|
+
getSessionStore: () => any;
|
|
29
|
+
getStore: () => any;
|
|
30
|
+
emit: (event: string, data: any) => void;
|
|
31
|
+
/** Resolve agent model + streaming options. */
|
|
32
|
+
resolveAgentModel: (agentConfig: any, settingsReasoning?: string) => Promise<{
|
|
33
|
+
model: any;
|
|
34
|
+
streamOpts: any;
|
|
35
|
+
}>;
|
|
36
|
+
/** Build agent system prompt for conversational mode. */
|
|
37
|
+
buildAgentPrompt: (agentConfig: any) => string;
|
|
38
|
+
/** Create tools + executor for the agent. Return empty arrays for chat-only. */
|
|
39
|
+
resolveAgentTools: (agentConfig: any) => Promise<{
|
|
40
|
+
tools: any[];
|
|
41
|
+
executor: (name: string, args: Record<string, unknown>) => Promise<string>;
|
|
42
|
+
}>;
|
|
43
|
+
/** LLM streaming function (streamSimple from pi-ai). */
|
|
44
|
+
streamLLM: (model: any, opts: {
|
|
45
|
+
systemPrompt: string;
|
|
46
|
+
messages: any[];
|
|
47
|
+
tools: any[];
|
|
48
|
+
}, streamOpts: any) => any;
|
|
49
|
+
/** Orchestrator mode support (optional — returns 501 if not provided). */
|
|
50
|
+
resolveOrchestratorContext?: () => Promise<{
|
|
51
|
+
systemPrompt: string;
|
|
52
|
+
model: any;
|
|
53
|
+
streamOpts: any;
|
|
54
|
+
tools: any[];
|
|
55
|
+
executor: (name: string, args: Record<string, unknown>) => Promise<string>;
|
|
56
|
+
isInteractive: (name: string) => boolean;
|
|
57
|
+
}>;
|
|
58
|
+
}
|
|
59
|
+
export declare function completionRoutes(getDeps: () => CompletionRouteDeps, apiKeys?: string[]): OpenAPIHono;
|
|
60
|
+
//# sourceMappingURL=completions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completions.d.ts","sourceRoot":"","sources":["../../src/routes/completions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AA+QhE;;;;;GAKG;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,+CAA+C;IAC/C,iBAAiB,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,iBAAiB,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAC9G,yDAAyD;IACzD,gBAAgB,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,MAAM,CAAC;IAC/C,gFAAgF;IAChF,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;KAC5E,CAAC,CAAC;IACH,wDAAwD;IACxD,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,GAAG,EAAE,CAAC;QAAC,KAAK,EAAE,GAAG,EAAE,CAAA;KAAE,EAAE,UAAU,EAAE,GAAG,KAAK,GAAG,CAAC;IAC/G,0EAA0E;IAC1E,0BAA0B,CAAC,EAAE,MAAM,OAAO,CAAC;QACzC,YAAY,EAAE,MAAM,CAAC;QACrB,KAAK,EAAE,GAAG,CAAC;QACX,UAAU,EAAE,GAAG,CAAC;QAChB,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;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,mBAAmB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,WAAW,CA2jBpG"}
|
|
@@ -0,0 +1,798 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI-compatible chat completions endpoint.
|
|
3
|
+
*
|
|
4
|
+
* POST /v1/chat/completions
|
|
5
|
+
*
|
|
6
|
+
* This is Polpo's primary conversational interface. It accepts OpenAI-format
|
|
7
|
+
* messages, runs the full agentic tool loop internally, and returns
|
|
8
|
+
* responses in OpenAI-compatible format — both streaming (SSE) and non-streaming.
|
|
9
|
+
*
|
|
10
|
+
* Supports two modes:
|
|
11
|
+
* - **Orchestrator mode** (default): The caller talks to Polpo. Polpo has 100+
|
|
12
|
+
* orchestration tools (tasks, missions, agents, vault, etc.).
|
|
13
|
+
* - **Agent-direct mode** (`agent` field): The caller talks directly to a
|
|
14
|
+
* specific agent. The agent uses its own model, system prompt, and coding
|
|
15
|
+
* tools — bypassing the orchestrator entirely.
|
|
16
|
+
*/
|
|
17
|
+
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
|
|
18
|
+
import { streamSSE } from "hono/streaming";
|
|
19
|
+
import { nanoid } from "nanoid";
|
|
20
|
+
import { agentMemoryScope } from "@polpo-ai/core";
|
|
21
|
+
const MAX_TURNS = 20;
|
|
22
|
+
/** Tools that write/modify files — emit file:changed after successful execution */
|
|
23
|
+
const FILE_WRITE_TOOLS = {
|
|
24
|
+
write_file: "created",
|
|
25
|
+
edit_file: "modified",
|
|
26
|
+
};
|
|
27
|
+
/** Emit file:changed if a file-writing tool succeeded */
|
|
28
|
+
function emitFileChanged(toolName, args, result, emit) {
|
|
29
|
+
const action = FILE_WRITE_TOOLS[toolName];
|
|
30
|
+
if (!action || result.startsWith("Error:"))
|
|
31
|
+
return;
|
|
32
|
+
const path = args.path;
|
|
33
|
+
if (!path)
|
|
34
|
+
return;
|
|
35
|
+
const dir = path.includes("/") ? path.substring(0, path.lastIndexOf("/")) : ".";
|
|
36
|
+
emit("file:changed", { path, dir, action, source: "chat" });
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Redact sensitive credential values from vault tool call arguments before persistence.
|
|
40
|
+
* Returns a sanitized copy — original is NOT mutated.
|
|
41
|
+
*/
|
|
42
|
+
function redactVaultToolCalls(toolCalls) {
|
|
43
|
+
// @ts-ignore — ToolCallInfo shape preserved via duck typing
|
|
44
|
+
return toolCalls.map(tc => {
|
|
45
|
+
if ((tc.name !== "set_vault_entry" && tc.name !== "update_vault_credentials") || !tc.arguments)
|
|
46
|
+
return tc;
|
|
47
|
+
const args = { ...tc.arguments };
|
|
48
|
+
if (args.credentials && typeof args.credentials === "object") {
|
|
49
|
+
// Replace each credential value with a redacted marker, preserve keys for display
|
|
50
|
+
const redacted = {};
|
|
51
|
+
for (const key of Object.keys(args.credentials)) {
|
|
52
|
+
redacted[key] = "[REDACTED]";
|
|
53
|
+
}
|
|
54
|
+
args.credentials = redacted;
|
|
55
|
+
}
|
|
56
|
+
return { ...tc, arguments: args };
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// ── Zod Schemas ────────────────────────────────────────────────────────
|
|
60
|
+
/** OpenAI-compatible content part (text or image_url). */
|
|
61
|
+
const contentPartSchema = z.discriminatedUnion("type", [
|
|
62
|
+
z.object({ type: z.literal("text"), text: z.string() }),
|
|
63
|
+
z.object({
|
|
64
|
+
type: z.literal("image_url"),
|
|
65
|
+
image_url: z.object({
|
|
66
|
+
url: z.string().openapi({ description: "Data URL (data:image/…;base64,…) or HTTPS URL" }),
|
|
67
|
+
detail: z.enum(["auto", "low", "high"]).optional(),
|
|
68
|
+
}),
|
|
69
|
+
}),
|
|
70
|
+
]);
|
|
71
|
+
const messageSchema = z.object({
|
|
72
|
+
role: z.enum(["system", "user", "assistant"]).openapi({
|
|
73
|
+
description: "Message role. System messages are appended as additional context (Polpo has its own system prompt).",
|
|
74
|
+
}),
|
|
75
|
+
content: z.union([
|
|
76
|
+
z.string(),
|
|
77
|
+
z.array(contentPartSchema),
|
|
78
|
+
]).openapi({ description: "Message content — plain string or array of content parts (text / image_url)" }),
|
|
79
|
+
});
|
|
80
|
+
const completionRequestSchema = z.object({
|
|
81
|
+
messages: z.array(messageSchema).min(1).openapi({
|
|
82
|
+
description: "Conversation messages in OpenAI format",
|
|
83
|
+
}),
|
|
84
|
+
stream: z.boolean().optional().default(false).openapi({
|
|
85
|
+
description: "If true, returns an SSE stream of OpenAI-format chunks. If false, returns a complete response.",
|
|
86
|
+
}),
|
|
87
|
+
model: z.string().optional().openapi({
|
|
88
|
+
description: "Ignored. Polpo uses its configured orchestrator model (or the agent's model in agent-direct mode).",
|
|
89
|
+
}),
|
|
90
|
+
temperature: z.number().optional().openapi({
|
|
91
|
+
description: "Ignored. Reserved for future use.",
|
|
92
|
+
}),
|
|
93
|
+
max_tokens: z.number().int().optional().openapi({
|
|
94
|
+
description: "Ignored. Reserved for future use.",
|
|
95
|
+
}),
|
|
96
|
+
agent: z.string().optional().openapi({
|
|
97
|
+
description: "Target a specific agent by name for direct conversation. Uses the agent's own model, system prompt, and coding tools instead of the orchestrator. Omit to talk to the orchestrator (default).",
|
|
98
|
+
}),
|
|
99
|
+
project: z.string().optional().openapi({
|
|
100
|
+
description: "Deprecated. Ignored.",
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
const completionResponseSchema = z.object({
|
|
104
|
+
id: z.string().openapi({ description: "Unique completion ID (chatcmpl-...)" }),
|
|
105
|
+
object: z.literal("chat.completion"),
|
|
106
|
+
created: z.number().int().openapi({ description: "Unix timestamp" }),
|
|
107
|
+
model: z.literal("polpo"),
|
|
108
|
+
choices: z.array(z.object({
|
|
109
|
+
index: z.number().int(),
|
|
110
|
+
message: z.object({
|
|
111
|
+
role: z.literal("assistant"),
|
|
112
|
+
content: z.string(),
|
|
113
|
+
}),
|
|
114
|
+
finish_reason: z.enum(["stop", "length", "ask_user", "mission_preview", "vault_preview"]),
|
|
115
|
+
})),
|
|
116
|
+
usage: z.object({
|
|
117
|
+
prompt_tokens: z.number().int(),
|
|
118
|
+
completion_tokens: z.number().int(),
|
|
119
|
+
total_tokens: z.number().int(),
|
|
120
|
+
}),
|
|
121
|
+
});
|
|
122
|
+
const errorResponseSchema = z.object({
|
|
123
|
+
error: z.object({
|
|
124
|
+
message: z.string(),
|
|
125
|
+
type: z.string(),
|
|
126
|
+
code: z.string().optional(),
|
|
127
|
+
}),
|
|
128
|
+
});
|
|
129
|
+
// ── Route definition ───────────────────────────────────────────────────
|
|
130
|
+
const chatCompletionsRoute = createRoute({
|
|
131
|
+
method: "post",
|
|
132
|
+
path: "/",
|
|
133
|
+
tags: ["Chat Completions"],
|
|
134
|
+
summary: "Chat completions",
|
|
135
|
+
description: "Polpo's primary conversational interface. Send messages in OpenAI format, receive responses in OpenAI format. Polpo runs its full 37-tool agentic loop internally — you describe what you need, Polpo handles the rest. Supports streaming (SSE) and non-streaming modes.",
|
|
136
|
+
request: {
|
|
137
|
+
body: {
|
|
138
|
+
content: {
|
|
139
|
+
"application/json": {
|
|
140
|
+
schema: completionRequestSchema,
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
responses: {
|
|
146
|
+
200: {
|
|
147
|
+
content: {
|
|
148
|
+
"application/json": {
|
|
149
|
+
schema: completionResponseSchema,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
description: "Chat completion response (non-streaming). When stream=true, returns text/event-stream with OpenAI-format chunks ending with data: [DONE].",
|
|
153
|
+
},
|
|
154
|
+
400: {
|
|
155
|
+
content: {
|
|
156
|
+
"application/json": {
|
|
157
|
+
schema: errorResponseSchema,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
description: "Invalid request (missing messages or no project available)",
|
|
161
|
+
},
|
|
162
|
+
401: {
|
|
163
|
+
content: {
|
|
164
|
+
"application/json": {
|
|
165
|
+
schema: errorResponseSchema,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
description: "Invalid API key",
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
// ── Helpers ────────────────────────────────────────────────────────────
|
|
173
|
+
/** Extract plain text from a content field (string or content-part array). */
|
|
174
|
+
function extractText(content) {
|
|
175
|
+
if (typeof content === "string")
|
|
176
|
+
return content;
|
|
177
|
+
return content
|
|
178
|
+
.filter((p) => p.type === "text")
|
|
179
|
+
.map((p) => p.text)
|
|
180
|
+
.join("\n");
|
|
181
|
+
}
|
|
182
|
+
/** Convert OpenAI-format content to pi-ai UserMessage content. */
|
|
183
|
+
function toPiContent(content) {
|
|
184
|
+
if (typeof content === "string")
|
|
185
|
+
return content;
|
|
186
|
+
// Check if there are any image parts
|
|
187
|
+
const hasImages = content.some((p) => p.type === "image_url");
|
|
188
|
+
if (!hasImages) {
|
|
189
|
+
// Text-only array → flatten to plain string
|
|
190
|
+
return content.map((p) => p.text).join("\n");
|
|
191
|
+
}
|
|
192
|
+
// Mixed content → convert to pi-ai TextContent | ImageContent array
|
|
193
|
+
return content.map((p) => {
|
|
194
|
+
if (p.type === "text") {
|
|
195
|
+
return { type: "text", text: p.text };
|
|
196
|
+
}
|
|
197
|
+
// image_url → ImageContent
|
|
198
|
+
const url = p.image_url.url;
|
|
199
|
+
// data:image/png;base64,... → extract mimeType and base64 data
|
|
200
|
+
const match = url.match(/^data:([^;]+);base64,(.+)$/);
|
|
201
|
+
if (match) {
|
|
202
|
+
return { type: "image", data: match[2], mimeType: match[1] };
|
|
203
|
+
}
|
|
204
|
+
// HTTPS URL — pass as-is (pi-ai may or may not support external URLs depending on provider)
|
|
205
|
+
return { type: "image", data: url, mimeType: "image/png" };
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function convertMessages(messages) {
|
|
209
|
+
const piMessages = [];
|
|
210
|
+
const extraSystemParts = [];
|
|
211
|
+
for (const msg of messages) {
|
|
212
|
+
if (msg.role === "system") {
|
|
213
|
+
extraSystemParts.push(extractText(msg.content));
|
|
214
|
+
}
|
|
215
|
+
else if (msg.role === "user") {
|
|
216
|
+
piMessages.push({ role: "user", content: toPiContent(msg.content), timestamp: Date.now() });
|
|
217
|
+
}
|
|
218
|
+
else if (msg.role === "assistant") {
|
|
219
|
+
piMessages.push({
|
|
220
|
+
role: "user",
|
|
221
|
+
content: `[Previous assistant response]\n${extractText(msg.content)}\n[End previous response]`,
|
|
222
|
+
timestamp: Date.now(),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return { piMessages, extraSystemParts };
|
|
227
|
+
}
|
|
228
|
+
function sseChunk(id, delta, finishReason = null, extra) {
|
|
229
|
+
return JSON.stringify({
|
|
230
|
+
id,
|
|
231
|
+
object: "chat.completion.chunk",
|
|
232
|
+
created: Math.floor(Date.now() / 1000),
|
|
233
|
+
model: "polpo",
|
|
234
|
+
choices: [{
|
|
235
|
+
index: 0,
|
|
236
|
+
delta,
|
|
237
|
+
finish_reason: finishReason,
|
|
238
|
+
...extra,
|
|
239
|
+
}],
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
function completionResponse(id, content, promptTokens, completionTokens) {
|
|
243
|
+
return {
|
|
244
|
+
id,
|
|
245
|
+
object: "chat.completion",
|
|
246
|
+
created: Math.floor(Date.now() / 1000),
|
|
247
|
+
model: "polpo",
|
|
248
|
+
choices: [{
|
|
249
|
+
index: 0,
|
|
250
|
+
message: { role: "assistant", content },
|
|
251
|
+
finish_reason: "stop",
|
|
252
|
+
}],
|
|
253
|
+
usage: {
|
|
254
|
+
prompt_tokens: promptTokens,
|
|
255
|
+
completion_tokens: completionTokens,
|
|
256
|
+
total_tokens: promptTokens + completionTokens,
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
export function completionRoutes(getDeps, apiKeys) {
|
|
261
|
+
const app = new OpenAPIHono();
|
|
262
|
+
app.openapi(chatCompletionsRoute, async (c) => {
|
|
263
|
+
const deps = getDeps();
|
|
264
|
+
// ── Auth ──
|
|
265
|
+
if (apiKeys && apiKeys.length > 0) {
|
|
266
|
+
const auth = c.req.header("Authorization");
|
|
267
|
+
const token = auth?.startsWith("Bearer ") ? auth.slice(7) : null;
|
|
268
|
+
if (!token || !apiKeys.includes(token)) {
|
|
269
|
+
return c.json({ error: { message: "Invalid API key", type: "invalid_request_error", code: "invalid_api_key" } }, 401);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// ── Parse body ──
|
|
273
|
+
const body = c.req.valid("json");
|
|
274
|
+
const agentMode = !!body.agent;
|
|
275
|
+
// ── Resolve effective context (orchestrator vs agent-direct) ──
|
|
276
|
+
let fullSystemPrompt;
|
|
277
|
+
let m;
|
|
278
|
+
let streamOpts;
|
|
279
|
+
let effectiveTools;
|
|
280
|
+
let effectiveToolExecutor;
|
|
281
|
+
let isInteractiveFn;
|
|
282
|
+
const { piMessages, extraSystemParts } = convertMessages(body.messages);
|
|
283
|
+
if (agentMode) {
|
|
284
|
+
// ── Agent-direct mode ──
|
|
285
|
+
const agents = await deps.getAgents();
|
|
286
|
+
const agentConfig = agents.find((a) => a.name === body.agent);
|
|
287
|
+
if (!agentConfig) {
|
|
288
|
+
return c.json({ error: { message: `Agent "${body.agent}" not found`, type: "invalid_request_error", code: "agent_not_found" } }, 404);
|
|
289
|
+
}
|
|
290
|
+
// Build system prompt via dep
|
|
291
|
+
const agentSystemPrompt = deps.buildAgentPrompt(agentConfig);
|
|
292
|
+
const conversationalPreamble = [
|
|
293
|
+
"You are now in interactive conversation mode with the user.",
|
|
294
|
+
"Unlike task execution, you should engage in dialogue: ask clarifying questions,",
|
|
295
|
+
"explain your reasoning, and wait for user input when needed.",
|
|
296
|
+
"You still have access to all your coding tools to help the user.",
|
|
297
|
+
].join("\n");
|
|
298
|
+
const basePrompt = `${conversationalPreamble}\n\n${agentSystemPrompt}`;
|
|
299
|
+
fullSystemPrompt = extraSystemParts.length > 0
|
|
300
|
+
? `${basePrompt}\n\n## Additional context from caller\n\n${extraSystemParts.join("\n\n")}`
|
|
301
|
+
: basePrompt;
|
|
302
|
+
// Inject agent memory
|
|
303
|
+
const memoryStore = deps.getMemoryStore();
|
|
304
|
+
const agentMemory = await memoryStore?.get(agentMemoryScope(agentConfig.name));
|
|
305
|
+
if (agentMemory) {
|
|
306
|
+
fullSystemPrompt += `\n\n## Your persistent memory\n\n${agentMemory}`;
|
|
307
|
+
}
|
|
308
|
+
// Resolve model via dep
|
|
309
|
+
const reasoning = agentConfig.reasoning ?? deps.getConfig()?.settings?.reasoning;
|
|
310
|
+
const resolved = await deps.resolveAgentModel(agentConfig, reasoning);
|
|
311
|
+
m = resolved.model;
|
|
312
|
+
streamOpts = resolved.streamOpts;
|
|
313
|
+
// Resolve tools via dep
|
|
314
|
+
const { tools, executor } = await deps.resolveAgentTools(agentConfig);
|
|
315
|
+
effectiveTools = tools;
|
|
316
|
+
effectiveToolExecutor = executor;
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
// ── Orchestrator mode (default) ──
|
|
320
|
+
if (!deps.resolveOrchestratorContext) {
|
|
321
|
+
return c.json({
|
|
322
|
+
error: { message: "Orchestrator mode is not available. Use agent-direct mode by specifying the 'agent' field.", type: "invalid_request_error", code: "orchestrator_unavailable" },
|
|
323
|
+
}, 501);
|
|
324
|
+
}
|
|
325
|
+
const ctx = await deps.resolveOrchestratorContext();
|
|
326
|
+
fullSystemPrompt = extraSystemParts.length > 0
|
|
327
|
+
? `${ctx.systemPrompt}\n\n## Additional context from caller\n\n${extraSystemParts.join("\n\n")}`
|
|
328
|
+
: ctx.systemPrompt;
|
|
329
|
+
m = ctx.model;
|
|
330
|
+
streamOpts = ctx.streamOpts;
|
|
331
|
+
effectiveTools = ctx.tools;
|
|
332
|
+
effectiveToolExecutor = ctx.executor;
|
|
333
|
+
isInteractiveFn = ctx.isInteractive;
|
|
334
|
+
}
|
|
335
|
+
const completionId = `chatcmpl-${nanoid(24)}`;
|
|
336
|
+
// ── Session persistence ──
|
|
337
|
+
const sessionStore = deps.getSessionStore();
|
|
338
|
+
const rawSessionHeader = c.req.header("x-session-id") ?? null;
|
|
339
|
+
const forceNewSession = rawSessionHeader === "new";
|
|
340
|
+
let sessionId = forceNewSession ? null : rawSessionHeader;
|
|
341
|
+
if (sessionStore) {
|
|
342
|
+
if (!sessionId) {
|
|
343
|
+
const firstUserMsg = body.messages.find(m => m.role === "user");
|
|
344
|
+
const sessionTitle = firstUserMsg ? extractText(firstUserMsg.content).slice(0, 60) : undefined;
|
|
345
|
+
// Agent scope: orchestrator sessions use null, agent sessions use the agent name
|
|
346
|
+
const agentScope = agentMode ? body.agent : null;
|
|
347
|
+
if (forceNewSession) {
|
|
348
|
+
// Client explicitly requested a new session — skip recency heuristic
|
|
349
|
+
sessionId = await sessionStore.create(sessionTitle, agentScope ?? undefined);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
// Reuse latest session if recent (< 30 min), scoped by agent
|
|
353
|
+
const latest = await sessionStore.getLatestSession(agentScope);
|
|
354
|
+
const timeout = 30 * 60 * 1000;
|
|
355
|
+
if (latest && Date.now() - new Date(latest.updatedAt).getTime() < timeout) {
|
|
356
|
+
sessionId = latest.id;
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
sessionId = await sessionStore.create(sessionTitle, agentScope ?? undefined);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// Persist user message (only the last one — earlier messages are already persisted)
|
|
364
|
+
const lastUserMsg = [...body.messages].reverse().find(m => m.role === "user");
|
|
365
|
+
if (lastUserMsg && sessionId) {
|
|
366
|
+
await sessionStore.addMessage(sessionId, "user", extractText(lastUserMsg.content));
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// Expose session ID to the client so it can track which session is active
|
|
370
|
+
if (sessionId) {
|
|
371
|
+
c.header("x-session-id", sessionId);
|
|
372
|
+
}
|
|
373
|
+
if (body.stream) {
|
|
374
|
+
// ── Streaming mode ──
|
|
375
|
+
return streamSSE(c, async (stream) => {
|
|
376
|
+
// Abort controller: cancelled when the client disconnects (closes SSE)
|
|
377
|
+
const abortController = new AbortController();
|
|
378
|
+
stream.onAbort(() => { abortController.abort(); });
|
|
379
|
+
await stream.writeSSE({ data: sseChunk(completionId, { role: "assistant" }) });
|
|
380
|
+
// Reserve a placeholder message in the store BEFORE streaming.
|
|
381
|
+
// This guarantees the assistant message exists even if the client disconnects.
|
|
382
|
+
let assistantMsgId = null;
|
|
383
|
+
if (sessionStore && sessionId) {
|
|
384
|
+
const placeholder = await sessionStore.addMessage(sessionId, "assistant", "");
|
|
385
|
+
assistantMsgId = placeholder.id;
|
|
386
|
+
}
|
|
387
|
+
const messages = [...piMessages];
|
|
388
|
+
let finalText = "";
|
|
389
|
+
const toolCallsAccum = [];
|
|
390
|
+
try {
|
|
391
|
+
for (let turn = 0; turn < MAX_TURNS; turn++) {
|
|
392
|
+
// Bail out early if the client already disconnected
|
|
393
|
+
if (abortController.signal.aborted)
|
|
394
|
+
break;
|
|
395
|
+
const piStream = deps.streamLLM(m, {
|
|
396
|
+
systemPrompt: fullSystemPrompt,
|
|
397
|
+
messages,
|
|
398
|
+
tools: effectiveTools,
|
|
399
|
+
}, { ...streamOpts, signal: abortController.signal });
|
|
400
|
+
let turnText = "";
|
|
401
|
+
let streamError;
|
|
402
|
+
for await (const event of piStream) {
|
|
403
|
+
if (abortController.signal.aborted)
|
|
404
|
+
break;
|
|
405
|
+
if (event.type === "text_delta") {
|
|
406
|
+
turnText += event.delta;
|
|
407
|
+
await stream.writeSSE({ data: sseChunk(completionId, { content: event.delta }) });
|
|
408
|
+
}
|
|
409
|
+
else if (event.type === "toolcall_start") {
|
|
410
|
+
// Emit early "preparing" signal — the LLM has started generating a tool call
|
|
411
|
+
// but arguments are not yet complete. Lets the UI show immediate feedback.
|
|
412
|
+
const block = event.partial.content[event.contentIndex];
|
|
413
|
+
if (block?.type === "toolCall") {
|
|
414
|
+
await stream.writeSSE({
|
|
415
|
+
data: sseChunk(completionId, {}, null, {
|
|
416
|
+
tool_call: { id: block.id, name: block.name, state: "preparing" },
|
|
417
|
+
}),
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
else if (event.type === "error") {
|
|
422
|
+
streamError = event.error?.errorMessage ?? "Model returned an error";
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// If aborted, stop the loop — skip error/tool processing
|
|
426
|
+
if (abortController.signal.aborted) {
|
|
427
|
+
finalText += turnText;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
if (streamError) {
|
|
431
|
+
finalText += `\n\nError: ${streamError}`;
|
|
432
|
+
await stream.writeSSE({ data: sseChunk(completionId, { content: `\n\nError: ${streamError}` }) });
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
const response = await piStream.result();
|
|
436
|
+
messages.push(response);
|
|
437
|
+
finalText += turnText;
|
|
438
|
+
const toolCalls = response.content.filter((cc) => cc.type === "toolCall");
|
|
439
|
+
if (toolCalls.length === 0)
|
|
440
|
+
break;
|
|
441
|
+
// Check for interactive tools — only in orchestrator mode (agents don't have interactive tools)
|
|
442
|
+
const interactiveCall = agentMode ? undefined : toolCalls.find((tc) => isInteractiveFn?.(tc.name));
|
|
443
|
+
if (interactiveCall) {
|
|
444
|
+
// Persist the interactive tool call so it survives session reload
|
|
445
|
+
toolCallsAccum.push({
|
|
446
|
+
id: interactiveCall.id,
|
|
447
|
+
name: interactiveCall.name,
|
|
448
|
+
arguments: interactiveCall.arguments,
|
|
449
|
+
state: "interrupted",
|
|
450
|
+
});
|
|
451
|
+
if (interactiveCall.name === "ask_user") {
|
|
452
|
+
const questions = interactiveCall.arguments?.questions ?? [];
|
|
453
|
+
await stream.writeSSE({
|
|
454
|
+
data: sseChunk(completionId, {}, "ask_user", { ask_user: { questions } }),
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
else if (interactiveCall.name === "create_mission") {
|
|
458
|
+
const args = interactiveCall.arguments;
|
|
459
|
+
let missionData;
|
|
460
|
+
try {
|
|
461
|
+
missionData = JSON.parse(args.data);
|
|
462
|
+
}
|
|
463
|
+
catch {
|
|
464
|
+
missionData = args.data;
|
|
465
|
+
}
|
|
466
|
+
await stream.writeSSE({
|
|
467
|
+
data: sseChunk(completionId, {}, "mission_preview", {
|
|
468
|
+
mission_preview: {
|
|
469
|
+
name: args.name,
|
|
470
|
+
data: missionData,
|
|
471
|
+
prompt: args.prompt,
|
|
472
|
+
},
|
|
473
|
+
}),
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
else if (interactiveCall.name === "set_vault_entry") {
|
|
477
|
+
const args = interactiveCall.arguments;
|
|
478
|
+
await stream.writeSSE({
|
|
479
|
+
data: sseChunk(completionId, {}, "vault_preview", {
|
|
480
|
+
vault_preview: {
|
|
481
|
+
agent: args.agent,
|
|
482
|
+
service: args.service,
|
|
483
|
+
type: args.type,
|
|
484
|
+
label: args.label,
|
|
485
|
+
credentials: args.credentials,
|
|
486
|
+
},
|
|
487
|
+
}),
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
else if (interactiveCall.name === "open_file") {
|
|
491
|
+
const args = interactiveCall.arguments;
|
|
492
|
+
await stream.writeSSE({
|
|
493
|
+
data: sseChunk(completionId, {}, "open_file", {
|
|
494
|
+
open_file: {
|
|
495
|
+
path: args.path,
|
|
496
|
+
},
|
|
497
|
+
}),
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
else if (interactiveCall.name === "navigate_to") {
|
|
501
|
+
const args = interactiveCall.arguments;
|
|
502
|
+
await stream.writeSSE({
|
|
503
|
+
data: sseChunk(completionId, {}, "navigate_to", {
|
|
504
|
+
navigate_to: {
|
|
505
|
+
target: args.target,
|
|
506
|
+
id: args.id,
|
|
507
|
+
name: args.name,
|
|
508
|
+
path: args.path,
|
|
509
|
+
highlight: args.highlight,
|
|
510
|
+
},
|
|
511
|
+
}),
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
else if (interactiveCall.name === "open_tab") {
|
|
515
|
+
const args = interactiveCall.arguments;
|
|
516
|
+
await stream.writeSSE({
|
|
517
|
+
data: sseChunk(completionId, {}, "open_tab", {
|
|
518
|
+
open_tab: {
|
|
519
|
+
url: args.url,
|
|
520
|
+
label: args.label,
|
|
521
|
+
},
|
|
522
|
+
}),
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
await stream.writeSSE({ data: "[DONE]" });
|
|
526
|
+
return; // finally block will persist whatever finalText we have
|
|
527
|
+
}
|
|
528
|
+
for (const call of toolCalls) {
|
|
529
|
+
// Stop executing tools if client disconnected
|
|
530
|
+
if (abortController.signal.aborted)
|
|
531
|
+
break;
|
|
532
|
+
// Notify client that a tool is being called
|
|
533
|
+
await stream.writeSSE({
|
|
534
|
+
data: sseChunk(completionId, {}, null, {
|
|
535
|
+
tool_call: { id: call.id, name: call.name, arguments: call.arguments, state: "calling" },
|
|
536
|
+
}),
|
|
537
|
+
});
|
|
538
|
+
const result = await effectiveToolExecutor(call.name, call.arguments);
|
|
539
|
+
const isError = result.startsWith("Error:");
|
|
540
|
+
emitFileChanged(call.name, call.arguments, result, deps.emit);
|
|
541
|
+
// Accumulate for persistence
|
|
542
|
+
toolCallsAccum.push({
|
|
543
|
+
id: call.id,
|
|
544
|
+
name: call.name,
|
|
545
|
+
arguments: call.arguments,
|
|
546
|
+
result,
|
|
547
|
+
state: isError ? "error" : "completed",
|
|
548
|
+
});
|
|
549
|
+
// Notify client with tool result (skip if aborted mid-tool)
|
|
550
|
+
if (!abortController.signal.aborted) {
|
|
551
|
+
await stream.writeSSE({
|
|
552
|
+
data: sseChunk(completionId, {}, null, {
|
|
553
|
+
tool_call: { id: call.id, name: call.name, result, state: isError ? "error" : "completed" },
|
|
554
|
+
}),
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
messages.push({
|
|
558
|
+
role: "toolResult",
|
|
559
|
+
toolCallId: call.id,
|
|
560
|
+
toolName: call.name,
|
|
561
|
+
content: [{ type: "text", text: result }],
|
|
562
|
+
isError,
|
|
563
|
+
timestamp: Date.now(),
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
if (!abortController.signal.aborted) {
|
|
568
|
+
await stream.writeSSE({ data: sseChunk(completionId, {}, "stop") });
|
|
569
|
+
await stream.writeSSE({ data: "[DONE]" });
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
catch (err) {
|
|
573
|
+
// Suppress AbortError — expected when client disconnects
|
|
574
|
+
if (!(err instanceof DOMException && err.name === "AbortError") && !abortController.signal.aborted) {
|
|
575
|
+
throw err;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
finally {
|
|
579
|
+
// Always persist the assistant response — even on disconnect.
|
|
580
|
+
// SECURITY: Redact vault credentials before persisting to SQLite
|
|
581
|
+
const safeToolCalls = redactVaultToolCalls(toolCallsAccum);
|
|
582
|
+
if (sessionStore && sessionId && assistantMsgId) {
|
|
583
|
+
if (finalText.trim()) {
|
|
584
|
+
await sessionStore.updateMessage(sessionId, assistantMsgId, finalText.trim(), safeToolCalls);
|
|
585
|
+
}
|
|
586
|
+
// If finalText is empty (LLM never responded), remove the empty placeholder
|
|
587
|
+
// by setting content to a marker that indicates an interrupted response
|
|
588
|
+
else {
|
|
589
|
+
await sessionStore.updateMessage(sessionId, assistantMsgId, "[Response interrupted]", safeToolCalls);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
// ── Non-streaming mode ──
|
|
597
|
+
// Reserve placeholder so the message is visible even if the request is interrupted
|
|
598
|
+
let assistantMsgId = null;
|
|
599
|
+
if (sessionStore && sessionId) {
|
|
600
|
+
const placeholder = await sessionStore.addMessage(sessionId, "assistant", "");
|
|
601
|
+
assistantMsgId = placeholder.id;
|
|
602
|
+
}
|
|
603
|
+
const messages = [...piMessages];
|
|
604
|
+
let finalText = "";
|
|
605
|
+
const toolCallsAccum = [];
|
|
606
|
+
try {
|
|
607
|
+
for (let turn = 0; turn < MAX_TURNS; turn++) {
|
|
608
|
+
const piStream = deps.streamLLM(m, {
|
|
609
|
+
systemPrompt: fullSystemPrompt,
|
|
610
|
+
messages,
|
|
611
|
+
tools: effectiveTools,
|
|
612
|
+
}, streamOpts);
|
|
613
|
+
let turnText = "";
|
|
614
|
+
let streamError;
|
|
615
|
+
for await (const event of piStream) {
|
|
616
|
+
if (event.type === "text_delta") {
|
|
617
|
+
turnText += event.delta;
|
|
618
|
+
}
|
|
619
|
+
else if (event.type === "error") {
|
|
620
|
+
streamError = event.error?.errorMessage ?? "Model returned an error";
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (streamError) {
|
|
624
|
+
return c.json({ error: { message: streamError, type: "upstream_error" } }, 502);
|
|
625
|
+
}
|
|
626
|
+
const response = await piStream.result();
|
|
627
|
+
messages.push(response);
|
|
628
|
+
finalText += turnText;
|
|
629
|
+
const toolCalls = response.content.filter((cc) => cc.type === "toolCall");
|
|
630
|
+
if (toolCalls.length === 0)
|
|
631
|
+
break;
|
|
632
|
+
// Check for interactive tools — only in orchestrator mode (agents don't have interactive tools)
|
|
633
|
+
const interactiveCall = agentMode ? undefined : toolCalls.find((tc) => isInteractiveFn?.(tc.name));
|
|
634
|
+
if (interactiveCall) {
|
|
635
|
+
// Persist the interactive tool call so it survives session reload
|
|
636
|
+
toolCallsAccum.push({
|
|
637
|
+
id: interactiveCall.id,
|
|
638
|
+
name: interactiveCall.name,
|
|
639
|
+
arguments: interactiveCall.arguments,
|
|
640
|
+
state: "interrupted",
|
|
641
|
+
});
|
|
642
|
+
const baseResponse = {
|
|
643
|
+
id: completionId,
|
|
644
|
+
object: "chat.completion",
|
|
645
|
+
created: Math.floor(Date.now() / 1000),
|
|
646
|
+
model: "polpo",
|
|
647
|
+
usage: {
|
|
648
|
+
prompt_tokens: Math.ceil(fullSystemPrompt.length / 4),
|
|
649
|
+
completion_tokens: Math.ceil(finalText.length / 4),
|
|
650
|
+
total_tokens: Math.ceil(fullSystemPrompt.length / 4) + Math.ceil(finalText.length / 4),
|
|
651
|
+
},
|
|
652
|
+
};
|
|
653
|
+
if (interactiveCall.name === "ask_user") {
|
|
654
|
+
const questions = interactiveCall.arguments?.questions ?? [];
|
|
655
|
+
return c.json({
|
|
656
|
+
...baseResponse,
|
|
657
|
+
choices: [{
|
|
658
|
+
index: 0,
|
|
659
|
+
message: { role: "assistant", content: finalText },
|
|
660
|
+
finish_reason: "ask_user",
|
|
661
|
+
ask_user: { questions },
|
|
662
|
+
}],
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
if (interactiveCall.name === "create_mission") {
|
|
666
|
+
const args = interactiveCall.arguments;
|
|
667
|
+
let missionData;
|
|
668
|
+
try {
|
|
669
|
+
missionData = JSON.parse(args.data);
|
|
670
|
+
}
|
|
671
|
+
catch {
|
|
672
|
+
missionData = args.data;
|
|
673
|
+
}
|
|
674
|
+
return c.json({
|
|
675
|
+
...baseResponse,
|
|
676
|
+
choices: [{
|
|
677
|
+
index: 0,
|
|
678
|
+
message: { role: "assistant", content: finalText },
|
|
679
|
+
finish_reason: "mission_preview",
|
|
680
|
+
mission_preview: {
|
|
681
|
+
name: args.name,
|
|
682
|
+
data: missionData,
|
|
683
|
+
prompt: args.prompt,
|
|
684
|
+
},
|
|
685
|
+
}],
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
if (interactiveCall.name === "set_vault_entry") {
|
|
689
|
+
const args = interactiveCall.arguments;
|
|
690
|
+
return c.json({
|
|
691
|
+
...baseResponse,
|
|
692
|
+
choices: [{
|
|
693
|
+
index: 0,
|
|
694
|
+
message: { role: "assistant", content: finalText },
|
|
695
|
+
finish_reason: "vault_preview",
|
|
696
|
+
vault_preview: {
|
|
697
|
+
agent: args.agent,
|
|
698
|
+
service: args.service,
|
|
699
|
+
type: args.type,
|
|
700
|
+
label: args.label,
|
|
701
|
+
credentials: args.credentials,
|
|
702
|
+
},
|
|
703
|
+
}],
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
if (interactiveCall.name === "open_file") {
|
|
707
|
+
const args = interactiveCall.arguments;
|
|
708
|
+
return c.json({
|
|
709
|
+
...baseResponse,
|
|
710
|
+
choices: [{
|
|
711
|
+
index: 0,
|
|
712
|
+
message: { role: "assistant", content: finalText },
|
|
713
|
+
finish_reason: "open_file",
|
|
714
|
+
open_file: {
|
|
715
|
+
path: args.path,
|
|
716
|
+
},
|
|
717
|
+
}],
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
if (interactiveCall.name === "navigate_to") {
|
|
721
|
+
const args = interactiveCall.arguments;
|
|
722
|
+
return c.json({
|
|
723
|
+
...baseResponse,
|
|
724
|
+
choices: [{
|
|
725
|
+
index: 0,
|
|
726
|
+
message: { role: "assistant", content: finalText },
|
|
727
|
+
finish_reason: "navigate_to",
|
|
728
|
+
navigate_to: {
|
|
729
|
+
target: args.target,
|
|
730
|
+
id: args.id,
|
|
731
|
+
name: args.name,
|
|
732
|
+
path: args.path,
|
|
733
|
+
highlight: args.highlight,
|
|
734
|
+
},
|
|
735
|
+
}],
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
if (interactiveCall.name === "open_tab") {
|
|
739
|
+
const args = interactiveCall.arguments;
|
|
740
|
+
return c.json({
|
|
741
|
+
...baseResponse,
|
|
742
|
+
choices: [{
|
|
743
|
+
index: 0,
|
|
744
|
+
message: { role: "assistant", content: finalText },
|
|
745
|
+
finish_reason: "open_tab",
|
|
746
|
+
open_tab: {
|
|
747
|
+
url: args.url,
|
|
748
|
+
label: args.label,
|
|
749
|
+
},
|
|
750
|
+
}],
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
// Note: finally block persists finalText + toolCallsAccum
|
|
754
|
+
}
|
|
755
|
+
for (const call of toolCalls) {
|
|
756
|
+
const result = await effectiveToolExecutor(call.name, call.arguments);
|
|
757
|
+
const isError = result.startsWith("Error:");
|
|
758
|
+
emitFileChanged(call.name, call.arguments, result, deps.emit);
|
|
759
|
+
// Accumulate for persistence
|
|
760
|
+
toolCallsAccum.push({
|
|
761
|
+
id: call.id,
|
|
762
|
+
name: call.name,
|
|
763
|
+
arguments: call.arguments,
|
|
764
|
+
result,
|
|
765
|
+
state: isError ? "error" : "completed",
|
|
766
|
+
});
|
|
767
|
+
messages.push({
|
|
768
|
+
role: "toolResult",
|
|
769
|
+
toolCallId: call.id,
|
|
770
|
+
toolName: call.name,
|
|
771
|
+
content: [{ type: "text", text: result }],
|
|
772
|
+
isError,
|
|
773
|
+
timestamp: Date.now(),
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
const promptTokens = Math.ceil(fullSystemPrompt.length / 4);
|
|
778
|
+
const completionTokens = Math.ceil(finalText.length / 4);
|
|
779
|
+
return c.json(completionResponse(completionId, finalText, promptTokens, completionTokens));
|
|
780
|
+
}
|
|
781
|
+
finally {
|
|
782
|
+
// Always persist the final text + tool calls — even on early return (ask_user) or error
|
|
783
|
+
// SECURITY: Redact vault credentials before persisting to SQLite
|
|
784
|
+
const safeToolCalls = redactVaultToolCalls(toolCallsAccum);
|
|
785
|
+
if (sessionStore && sessionId && assistantMsgId) {
|
|
786
|
+
if (finalText.trim()) {
|
|
787
|
+
await sessionStore.updateMessage(sessionId, assistantMsgId, finalText.trim(), safeToolCalls);
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
await sessionStore.updateMessage(sessionId, assistantMsgId, "[Response interrupted]", safeToolCalls);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
return app;
|
|
797
|
+
}
|
|
798
|
+
//# sourceMappingURL=completions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completions.js","sourceRoot":"","sources":["../../src/routes/completions.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED