@spinabot/brigade 1.19.4 → 1.21.0
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/README.md +4 -3
- package/convex/config.d.ts +2 -2
- package/convex/schema.d.ts +4 -4
- package/dist/agents/agent-loop.d.ts.map +1 -1
- package/dist/agents/agent-loop.js +92 -22
- package/dist/agents/agent-loop.js.map +1 -1
- package/dist/agents/content-quality-retry.d.ts.map +1 -1
- package/dist/agents/content-quality-retry.js +3 -22
- package/dist/agents/content-quality-retry.js.map +1 -1
- package/dist/agents/error-classifier.d.ts.map +1 -1
- package/dist/agents/error-classifier.js +2 -0
- package/dist/agents/error-classifier.js.map +1 -1
- package/dist/agents/memory/extract.d.ts.map +1 -1
- package/dist/agents/memory/extract.js +11 -44
- package/dist/agents/memory/extract.js.map +1 -1
- package/dist/agents/model-resolution.d.ts.map +1 -1
- package/dist/agents/model-resolution.js +9 -3
- package/dist/agents/model-resolution.js.map +1 -1
- package/dist/agents/ollama-native/ollama-json.d.ts +6 -0
- package/dist/agents/ollama-native/ollama-json.d.ts.map +1 -0
- package/dist/agents/ollama-native/ollama-json.js +126 -0
- package/dist/agents/ollama-native/ollama-json.js.map +1 -0
- package/dist/agents/ollama-native/register.d.ts +12 -0
- package/dist/agents/ollama-native/register.d.ts.map +1 -0
- package/dist/agents/ollama-native/register.js +37 -0
- package/dist/agents/ollama-native/register.js.map +1 -0
- package/dist/agents/ollama-native/stream.d.ts +59 -0
- package/dist/agents/ollama-native/stream.d.ts.map +1 -0
- package/dist/agents/ollama-native/stream.js +532 -0
- package/dist/agents/ollama-native/stream.js.map +1 -0
- package/dist/agents/payload-mutators.d.ts +0 -21
- package/dist/agents/payload-mutators.d.ts.map +1 -1
- package/dist/agents/payload-mutators.js +0 -58
- package/dist/agents/payload-mutators.js.map +1 -1
- package/dist/agents/thinking-fallback.d.ts.map +1 -1
- package/dist/agents/thinking-fallback.js +32 -10
- package/dist/agents/thinking-fallback.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/cli/commands/connect.d.ts.map +1 -1
- package/dist/cli/commands/connect.js +31 -43
- package/dist/cli/commands/connect.js.map +1 -1
- package/dist/cli/commands/update.d.ts +0 -6
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +9 -124
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/program/build-program.d.ts.map +1 -1
- package/dist/cli/program/build-program.js +1 -5
- package/dist/cli/program/build-program.js.map +1 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +43 -25
- package/dist/core/server.js.map +1 -1
- package/dist/integrations/antigravity/transport.d.ts +29 -0
- package/dist/integrations/antigravity/transport.d.ts.map +1 -0
- package/dist/integrations/antigravity/transport.js +498 -0
- package/dist/integrations/antigravity/transport.js.map +1 -0
- package/dist/integrations/cli-login.d.ts +13 -0
- package/dist/integrations/cli-login.d.ts.map +1 -1
- package/dist/integrations/cli-login.js +29 -0
- package/dist/integrations/cli-login.js.map +1 -1
- package/dist/integrations/ollama.d.ts +29 -36
- package/dist/integrations/ollama.d.ts.map +1 -1
- package/dist/integrations/ollama.js +213 -78
- package/dist/integrations/ollama.js.map +1 -1
- package/dist/integrations/provider-discovery.d.ts +37 -0
- package/dist/integrations/provider-discovery.d.ts.map +1 -1
- package/dist/integrations/provider-discovery.js +102 -0
- package/dist/integrations/provider-discovery.js.map +1 -1
- package/dist/providers/catalog.d.ts +8 -1
- package/dist/providers/catalog.d.ts.map +1 -1
- package/dist/providers/catalog.js +29 -1
- package/dist/providers/catalog.js.map +1 -1
- package/dist/providers/validate-key.js +1 -1
- package/dist/storage/boot.d.ts.map +1 -1
- package/dist/storage/boot.js +2 -1
- package/dist/storage/boot.js.map +1 -1
- package/dist/storage/convex/index.d.ts.map +1 -1
- package/dist/storage/convex/index.js +15 -4
- package/dist/storage/convex/index.js.map +1 -1
- package/dist/system-prompt/guidance.d.ts.map +1 -1
- package/dist/system-prompt/guidance.js +2 -9
- package/dist/system-prompt/guidance.js.map +1 -1
- package/dist/ui/onboard-storage-mode.js +30 -4
- package/dist/ui/onboard-storage-mode.js.map +1 -1
- package/dist/ui/onboarding.d.ts.map +1 -1
- package/dist/ui/onboarding.js +150 -32
- package/dist/ui/onboarding.js.map +1 -1
- package/package.json +5 -2
- package/scripts/convex-push.mjs +47 -29
- package/dist/agents/tool-name-repair.d.ts +0 -28
- package/dist/agents/tool-name-repair.d.ts.map +0 -1
- package/dist/agents/tool-name-repair.js +0 -168
- package/dist/agents/tool-name-repair.js.map +0 -1
- package/dist/shared/reasoning-tags.d.ts +0 -14
- package/dist/shared/reasoning-tags.d.ts.map +0 -1
- package/dist/shared/reasoning-tags.js +0 -71
- package/dist/shared/reasoning-tags.js.map +0 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Tool } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { StreamFn } from "@earendil-works/pi-agent-core";
|
|
3
|
+
export declare const OLLAMA_NATIVE_BASE_URL = "http://127.0.0.1:11434";
|
|
4
|
+
interface OllamaChatMessage {
|
|
5
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
6
|
+
content: string;
|
|
7
|
+
images?: string[];
|
|
8
|
+
tool_calls?: OllamaWireToolCall[];
|
|
9
|
+
tool_name?: string;
|
|
10
|
+
}
|
|
11
|
+
interface OllamaWireToolCall {
|
|
12
|
+
function: {
|
|
13
|
+
name: string;
|
|
14
|
+
arguments: Record<string, unknown>;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
interface OllamaWireTool {
|
|
18
|
+
type: "function";
|
|
19
|
+
function: {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
parameters: Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
interface OllamaChatResponse {
|
|
26
|
+
model?: string;
|
|
27
|
+
message?: {
|
|
28
|
+
role?: string;
|
|
29
|
+
content?: string;
|
|
30
|
+
thinking?: string;
|
|
31
|
+
reasoning?: string;
|
|
32
|
+
tool_calls?: OllamaWireToolCall[];
|
|
33
|
+
};
|
|
34
|
+
done?: boolean;
|
|
35
|
+
done_reason?: string;
|
|
36
|
+
prompt_eval_count?: number;
|
|
37
|
+
eval_count?: number;
|
|
38
|
+
}
|
|
39
|
+
/** Strip trailing slashes and a trailing `/v1`, then append `/api/chat`. */
|
|
40
|
+
export declare function resolveOllamaChatUrl(baseUrl: string): string;
|
|
41
|
+
/** Convert Pi's message array + system prompt into Ollama chat messages. */
|
|
42
|
+
export declare function convertToOllamaMessages(messages: Array<{
|
|
43
|
+
role: string;
|
|
44
|
+
content: unknown;
|
|
45
|
+
toolName?: unknown;
|
|
46
|
+
}>, systemPrompt?: string): OllamaChatMessage[];
|
|
47
|
+
/** Map Pi `Tool[]` to Ollama's function-tool wire shape (schema passed through). */
|
|
48
|
+
export declare function extractOllamaTools(tools: Tool[] | undefined): OllamaWireTool[];
|
|
49
|
+
/** Line-buffered NDJSON reader. Skips blank/malformed lines (never fatal). */
|
|
50
|
+
export declare function parseNdjsonStream(reader: ReadableStreamDefaultReader<Uint8Array>): AsyncGenerator<OllamaChatResponse>;
|
|
51
|
+
/**
|
|
52
|
+
* Build a Pi `StreamFn` that streams a turn against Ollama's native /api/chat.
|
|
53
|
+
* The chat URL is resolved from the MODEL's baseUrl per call (so one registered
|
|
54
|
+
* transport serves every Ollama endpoint — local or remote). `defaultHeaders`
|
|
55
|
+
* merge under per-call `options.headers`.
|
|
56
|
+
*/
|
|
57
|
+
export declare function createOllamaStreamFn(defaultHeaders?: Record<string, string>): StreamFn;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../src/agents/ollama-native/stream.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAOX,IAAI,EAGJ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAQ9D,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AA8C/D,UAAU,iBAAiB;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,kBAAkB;IAC3B,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;CAC/D;AAED,UAAU,cAAc;IACvB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;CACrF;AAWD,UAAU,kBAAkB;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,kBAAkB,EAAE,CAAC;KAClC,CAAC;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5D;AAiDD,4EAA4E;AAC5E,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EACvE,YAAY,CAAC,EAAE,MAAM,GACnB,iBAAiB,EAAE,CAiCrB;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,GAAG,cAAc,EAAE,CAe9E;AA6DD,8EAA8E;AAC9E,wBAAuB,iBAAiB,CACvC,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,GAC7C,cAAc,CAAC,kBAAkB,CAAC,CA0BpC;AAcD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,QAAQ,CA8StF"}
|
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
// Native Ollama transport — talks to Ollama's own /api/chat endpoint instead of
|
|
2
|
+
// the OpenAI-compatible /v1 shim. The native endpoint runs the model's tool-aware
|
|
3
|
+
// chat template server-side and returns STRUCTURED `tool_calls` (plus native
|
|
4
|
+
// `thinking`), which the /v1 shim does not reliably do for local models. The
|
|
5
|
+
// producer maps the native NDJSON stream 1:1 onto pi-ai's
|
|
6
|
+
// `AssistantMessageEventStream`, so `api: "ollama"` models dispatch through this
|
|
7
|
+
// transport exactly like a Pi built-in provider.
|
|
8
|
+
//
|
|
9
|
+
// Shape: `createOllamaStreamFn(baseUrl)` returns a Pi `StreamFn`
|
|
10
|
+
// `(model, context, options) => AssistantMessageEventStream`. It returns the
|
|
11
|
+
// stream synchronously and fills it from an async producer, exactly as pi-ai's
|
|
12
|
+
// built-in providers do.
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { createAssistantMessageEventStream } from "@earendil-works/pi-ai";
|
|
15
|
+
import { classifyUrlForSsrf } from "../../infra/net/fetch-guard.js";
|
|
16
|
+
import { parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, } from "./ollama-json.js";
|
|
17
|
+
export const OLLAMA_NATIVE_BASE_URL = "http://127.0.0.1:11434";
|
|
18
|
+
const DEFAULT_NUM_CTX = 65536;
|
|
19
|
+
// Local Ollama needs no credential; discovery seeds a sentinel apiKey purely to
|
|
20
|
+
// satisfy Pi's "custom provider needs a key" requirement. Never send it as a
|
|
21
|
+
// Bearer token (it's not a secret; only real cloud keys go on the wire).
|
|
22
|
+
const LOCAL_SENTINEL_KEYS = new Set([
|
|
23
|
+
"ollama-local-no-auth-required",
|
|
24
|
+
"ollama-local",
|
|
25
|
+
"ollama",
|
|
26
|
+
]);
|
|
27
|
+
// Models Ollama rejected tools for this process (a text/vision-only model 400s
|
|
28
|
+
// with `"<model>" does not support tools` when a tools array is present). Learned
|
|
29
|
+
// REACTIVELY from that 400 and cached so later turns skip tools proactively (≤1
|
|
30
|
+
// wasted round trip per model per process). Not persisted: Pi's ModelRegistry
|
|
31
|
+
// rebuilds each Model from a fixed field allow-list, so a per-model flag on the
|
|
32
|
+
// models.json def can't reach this stream — an in-process Set is the reliable seam.
|
|
33
|
+
// Reactive-only (never seeded from /api/show) so a capable tool-caller is NEVER
|
|
34
|
+
// pre-emptively stripped; the only removal happens after Ollama itself refused them.
|
|
35
|
+
const noToolsModels = new Set();
|
|
36
|
+
/** Resolve num_ctx: env override (BRIGADE_OLLAMA_NUM_CTX) → model context window
|
|
37
|
+
* → default. The env knob lets an operator cap the KV-cache size on constrained
|
|
38
|
+
* hardware where a model's full context would OOM. */
|
|
39
|
+
function resolveNumCtx(model) {
|
|
40
|
+
const raw = process.env.BRIGADE_OLLAMA_NUM_CTX;
|
|
41
|
+
if (raw) {
|
|
42
|
+
const n = Number.parseInt(raw, 10);
|
|
43
|
+
if (Number.isFinite(n) && n > 0)
|
|
44
|
+
return n;
|
|
45
|
+
}
|
|
46
|
+
const ctx = model.contextWindow;
|
|
47
|
+
const window = typeof ctx === "number" && Number.isFinite(ctx) && ctx > 0 ? Math.floor(ctx) : DEFAULT_NUM_CTX;
|
|
48
|
+
// CAP the KV-cache request. The strongest open models report huge trained
|
|
49
|
+
// windows via /api/show (llama3.1 128k, qwen3 256k, mistral-nemo up to 1M);
|
|
50
|
+
// forwarding that verbatim as num_ctx makes Ollama allocate the full KV cache
|
|
51
|
+
// up front → OOM / heavy CPU-spill on typical local hardware, right when the
|
|
52
|
+
// user is trying to run the best models. 64k covers real agent turns; an
|
|
53
|
+
// operator with the RAM/VRAM raises it (or sets the exact size) via
|
|
54
|
+
// BRIGADE_OLLAMA_NUM_CTX. Sending an explicit num_ctx still beats Ollama's
|
|
55
|
+
// tiny 4k/8k default for models that need room.
|
|
56
|
+
return Math.min(window, DEFAULT_NUM_CTX);
|
|
57
|
+
}
|
|
58
|
+
/* ─────────────────────────── url + id normalization ─────────────────────────── */
|
|
59
|
+
/** Strip trailing slashes and a trailing `/v1`, then append `/api/chat`. */
|
|
60
|
+
export function resolveOllamaChatUrl(baseUrl) {
|
|
61
|
+
const trimmed = (baseUrl ?? "").trim().replace(/\/+$/, "");
|
|
62
|
+
const base = trimmed.replace(/\/v1$/i, "");
|
|
63
|
+
return `${base || OLLAMA_NATIVE_BASE_URL}/api/chat`;
|
|
64
|
+
}
|
|
65
|
+
/** Drop a leading `ollama/` provider prefix from the wire model id. */
|
|
66
|
+
function normalizeWireModelId(modelId) {
|
|
67
|
+
const trimmed = (modelId ?? "").trim();
|
|
68
|
+
return trimmed.startsWith("ollama/") ? trimmed.slice("ollama/".length) : trimmed;
|
|
69
|
+
}
|
|
70
|
+
function ensureArgsObject(value) {
|
|
71
|
+
return parseJsonObjectPreservingUnsafeIntegers(value) ?? {};
|
|
72
|
+
}
|
|
73
|
+
function extractTextContent(content) {
|
|
74
|
+
if (typeof content === "string")
|
|
75
|
+
return content;
|
|
76
|
+
if (!Array.isArray(content))
|
|
77
|
+
return "";
|
|
78
|
+
return content
|
|
79
|
+
.filter((p) => p?.type === "text" && typeof p.text === "string")
|
|
80
|
+
.map((p) => p.text)
|
|
81
|
+
.join("");
|
|
82
|
+
}
|
|
83
|
+
function extractImages(content) {
|
|
84
|
+
if (!Array.isArray(content))
|
|
85
|
+
return [];
|
|
86
|
+
return content
|
|
87
|
+
.filter((p) => p?.type === "image" && typeof p.data === "string")
|
|
88
|
+
.map((p) => p.data);
|
|
89
|
+
}
|
|
90
|
+
function extractWireToolCalls(content) {
|
|
91
|
+
if (!Array.isArray(content))
|
|
92
|
+
return [];
|
|
93
|
+
const out = [];
|
|
94
|
+
for (const part of content) {
|
|
95
|
+
if (part?.type === "toolCall") {
|
|
96
|
+
out.push({ function: { name: part.name, arguments: ensureArgsObject(part.arguments) } });
|
|
97
|
+
}
|
|
98
|
+
else if (part?.type === "tool_use") {
|
|
99
|
+
out.push({ function: { name: part.name, arguments: ensureArgsObject(part.input) } });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
/** Convert Pi's message array + system prompt into Ollama chat messages. */
|
|
105
|
+
export function convertToOllamaMessages(messages, systemPrompt) {
|
|
106
|
+
const out = [];
|
|
107
|
+
if (systemPrompt)
|
|
108
|
+
out.push({ role: "system", content: systemPrompt });
|
|
109
|
+
for (const msg of messages) {
|
|
110
|
+
if (msg.role === "user") {
|
|
111
|
+
const images = extractImages(msg.content);
|
|
112
|
+
out.push({
|
|
113
|
+
role: "user",
|
|
114
|
+
content: extractTextContent(msg.content),
|
|
115
|
+
...(images.length > 0 ? { images } : {}),
|
|
116
|
+
});
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (msg.role === "assistant") {
|
|
120
|
+
const toolCalls = extractWireToolCalls(msg.content);
|
|
121
|
+
out.push({
|
|
122
|
+
role: "assistant",
|
|
123
|
+
content: extractTextContent(msg.content),
|
|
124
|
+
...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),
|
|
125
|
+
});
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (msg.role === "tool" || msg.role === "toolResult") {
|
|
129
|
+
const toolName = typeof msg.toolName === "string" ? msg.toolName : undefined;
|
|
130
|
+
out.push({
|
|
131
|
+
role: "tool",
|
|
132
|
+
content: extractTextContent(msg.content),
|
|
133
|
+
...(toolName ? { tool_name: toolName } : {}),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
/** Map Pi `Tool[]` to Ollama's function-tool wire shape (schema passed through). */
|
|
140
|
+
export function extractOllamaTools(tools) {
|
|
141
|
+
if (!Array.isArray(tools))
|
|
142
|
+
return [];
|
|
143
|
+
const out = [];
|
|
144
|
+
for (const tool of tools) {
|
|
145
|
+
if (typeof tool?.name !== "string" || !tool.name)
|
|
146
|
+
continue;
|
|
147
|
+
out.push({
|
|
148
|
+
type: "function",
|
|
149
|
+
function: {
|
|
150
|
+
name: tool.name,
|
|
151
|
+
description: typeof tool.description === "string" ? tool.description : "",
|
|
152
|
+
parameters: (tool.parameters ?? {}),
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
function buildOllamaChatRequest(params) {
|
|
159
|
+
return {
|
|
160
|
+
model: normalizeWireModelId(params.modelId),
|
|
161
|
+
messages: params.messages,
|
|
162
|
+
stream: true,
|
|
163
|
+
...(params.tools && params.tools.length > 0 ? { tools: params.tools } : {}),
|
|
164
|
+
...(params.options ? { options: params.options } : {}),
|
|
165
|
+
...(params.think !== undefined ? { think: params.think } : {}),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/* ─────────────────────────── message + usage builders ─────────────────────────── */
|
|
169
|
+
function buildUsageWithNoCost(params) {
|
|
170
|
+
const input = params.input ?? 0;
|
|
171
|
+
const output = params.output ?? 0;
|
|
172
|
+
return {
|
|
173
|
+
input,
|
|
174
|
+
output,
|
|
175
|
+
cacheRead: 0,
|
|
176
|
+
cacheWrite: 0,
|
|
177
|
+
totalTokens: input + output,
|
|
178
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function buildAssistantMessageShell(params) {
|
|
182
|
+
return {
|
|
183
|
+
role: "assistant",
|
|
184
|
+
content: params.content,
|
|
185
|
+
api: params.model.api,
|
|
186
|
+
provider: params.model.provider,
|
|
187
|
+
model: params.model.id,
|
|
188
|
+
usage: params.usage,
|
|
189
|
+
stopReason: params.stopReason,
|
|
190
|
+
...(params.errorMessage ? { errorMessage: params.errorMessage } : {}),
|
|
191
|
+
timestamp: params.timestamp,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/* ─────────────────────────── NDJSON reader ─────────────────────────── */
|
|
195
|
+
/** Line-buffered NDJSON reader. Skips blank/malformed lines (never fatal). */
|
|
196
|
+
export async function* parseNdjsonStream(reader) {
|
|
197
|
+
const decoder = new TextDecoder();
|
|
198
|
+
let buffer = "";
|
|
199
|
+
while (true) {
|
|
200
|
+
const { done, value } = await reader.read();
|
|
201
|
+
if (done)
|
|
202
|
+
break;
|
|
203
|
+
buffer += decoder.decode(value, { stream: true });
|
|
204
|
+
const lines = buffer.split("\n");
|
|
205
|
+
buffer = lines.pop() ?? "";
|
|
206
|
+
for (const line of lines) {
|
|
207
|
+
const trimmed = line.trim();
|
|
208
|
+
if (!trimmed)
|
|
209
|
+
continue;
|
|
210
|
+
try {
|
|
211
|
+
yield parseJsonPreservingUnsafeIntegers(trimmed);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
/* skip malformed line */
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (buffer.trim()) {
|
|
219
|
+
try {
|
|
220
|
+
yield parseJsonPreservingUnsafeIntegers(buffer.trim());
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
/* skip malformed trailing data */
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/* ─────────────────────────── the stream fn ─────────────────────────── */
|
|
228
|
+
/** Derive Ollama's native `think` flag from Pi's thinking level. Default OFF, and
|
|
229
|
+
* sent EXPLICITLY as `think:false` (never omitted): the Pi harness maps
|
|
230
|
+
* thinkingLevel "off" → reasoning:undefined, and OMITTING `think` lets Ollama
|
|
231
|
+
* fall back to the model's server-side default — which is thinking-ON for
|
|
232
|
+
* reasoning models, and makes local models narrate tool calls as prose instead
|
|
233
|
+
* of emitting structured calls. Only an explicit non-off level enables thinking. */
|
|
234
|
+
function resolveThink(reasoning) {
|
|
235
|
+
return typeof reasoning === "string" && reasoning !== "off";
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Build a Pi `StreamFn` that streams a turn against Ollama's native /api/chat.
|
|
239
|
+
* The chat URL is resolved from the MODEL's baseUrl per call (so one registered
|
|
240
|
+
* transport serves every Ollama endpoint — local or remote). `defaultHeaders`
|
|
241
|
+
* merge under per-call `options.headers`.
|
|
242
|
+
*/
|
|
243
|
+
export function createOllamaStreamFn(defaultHeaders) {
|
|
244
|
+
return ((model, context, options) => {
|
|
245
|
+
const chatUrl = resolveOllamaChatUrl(model.baseUrl ?? OLLAMA_NATIVE_BASE_URL);
|
|
246
|
+
const stream = createAssistantMessageEventStream();
|
|
247
|
+
const modelInfo = { api: model.api, provider: model.provider, id: model.id };
|
|
248
|
+
// ONE stable timestamp for the whole turn — every partial + the final message
|
|
249
|
+
// must share it. The connect render identity-keys an assistant block by
|
|
250
|
+
// `<depth>:<timestamp>`; a per-frame Date.now() renders each token as a new line.
|
|
251
|
+
const messageTimestamp = Date.now();
|
|
252
|
+
const run = async () => {
|
|
253
|
+
// accumulators
|
|
254
|
+
let accumulatedThinking = "";
|
|
255
|
+
let accumulatedContent = "";
|
|
256
|
+
const accumulatedToolCalls = [];
|
|
257
|
+
let finalResponse;
|
|
258
|
+
// event-ordering flags
|
|
259
|
+
let started = false;
|
|
260
|
+
let thinkingStarted = false;
|
|
261
|
+
let thinkingEnded = false;
|
|
262
|
+
let textStarted = false;
|
|
263
|
+
let textClosed = false;
|
|
264
|
+
// The text block's contentIndex is LATCHED on first use (when text_start
|
|
265
|
+
// fires), never recomputed per call: a thinking delta arriving AFTER text
|
|
266
|
+
// already started must not retroactively shift the index that text_delta /
|
|
267
|
+
// text_end already emitted under — that would desync an index-keyed renderer.
|
|
268
|
+
let latchedTextIndex;
|
|
269
|
+
const textIndex = () => {
|
|
270
|
+
if (latchedTextIndex === undefined)
|
|
271
|
+
latchedTextIndex = thinkingStarted ? 1 : 0;
|
|
272
|
+
return latchedTextIndex;
|
|
273
|
+
};
|
|
274
|
+
let reader;
|
|
275
|
+
const currentContent = () => {
|
|
276
|
+
const parts = [];
|
|
277
|
+
if (accumulatedThinking)
|
|
278
|
+
parts.push({ type: "thinking", thinking: accumulatedThinking });
|
|
279
|
+
if (accumulatedContent)
|
|
280
|
+
parts.push({ type: "text", text: accumulatedContent });
|
|
281
|
+
return parts;
|
|
282
|
+
};
|
|
283
|
+
const partial = () => buildAssistantMessageShell({
|
|
284
|
+
model: modelInfo,
|
|
285
|
+
timestamp: messageTimestamp,
|
|
286
|
+
content: currentContent(),
|
|
287
|
+
stopReason: "stop",
|
|
288
|
+
usage: buildUsageWithNoCost({}),
|
|
289
|
+
});
|
|
290
|
+
const ensureStarted = () => {
|
|
291
|
+
if (started)
|
|
292
|
+
return;
|
|
293
|
+
started = true;
|
|
294
|
+
stream.push({
|
|
295
|
+
type: "start",
|
|
296
|
+
partial: buildAssistantMessageShell({
|
|
297
|
+
model: modelInfo,
|
|
298
|
+
timestamp: messageTimestamp,
|
|
299
|
+
content: [],
|
|
300
|
+
stopReason: "stop",
|
|
301
|
+
usage: buildUsageWithNoCost({}),
|
|
302
|
+
}),
|
|
303
|
+
});
|
|
304
|
+
};
|
|
305
|
+
const closeThinking = () => {
|
|
306
|
+
if (!thinkingStarted || thinkingEnded)
|
|
307
|
+
return;
|
|
308
|
+
thinkingEnded = true;
|
|
309
|
+
stream.push({ type: "thinking_end", contentIndex: 0, content: accumulatedThinking, partial: partial() });
|
|
310
|
+
};
|
|
311
|
+
const closeText = () => {
|
|
312
|
+
if (!textStarted || textClosed)
|
|
313
|
+
return;
|
|
314
|
+
textClosed = true;
|
|
315
|
+
stream.push({ type: "text_end", contentIndex: textIndex(), content: accumulatedContent, partial: partial() });
|
|
316
|
+
};
|
|
317
|
+
try {
|
|
318
|
+
const ctx = (context ?? {});
|
|
319
|
+
const ollamaMessages = convertToOllamaMessages(ctx.messages ?? [], ctx.systemPrompt);
|
|
320
|
+
const wireModelId = normalizeWireModelId(model.id);
|
|
321
|
+
// Omit tools for a model Ollama already rejected them for this process:
|
|
322
|
+
// a text/vision-only model 400s when a tools array is present, so a plain
|
|
323
|
+
// answer beats a hard failure. buildOllamaChatRequest omits `tools` when
|
|
324
|
+
// the array is empty.
|
|
325
|
+
const ollamaTools = noToolsModels.has(wireModelId) ? [] : extractOllamaTools(ctx.tools);
|
|
326
|
+
const ollamaOptions = { num_ctx: resolveNumCtx(model) };
|
|
327
|
+
if (typeof options?.temperature === "number")
|
|
328
|
+
ollamaOptions.temperature = options.temperature;
|
|
329
|
+
if (typeof options?.maxTokens === "number")
|
|
330
|
+
ollamaOptions.num_predict = options.maxTokens;
|
|
331
|
+
let body = buildOllamaChatRequest({
|
|
332
|
+
modelId: model.id,
|
|
333
|
+
messages: ollamaMessages,
|
|
334
|
+
tools: ollamaTools,
|
|
335
|
+
options: ollamaOptions,
|
|
336
|
+
think: resolveThink(options?.reasoning),
|
|
337
|
+
});
|
|
338
|
+
if (typeof options?.onPayload === "function") {
|
|
339
|
+
// pi-ai contract: onPayload MAY return a replacement payload (undefined = keep).
|
|
340
|
+
const next = await options.onPayload(body, model);
|
|
341
|
+
if (next !== undefined)
|
|
342
|
+
body = next;
|
|
343
|
+
}
|
|
344
|
+
const modelHeaders = model.headers;
|
|
345
|
+
const headers = {
|
|
346
|
+
"Content-Type": "application/json",
|
|
347
|
+
// model.headers (e.g. a remote/authed Ollama proxy token) below the
|
|
348
|
+
// defaults; per-call options.headers win last — pi-ai built-in precedence.
|
|
349
|
+
...defaultHeaders,
|
|
350
|
+
...(modelHeaders && typeof modelHeaders === "object" && !Array.isArray(modelHeaders)
|
|
351
|
+
? modelHeaders
|
|
352
|
+
: {}),
|
|
353
|
+
...(options?.headers ?? {}),
|
|
354
|
+
};
|
|
355
|
+
const apiKey = options?.apiKey;
|
|
356
|
+
// Only attach a Bearer token for real (cloud) keys — never the local
|
|
357
|
+
// sentinel, which isn't a secret.
|
|
358
|
+
if (typeof apiKey === "string" && apiKey && !LOCAL_SENTINEL_KEYS.has(apiKey) && !headers.Authorization) {
|
|
359
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
360
|
+
}
|
|
361
|
+
// SSRF pre-check (the base URL is config-driven and can be remote):
|
|
362
|
+
// blocks cloud-metadata / disallowed hosts while permitting localhost/LAN
|
|
363
|
+
// Ollama. Pre-check + plain fetch (not guardedFetch) so the guard's
|
|
364
|
+
// request timeout never aborts a long-running stream mid-generation.
|
|
365
|
+
const ssrfReason = await classifyUrlForSsrf(chatUrl, { allowPrivateNetwork: true });
|
|
366
|
+
if (ssrfReason)
|
|
367
|
+
throw new Error(`Ollama endpoint blocked: ${ssrfReason} (${chatUrl})`);
|
|
368
|
+
const doFetch = () => fetch(chatUrl, {
|
|
369
|
+
method: "POST",
|
|
370
|
+
headers,
|
|
371
|
+
body: JSON.stringify(body),
|
|
372
|
+
signal: options?.signal,
|
|
373
|
+
// Never follow redirects: a native Ollama /api/chat never legitimately
|
|
374
|
+
// 3xx-redirects, and following one would resend the request (+ any auth
|
|
375
|
+
// header) to a host the SSRF pre-check never saw — defeating the guard.
|
|
376
|
+
redirect: "manual",
|
|
377
|
+
});
|
|
378
|
+
let response = await doFetch();
|
|
379
|
+
if (!response.ok || !response.body) {
|
|
380
|
+
const detail = await response.text().catch(() => "");
|
|
381
|
+
// A text/vision-only model 400s with `"<model>" does not support tools`
|
|
382
|
+
// when a tools array is present. A plain answer beats a hard failure:
|
|
383
|
+
// drop tools, remember it for the rest of the process, retry ONCE. Mirrors
|
|
384
|
+
// the thinking-fallback downgrade for the parallel "does not support
|
|
385
|
+
// thinking" 400. Only fires when we actually SENT tools, so a genuine 400
|
|
386
|
+
// for any other reason still surfaces below unchanged.
|
|
387
|
+
if (response.status === 400 &&
|
|
388
|
+
Array.isArray(body.tools) &&
|
|
389
|
+
body.tools.length > 0 &&
|
|
390
|
+
/does not support tools/i.test(detail)) {
|
|
391
|
+
noToolsModels.add(wireModelId);
|
|
392
|
+
delete body.tools;
|
|
393
|
+
response = await doFetch();
|
|
394
|
+
}
|
|
395
|
+
if (!response.ok || !response.body) {
|
|
396
|
+
const detail2 = await response.text().catch(() => "");
|
|
397
|
+
// The status is embedded in the message (the transport converts this
|
|
398
|
+
// throw into an error EVENT that carries only the message string, so a
|
|
399
|
+
// structured `.status` property wouldn't survive to the classifier).
|
|
400
|
+
// 401/403/429/402 are matched by the classifier's text patterns; a
|
|
401
|
+
// permanent 400 "does not support thinking" is caught upstream by the
|
|
402
|
+
// thinking-fallback downgrade.
|
|
403
|
+
throw new Error(`Ollama /api/chat returned ${response.status}${detail2 ? `: ${detail2.slice(0, 200)}` : ""}`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Emit `start` before reading any chunk — mirroring pi-ai's built-in
|
|
407
|
+
// providers. A turn whose only output is a tool call (Ollama's headline
|
|
408
|
+
// agentic case) or an empty reply would otherwise reach `done` having
|
|
409
|
+
// never emitted `start`, violating the event contract and starving a
|
|
410
|
+
// streaming UI until completion.
|
|
411
|
+
ensureStarted();
|
|
412
|
+
reader = response.body.getReader();
|
|
413
|
+
for await (const chunk of parseNdjsonStream(reader)) {
|
|
414
|
+
const thinkingDelta = chunk.message?.thinking ?? chunk.message?.reasoning;
|
|
415
|
+
if (thinkingDelta) {
|
|
416
|
+
ensureStarted();
|
|
417
|
+
if (!thinkingStarted) {
|
|
418
|
+
thinkingStarted = true;
|
|
419
|
+
stream.push({ type: "thinking_start", contentIndex: 0, partial: partial() });
|
|
420
|
+
}
|
|
421
|
+
accumulatedThinking += thinkingDelta;
|
|
422
|
+
stream.push({ type: "thinking_delta", contentIndex: 0, delta: thinkingDelta, partial: partial() });
|
|
423
|
+
}
|
|
424
|
+
const contentDelta = chunk.message?.content;
|
|
425
|
+
if (contentDelta) {
|
|
426
|
+
if (thinkingStarted && !thinkingEnded)
|
|
427
|
+
closeThinking();
|
|
428
|
+
ensureStarted();
|
|
429
|
+
if (!textStarted) {
|
|
430
|
+
textStarted = true;
|
|
431
|
+
stream.push({ type: "text_start", contentIndex: textIndex(), partial: partial() });
|
|
432
|
+
}
|
|
433
|
+
accumulatedContent += contentDelta;
|
|
434
|
+
stream.push({ type: "text_delta", contentIndex: textIndex(), delta: contentDelta, partial: partial() });
|
|
435
|
+
}
|
|
436
|
+
if (chunk.message?.tool_calls && chunk.message.tool_calls.length > 0) {
|
|
437
|
+
closeThinking();
|
|
438
|
+
closeText();
|
|
439
|
+
// Only accumulate WELL-FORMED tool calls. Small/quantized local models
|
|
440
|
+
// routinely emit off-spec shapes (flat `{name,arguments}` with no
|
|
441
|
+
// `function` wrapper, or a `function` with no `name`); Ollama forwards
|
|
442
|
+
// them verbatim. Accessing `tc.function.name` on those throws a
|
|
443
|
+
// TypeError inside the producer → the whole turn errors out. Skip them
|
|
444
|
+
// (defensively coercing args) so a stray malformed call can't nuke a turn.
|
|
445
|
+
for (const tc of chunk.message.tool_calls) {
|
|
446
|
+
if (tc && typeof tc.function?.name === "string" && tc.function.name.length > 0) {
|
|
447
|
+
accumulatedToolCalls.push(tc);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (chunk.done) {
|
|
452
|
+
finalResponse = chunk;
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// Ollama's /api/chat protocol ALWAYS terminates with a `done:true`
|
|
457
|
+
// chunk carrying the final stop reason + eval counts. Its absence
|
|
458
|
+
// means the connection dropped mid-generation, so the accumulated
|
|
459
|
+
// output is truncated. Fail the turn (→ error event → the resilient
|
|
460
|
+
// retry layer re-runs it) rather than pass partial content off as a
|
|
461
|
+
// clean completion — a half-streamed tool call or sentence acted on
|
|
462
|
+
// as "done" is a correctness hazard. Matches the reference transport.
|
|
463
|
+
if (!finalResponse) {
|
|
464
|
+
throw new Error("Ollama /api/chat stream ended without a final response (connection dropped mid-generation)");
|
|
465
|
+
}
|
|
466
|
+
closeThinking();
|
|
467
|
+
closeText();
|
|
468
|
+
const content = [];
|
|
469
|
+
if (accumulatedThinking)
|
|
470
|
+
content.push({ type: "thinking", thinking: accumulatedThinking });
|
|
471
|
+
if (accumulatedContent)
|
|
472
|
+
content.push({ type: "text", text: accumulatedContent });
|
|
473
|
+
for (const tc of accumulatedToolCalls) {
|
|
474
|
+
content.push({
|
|
475
|
+
type: "toolCall",
|
|
476
|
+
id: `ollama_call_${randomUUID()}`,
|
|
477
|
+
name: tc.function.name,
|
|
478
|
+
arguments: ensureArgsObject(tc.function.arguments),
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
const hasToolCalls = accumulatedToolCalls.length > 0;
|
|
482
|
+
// Map Ollama's done_reason: "length" (hit the num_predict / maxTokens cap)
|
|
483
|
+
// surfaces as StopReason "length" so max-tokens continuation logic sees a
|
|
484
|
+
// TRUNCATED turn instead of mistaking a capped reply for a clean "stop".
|
|
485
|
+
const stopReason = hasToolCalls
|
|
486
|
+
? "toolUse"
|
|
487
|
+
: finalResponse.done_reason === "length"
|
|
488
|
+
? "length"
|
|
489
|
+
: "stop";
|
|
490
|
+
const message = buildAssistantMessageShell({
|
|
491
|
+
model: modelInfo,
|
|
492
|
+
timestamp: messageTimestamp,
|
|
493
|
+
content,
|
|
494
|
+
stopReason,
|
|
495
|
+
usage: buildUsageWithNoCost({
|
|
496
|
+
input: finalResponse.prompt_eval_count ?? 0,
|
|
497
|
+
output: finalResponse.eval_count ?? 0,
|
|
498
|
+
}),
|
|
499
|
+
});
|
|
500
|
+
stream.push({ type: "done", reason: stopReason, message });
|
|
501
|
+
}
|
|
502
|
+
catch (err) {
|
|
503
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
504
|
+
const aborted = err instanceof Error && (err.name === "AbortError" || /abort/i.test(errorMessage));
|
|
505
|
+
stream.push({
|
|
506
|
+
type: "error",
|
|
507
|
+
reason: aborted ? "aborted" : "error",
|
|
508
|
+
error: buildAssistantMessageShell({
|
|
509
|
+
model: modelInfo,
|
|
510
|
+
timestamp: messageTimestamp,
|
|
511
|
+
content: accumulatedContent ? [{ type: "text", text: accumulatedContent }] : [],
|
|
512
|
+
stopReason: aborted ? "aborted" : "error",
|
|
513
|
+
usage: buildUsageWithNoCost({}),
|
|
514
|
+
errorMessage,
|
|
515
|
+
}),
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
finally {
|
|
519
|
+
// Release the response-body reader on ANY exit (normal completion,
|
|
520
|
+
// abort, or mid-stream throw). Web streams don't auto-release the lock
|
|
521
|
+
// when read() reports done, so without this the socket dangles until GC
|
|
522
|
+
// on a dropped/aborted turn. No-op resolve when already closed.
|
|
523
|
+
if (reader)
|
|
524
|
+
await reader.cancel().catch(() => { });
|
|
525
|
+
stream.end();
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
queueMicrotask(() => void run());
|
|
529
|
+
return stream;
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../../src/agents/ollama-native/stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -149,27 +149,6 @@ export declare function normalizeSiliconFlowThinking(payload: unknown, model: Mo
|
|
|
149
149
|
export declare function isSiliconFlowModel(model: Model<any>): boolean;
|
|
150
150
|
export declare function disableMinimaxThinking(payload: unknown, model: Model<any>): void;
|
|
151
151
|
export declare function isMinimaxAnthropicModel(model: Model<any>): boolean;
|
|
152
|
-
/** Whether the active model is served by a local Ollama daemon. */
|
|
153
|
-
export declare function isOllamaModel(model: Model<any>): boolean;
|
|
154
|
-
/**
|
|
155
|
-
* Resolve the num_ctx to inject: `BRIGADE_OLLAMA_NUM_CTX` env override wins,
|
|
156
|
-
* else the model's own context window (models.json, seeded from `/api/show`).
|
|
157
|
-
* Returns undefined when nothing usable is known (leave Ollama's default).
|
|
158
|
-
*/
|
|
159
|
-
export declare function resolveOllamaNumCtx(model: Model<any>): number | undefined;
|
|
160
|
-
/**
|
|
161
|
-
* Inject `options.num_ctx` for Ollama requests.
|
|
162
|
-
*
|
|
163
|
-
* Ollama's OpenAI-compatible endpoint defaults num_ctx to ~2048–4096 and
|
|
164
|
-
* SILENTLY truncates anything longer. That shreds Brigade's large system prompt
|
|
165
|
-
* (identity / tool guidance gets cut → the model leaks its base-model identity),
|
|
166
|
-
* cuts replies off mid-stream, and degrades tool discipline. Pi never sets
|
|
167
|
-
* num_ctx, so we set it from the model's real context window. Ollama clamps the
|
|
168
|
-
* value down to the model's true maximum, so an over-estimate is safe (it can
|
|
169
|
-
* only ever raise the ceiling above the tiny default, never below it). Never
|
|
170
|
-
* overrides an explicit caller/model value.
|
|
171
|
-
*/
|
|
172
|
-
export declare function injectOllamaNumCtx(payload: unknown, model: Model<any>): void;
|
|
173
152
|
/**
|
|
174
153
|
* Run every applicable mutator against the payload. Each mutator self-gates
|
|
175
154
|
* on the active model — no-ops when the provider doesn't match — so calling
|