@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.
Files changed (96) hide show
  1. package/README.md +4 -3
  2. package/convex/config.d.ts +2 -2
  3. package/convex/schema.d.ts +4 -4
  4. package/dist/agents/agent-loop.d.ts.map +1 -1
  5. package/dist/agents/agent-loop.js +92 -22
  6. package/dist/agents/agent-loop.js.map +1 -1
  7. package/dist/agents/content-quality-retry.d.ts.map +1 -1
  8. package/dist/agents/content-quality-retry.js +3 -22
  9. package/dist/agents/content-quality-retry.js.map +1 -1
  10. package/dist/agents/error-classifier.d.ts.map +1 -1
  11. package/dist/agents/error-classifier.js +2 -0
  12. package/dist/agents/error-classifier.js.map +1 -1
  13. package/dist/agents/memory/extract.d.ts.map +1 -1
  14. package/dist/agents/memory/extract.js +11 -44
  15. package/dist/agents/memory/extract.js.map +1 -1
  16. package/dist/agents/model-resolution.d.ts.map +1 -1
  17. package/dist/agents/model-resolution.js +9 -3
  18. package/dist/agents/model-resolution.js.map +1 -1
  19. package/dist/agents/ollama-native/ollama-json.d.ts +6 -0
  20. package/dist/agents/ollama-native/ollama-json.d.ts.map +1 -0
  21. package/dist/agents/ollama-native/ollama-json.js +126 -0
  22. package/dist/agents/ollama-native/ollama-json.js.map +1 -0
  23. package/dist/agents/ollama-native/register.d.ts +12 -0
  24. package/dist/agents/ollama-native/register.d.ts.map +1 -0
  25. package/dist/agents/ollama-native/register.js +37 -0
  26. package/dist/agents/ollama-native/register.js.map +1 -0
  27. package/dist/agents/ollama-native/stream.d.ts +59 -0
  28. package/dist/agents/ollama-native/stream.d.ts.map +1 -0
  29. package/dist/agents/ollama-native/stream.js +532 -0
  30. package/dist/agents/ollama-native/stream.js.map +1 -0
  31. package/dist/agents/payload-mutators.d.ts +0 -21
  32. package/dist/agents/payload-mutators.d.ts.map +1 -1
  33. package/dist/agents/payload-mutators.js +0 -58
  34. package/dist/agents/payload-mutators.js.map +1 -1
  35. package/dist/agents/thinking-fallback.d.ts.map +1 -1
  36. package/dist/agents/thinking-fallback.js +32 -10
  37. package/dist/agents/thinking-fallback.js.map +1 -1
  38. package/dist/buildstamp.json +1 -1
  39. package/dist/cli/commands/connect.d.ts.map +1 -1
  40. package/dist/cli/commands/connect.js +31 -43
  41. package/dist/cli/commands/connect.js.map +1 -1
  42. package/dist/cli/commands/update.d.ts +0 -6
  43. package/dist/cli/commands/update.d.ts.map +1 -1
  44. package/dist/cli/commands/update.js +9 -124
  45. package/dist/cli/commands/update.js.map +1 -1
  46. package/dist/cli/program/build-program.d.ts.map +1 -1
  47. package/dist/cli/program/build-program.js +1 -5
  48. package/dist/cli/program/build-program.js.map +1 -1
  49. package/dist/core/server.d.ts.map +1 -1
  50. package/dist/core/server.js +43 -25
  51. package/dist/core/server.js.map +1 -1
  52. package/dist/integrations/antigravity/transport.d.ts +29 -0
  53. package/dist/integrations/antigravity/transport.d.ts.map +1 -0
  54. package/dist/integrations/antigravity/transport.js +498 -0
  55. package/dist/integrations/antigravity/transport.js.map +1 -0
  56. package/dist/integrations/cli-login.d.ts +13 -0
  57. package/dist/integrations/cli-login.d.ts.map +1 -1
  58. package/dist/integrations/cli-login.js +29 -0
  59. package/dist/integrations/cli-login.js.map +1 -1
  60. package/dist/integrations/ollama.d.ts +29 -36
  61. package/dist/integrations/ollama.d.ts.map +1 -1
  62. package/dist/integrations/ollama.js +213 -78
  63. package/dist/integrations/ollama.js.map +1 -1
  64. package/dist/integrations/provider-discovery.d.ts +37 -0
  65. package/dist/integrations/provider-discovery.d.ts.map +1 -1
  66. package/dist/integrations/provider-discovery.js +102 -0
  67. package/dist/integrations/provider-discovery.js.map +1 -1
  68. package/dist/providers/catalog.d.ts +8 -1
  69. package/dist/providers/catalog.d.ts.map +1 -1
  70. package/dist/providers/catalog.js +29 -1
  71. package/dist/providers/catalog.js.map +1 -1
  72. package/dist/providers/validate-key.js +1 -1
  73. package/dist/storage/boot.d.ts.map +1 -1
  74. package/dist/storage/boot.js +2 -1
  75. package/dist/storage/boot.js.map +1 -1
  76. package/dist/storage/convex/index.d.ts.map +1 -1
  77. package/dist/storage/convex/index.js +15 -4
  78. package/dist/storage/convex/index.js.map +1 -1
  79. package/dist/system-prompt/guidance.d.ts.map +1 -1
  80. package/dist/system-prompt/guidance.js +2 -9
  81. package/dist/system-prompt/guidance.js.map +1 -1
  82. package/dist/ui/onboard-storage-mode.js +30 -4
  83. package/dist/ui/onboard-storage-mode.js.map +1 -1
  84. package/dist/ui/onboarding.d.ts.map +1 -1
  85. package/dist/ui/onboarding.js +150 -32
  86. package/dist/ui/onboarding.js.map +1 -1
  87. package/package.json +5 -2
  88. package/scripts/convex-push.mjs +47 -29
  89. package/dist/agents/tool-name-repair.d.ts +0 -28
  90. package/dist/agents/tool-name-repair.d.ts.map +0 -1
  91. package/dist/agents/tool-name-repair.js +0 -168
  92. package/dist/agents/tool-name-repair.js.map +0 -1
  93. package/dist/shared/reasoning-tags.d.ts +0 -14
  94. package/dist/shared/reasoning-tags.d.ts.map +0 -1
  95. package/dist/shared/reasoning-tags.js +0 -71
  96. 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