@proposit/proposit-core 1.5.1 → 1.6.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/dist/extensions/argument-ingestion/shared/resolve-llm-stage-options.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/shared/resolve-llm-stage-options.js +6 -0
- package/dist/extensions/argument-ingestion/shared/resolve-llm-stage-options.js.map +1 -1
- package/dist/extensions/argument-ingestion/shared/types.d.ts +18 -7
- package/dist/extensions/argument-ingestion/shared/types.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/axiom-indicator-detection.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/axiom-indicator-detection.js +4 -2
- package/dist/extensions/argument-ingestion/stages/axiom-indicator-detection.js.map +1 -1
- package/dist/extensions/argument-ingestion/stages/citation-source-detection.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/citation-source-detection.js +4 -2
- package/dist/extensions/argument-ingestion/stages/citation-source-detection.js.map +1 -1
- package/dist/extensions/argument-ingestion/stages/claim-canonicalization.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/claim-canonicalization.js +2 -1
- package/dist/extensions/argument-ingestion/stages/claim-canonicalization.js.map +1 -1
- package/dist/extensions/argument-ingestion/stages/claim-mention-extraction.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/claim-mention-extraction.js +4 -2
- package/dist/extensions/argument-ingestion/stages/claim-mention-extraction.js.map +1 -1
- package/dist/extensions/argument-ingestion/stages/claim-type-classification.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/claim-type-classification.js +4 -2
- package/dist/extensions/argument-ingestion/stages/claim-type-classification.js.map +1 -1
- package/dist/extensions/argument-ingestion/stages/conclusion-selection.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/conclusion-selection.js +2 -1
- package/dist/extensions/argument-ingestion/stages/conclusion-selection.js.map +1 -1
- package/dist/extensions/argument-ingestion/stages/relation-extraction.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/relation-extraction.js +2 -1
- package/dist/extensions/argument-ingestion/stages/relation-extraction.js.map +1 -1
- package/dist/extensions/argument-ingestion/stages/segmentation.d.ts.map +1 -1
- package/dist/extensions/argument-ingestion/stages/segmentation.js +2 -1
- package/dist/extensions/argument-ingestion/stages/segmentation.js.map +1 -1
- package/dist/extensions/ollama/errors.d.ts +70 -0
- package/dist/extensions/ollama/errors.d.ts.map +1 -0
- package/dist/extensions/ollama/errors.js +210 -0
- package/dist/extensions/ollama/errors.js.map +1 -0
- package/dist/extensions/ollama/index.d.ts +6 -0
- package/dist/extensions/ollama/index.d.ts.map +1 -0
- package/dist/extensions/ollama/index.js +17 -0
- package/dist/extensions/ollama/index.js.map +1 -0
- package/dist/extensions/ollama/provider.d.ts +19 -0
- package/dist/extensions/ollama/provider.d.ts.map +1 -0
- package/dist/extensions/ollama/provider.js +285 -0
- package/dist/extensions/ollama/provider.js.map +1 -0
- package/dist/extensions/ollama/structured-output.d.ts +18 -0
- package/dist/extensions/ollama/structured-output.d.ts.map +1 -0
- package/dist/extensions/ollama/structured-output.js +164 -0
- package/dist/extensions/ollama/structured-output.js.map +1 -0
- package/dist/extensions/ollama/types.d.ts +101 -0
- package/dist/extensions/ollama/types.d.ts.map +1 -0
- package/dist/extensions/ollama/types.js +7 -0
- package/dist/extensions/ollama/types.js.map +1 -0
- package/package.json +11 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// Ollama-provider error classes + the `classifyOllamaError` mapping.
|
|
2
|
+
//
|
|
3
|
+
// The framework's `llmStage` retry policy classifies provider errors
|
|
4
|
+
// by inspecting a `retryReason` tag on the thrown object (see
|
|
5
|
+
// `src/lib/pipelines/stage-helpers.ts` #classifyError) — NOT by class
|
|
6
|
+
// identity. The failure *codes* live in the SDK-free
|
|
7
|
+
// `src/lib/pipelines/failure-codes.ts`. So these Ollama classes carry
|
|
8
|
+
// the same `retryReason` tags as the OpenAI provider's classes and set
|
|
9
|
+
// their `code` from the lib constants. They deliberately do NOT import
|
|
10
|
+
// from `extensions/openai/` and do NOT touch `src/lib/`.
|
|
11
|
+
//
|
|
12
|
+
// Mapping for the framework's default retry policy
|
|
13
|
+
// (`retryOn: ["schema_validation", "transient"]`):
|
|
14
|
+
//
|
|
15
|
+
// * `TransientLlmError` — `retryReason: "transient"`. Genuinely
|
|
16
|
+
// transient local hiccups: mid-stream `ECONNRESET`/socket drop,
|
|
17
|
+
// cold-model-load 5xx (model pulled but still loading into VRAM),
|
|
18
|
+
// generic 5xx. Retried by the default policy.
|
|
19
|
+
// * `RateLimitLlmError` — `retryReason: "rate_limit"`. A local
|
|
20
|
+
// daemon rarely rate-limits, but a remote-Ollama / proxy setup can
|
|
21
|
+
// return 429; mapped for contract parity. Not in the default
|
|
22
|
+
// `retryOn`, so it fails fast (callers can opt in).
|
|
23
|
+
// * `SchemaValidationLlmError` — tagged `transient`; the framework's
|
|
24
|
+
// schema-retry path handles it. Thrown only for genuinely
|
|
25
|
+
// malformed / non-parseable JSON in the model's reply — NOT for a
|
|
26
|
+
// context-overflow (which is deterministic; see below).
|
|
27
|
+
// * `NonRetryableLlmError` — no tag; framework surfaces it
|
|
28
|
+
// immediately as `LLM_NON_RETRYABLE_ERROR`. Used for: daemon
|
|
29
|
+
// unreachable (`ECONNREFUSED`), model-not-pulled (404), and
|
|
30
|
+
// context-length / eval errors (deterministic — a retry re-fails).
|
|
31
|
+
// * `ToolLoopExhaustedError` — surfaces from the function-tool loop
|
|
32
|
+
// when the round cap is hit. Non-retryable (no tag).
|
|
33
|
+
import { LLM_NON_RETRYABLE_ERROR, LLM_RATE_LIMITED, LLM_TRANSIENT_ERROR, } from "../../lib/pipelines/failure-codes.js";
|
|
34
|
+
export class TransientLlmError extends Error {
|
|
35
|
+
retryReason = "transient";
|
|
36
|
+
code = LLM_TRANSIENT_ERROR;
|
|
37
|
+
status;
|
|
38
|
+
constructor(args) {
|
|
39
|
+
super(args.message);
|
|
40
|
+
this.name = "TransientLlmError";
|
|
41
|
+
this.status = args.status;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export class RateLimitLlmError extends Error {
|
|
45
|
+
retryReason = "rate_limit";
|
|
46
|
+
code = LLM_RATE_LIMITED;
|
|
47
|
+
status;
|
|
48
|
+
constructor(args) {
|
|
49
|
+
super(args.message);
|
|
50
|
+
this.name = "RateLimitLlmError";
|
|
51
|
+
this.status = args.status;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Thrown when the model's structured-output reply is genuinely
|
|
56
|
+
* malformed / non-parseable JSON. Tagged `transient` so the framework's
|
|
57
|
+
* default retry policy retries — a single re-roll often produces
|
|
58
|
+
* conforming output.
|
|
59
|
+
*
|
|
60
|
+
* **Do not** route a context-length overflow here: an overflow is
|
|
61
|
+
* deterministic and re-fails on the retried (still-oversized) prompt.
|
|
62
|
+
* `classifyOllamaError` routes overflow to {@link NonRetryableLlmError}.
|
|
63
|
+
*/
|
|
64
|
+
export class SchemaValidationLlmError extends Error {
|
|
65
|
+
retryReason = "transient";
|
|
66
|
+
status;
|
|
67
|
+
constructor(args) {
|
|
68
|
+
super(args.message);
|
|
69
|
+
this.name = "SchemaValidationLlmError";
|
|
70
|
+
this.status = args.status;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export class NonRetryableLlmError extends Error {
|
|
74
|
+
code = LLM_NON_RETRYABLE_ERROR;
|
|
75
|
+
status;
|
|
76
|
+
constructor(args) {
|
|
77
|
+
super(args.message);
|
|
78
|
+
this.name = "NonRetryableLlmError";
|
|
79
|
+
this.status = args.status;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class ToolLoopExhaustedError extends Error {
|
|
83
|
+
rounds;
|
|
84
|
+
constructor(args) {
|
|
85
|
+
super(args.message);
|
|
86
|
+
this.name = "ToolLoopExhaustedError";
|
|
87
|
+
this.rounds = args.rounds;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// -- error-shape probes ---------------------------------------------------
|
|
91
|
+
//
|
|
92
|
+
// The `ollama` SDK throws plain `Error`s (sometimes a `ResponseError`
|
|
93
|
+
// carrying a `status_code`) and lets low-level `fetch` failures bubble
|
|
94
|
+
// up. undici wraps a connection refusal as `TypeError: fetch failed`
|
|
95
|
+
// with a `.cause` carrying the Node `code`. We probe both the error
|
|
96
|
+
// itself and one level of `.cause` for the Node-style `code` and an
|
|
97
|
+
// HTTP-ish `status` / `status_code`.
|
|
98
|
+
function nodeCodeOf(err) {
|
|
99
|
+
const direct = readCode(err);
|
|
100
|
+
if (direct !== undefined)
|
|
101
|
+
return direct;
|
|
102
|
+
if (typeof err === "object" && err !== null) {
|
|
103
|
+
return readCode(err.cause);
|
|
104
|
+
}
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
function readCode(value) {
|
|
108
|
+
if (typeof value !== "object" || value === null)
|
|
109
|
+
return undefined;
|
|
110
|
+
const code = value.code;
|
|
111
|
+
return typeof code === "string" ? code : undefined;
|
|
112
|
+
}
|
|
113
|
+
function statusOf(err) {
|
|
114
|
+
if (typeof err !== "object" || err === null)
|
|
115
|
+
return undefined;
|
|
116
|
+
// `status_code` is the `ollama` SDK's ResponseError wire field — an
|
|
117
|
+
// external snake_case name, exempt from the camelCase rule.
|
|
118
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
119
|
+
const e = err;
|
|
120
|
+
if (typeof e.status === "number")
|
|
121
|
+
return e.status;
|
|
122
|
+
if (typeof e.status_code === "number")
|
|
123
|
+
return e.status_code;
|
|
124
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
function messageOf(err) {
|
|
128
|
+
if (err instanceof Error)
|
|
129
|
+
return err.message;
|
|
130
|
+
if (typeof err === "string")
|
|
131
|
+
return err;
|
|
132
|
+
return String(err);
|
|
133
|
+
}
|
|
134
|
+
const CONTEXT_OVERFLOW_PATTERN = /context (?:length|window)|maximum context|exceeds the (?:maximum )?context|too (?:many|long).*token|num_ctx/i;
|
|
135
|
+
const MODEL_NOT_FOUND_PATTERN = /model .* not found|not found, try pulling|no such model|pull(?:ing)? it/i;
|
|
136
|
+
/**
|
|
137
|
+
* Map an error surfaced by the `ollama` SDK (or an underlying `fetch`
|
|
138
|
+
* failure) to one of the framework-recognized provider error classes.
|
|
139
|
+
*
|
|
140
|
+
* The mapping is deliberately exhaustive on the cases the reviewer
|
|
141
|
+
* called out so they can't silently regress:
|
|
142
|
+
*
|
|
143
|
+
* - `ECONNREFUSED` → NonRetryable (daemon down; a retry
|
|
144
|
+
* won't bring it up within backoff).
|
|
145
|
+
* - model-not-pulled (404) → NonRetryable (`ollama pull` hint).
|
|
146
|
+
* - context-overflow/eval err → NonRetryable (deterministic; never
|
|
147
|
+
* SchemaValidationLlmError).
|
|
148
|
+
* - `ECONNRESET` / socket drop→ Transient.
|
|
149
|
+
* - cold-load / generic 5xx → Transient.
|
|
150
|
+
* - 429 → RateLimit (remote/proxy setups).
|
|
151
|
+
* - anything else → NonRetryable (safe fail-fast default).
|
|
152
|
+
*/
|
|
153
|
+
export function classifyOllamaError(err) {
|
|
154
|
+
const code = nodeCodeOf(err);
|
|
155
|
+
const status = statusOf(err);
|
|
156
|
+
const message = messageOf(err);
|
|
157
|
+
// Daemon unreachable — a connection refusal is the canonical
|
|
158
|
+
// "`ollama serve` isn't running on :11434" failure. A retry within
|
|
159
|
+
// the framework's short backoff won't bring it back up.
|
|
160
|
+
if (code === "ECONNREFUSED") {
|
|
161
|
+
return new NonRetryableLlmError({
|
|
162
|
+
message: `Cannot reach the Ollama daemon (${code}). Is \`ollama serve\` running on :11434? Original error: ${message}`,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// Mid-stream socket drop / transient connection loss — retryable.
|
|
166
|
+
if (code === "ECONNRESET" || code === "ETIMEDOUT" || code === "EPIPE") {
|
|
167
|
+
return new TransientLlmError({
|
|
168
|
+
message: `Transient connection error talking to the Ollama daemon (${code}): ${message}`,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
// Model not pulled — Ollama returns a 404 whose body says the model
|
|
172
|
+
// was not found. Deterministic until the user pulls it.
|
|
173
|
+
if (status === 404 || MODEL_NOT_FOUND_PATTERN.test(message)) {
|
|
174
|
+
return new NonRetryableLlmError({
|
|
175
|
+
message: `Ollama model not found. Run \`ollama pull <model>\` to download it first. Original error: ${message}`,
|
|
176
|
+
status,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
// Context-length overflow / model-eval error — DETERMINISTIC. Must
|
|
180
|
+
// be NonRetryable: routing this to SchemaValidationLlmError (tagged
|
|
181
|
+
// `transient`) would burn a guaranteed-failing second attempt on
|
|
182
|
+
// the same oversized prompt.
|
|
183
|
+
if (CONTEXT_OVERFLOW_PATTERN.test(message)) {
|
|
184
|
+
return new NonRetryableLlmError({
|
|
185
|
+
message: `Ollama request exceeded the model's context window (deterministic — retrying the same prompt will re-fail). Shorten the input or raise \`num_ctx\`. Original error: ${message}`,
|
|
186
|
+
status,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (status === 429) {
|
|
190
|
+
return new RateLimitLlmError({
|
|
191
|
+
message: `Ollama returned 429 (rate-limited; typical of a remote/proxied daemon): ${message}`,
|
|
192
|
+
status,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// Cold-model-load (model pulled but still loading into VRAM) and
|
|
196
|
+
// any other 5xx are transient — a retry after backoff can succeed
|
|
197
|
+
// once the model is resident.
|
|
198
|
+
if (status !== undefined && status >= 500) {
|
|
199
|
+
return new TransientLlmError({
|
|
200
|
+
message: `Ollama returned ${status.toString()} (possibly a cold model load into VRAM): ${message}`,
|
|
201
|
+
status,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// Safe default: fail fast rather than retry an unrecognized error.
|
|
205
|
+
return new NonRetryableLlmError({
|
|
206
|
+
message: `Unclassified Ollama error: ${message}`,
|
|
207
|
+
status,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/extensions/ollama/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { OllamaProvider } from "./provider.js";
|
|
2
|
+
export type { TOllamaProviderConfig, TOllamaClient, TOllamaChatRequest, TOllamaChatResponse, } from "./types.js";
|
|
3
|
+
export { typeboxToJsonSchema } from "./structured-output.js";
|
|
4
|
+
export type { TOllamaJsonSchema } from "./structured-output.js";
|
|
5
|
+
export { NonRetryableLlmError, RateLimitLlmError, SchemaValidationLlmError, ToolLoopExhaustedError, TransientLlmError, classifyOllamaError, } from "./errors.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/ollama/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,YAAY,EACR,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EACH,oBAAoB,EACpB,iBAAiB,EACjB,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,GACtB,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Barrel for the Ollama provider extension.
|
|
2
|
+
//
|
|
3
|
+
// Public surface consumed via the `@proposit/proposit-core/extensions/ollama`
|
|
4
|
+
// subpath export: the provider constructor + its config type + the
|
|
5
|
+
// standard-JSON-schema converter + the error classes (which callers may
|
|
6
|
+
// `instanceof`-match for finer-grained observability).
|
|
7
|
+
//
|
|
8
|
+
// NOTE: the error class names (`NonRetryableLlmError`, …) intentionally
|
|
9
|
+
// mirror the OpenAI provider's names but are *distinct* classes living
|
|
10
|
+
// in this extension. They are surfaced only from this subpath (NOT the
|
|
11
|
+
// package root) to avoid colliding with the root-exported OpenAI error
|
|
12
|
+
// classes. The framework classifies by the `retryReason` tag, not class
|
|
13
|
+
// identity, so the duplication is intentional and harmless.
|
|
14
|
+
export { OllamaProvider } from "./provider.js";
|
|
15
|
+
export { typeboxToJsonSchema } from "./structured-output.js";
|
|
16
|
+
export { NonRetryableLlmError, RateLimitLlmError, SchemaValidationLlmError, ToolLoopExhaustedError, TransientLlmError, classifyOllamaError, } from "./errors.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/ollama/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,8EAA8E;AAC9E,mEAAmE;AACnE,wEAAwE;AACxE,uDAAuD;AACvD,EAAE;AACF,wEAAwE;AACxE,uEAAuE;AACvE,uEAAuE;AACvE,uEAAuE;AACvE,wEAAwE;AACxE,4DAA4D;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAO9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAE5D,OAAO,EACH,oBAAoB,EACpB,iBAAiB,EACjB,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,GACtB,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TLlmProvider, TLlmRequest, TLlmResponse } from "../../lib/llm/types.js";
|
|
2
|
+
import type { TOllamaProviderConfig } from "./types.js";
|
|
3
|
+
export declare class OllamaProvider implements TLlmProvider {
|
|
4
|
+
private readonly config;
|
|
5
|
+
private clientPromise;
|
|
6
|
+
private readonly maxToolRounds;
|
|
7
|
+
private readonly numCtx;
|
|
8
|
+
constructor(config?: TOllamaProviderConfig);
|
|
9
|
+
respond<T>(req: TLlmRequest<T>): Promise<TLlmResponse<T>>;
|
|
10
|
+
private runChatLoop;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the SDK client: the injected one, or a freshly imported
|
|
13
|
+
* `Ollama` instance. Memoized so the dynamic import + construction
|
|
14
|
+
* runs at most once.
|
|
15
|
+
*/
|
|
16
|
+
private getClient;
|
|
17
|
+
private importAndConstructClient;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/extensions/ollama/provider.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EACR,YAAY,EACZ,WAAW,EACX,YAAY,EAGf,MAAM,wBAAwB,CAAA;AAa/B,OAAO,KAAK,EAKR,qBAAqB,EAExB,MAAM,YAAY,CAAA;AAYnB,qBAAa,cAAe,YAAW,YAAY;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAsC;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;gBAEnB,MAAM,CAAC,EAAE,qBAAqB;IAOpC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAmCjD,WAAW;IAgJzB;;;;OAIG;IACH,OAAO,CAAC,SAAS;YAQH,wBAAwB;CAiBzC"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// Concrete `TLlmProvider` backed by a local Ollama daemon via the
|
|
2
|
+
// official `ollama` npm SDK.
|
|
3
|
+
//
|
|
4
|
+
// Dev/test only — production stays on OpenAI. The provider exists so a
|
|
5
|
+
// developer can run the entire LLM-backed stack (notably the v2
|
|
6
|
+
// argument-ingestion pipeline) against a self-hosted model
|
|
7
|
+
// (`qwen3.6:latest`) with zero API cost.
|
|
8
|
+
//
|
|
9
|
+
// Deliberate divergences from the in-repo OpenAI provider:
|
|
10
|
+
// * Uses the official `ollama` SDK (an optional peer) rather than raw
|
|
11
|
+
// `fetch`. A missing package surfaces as an actionable error at
|
|
12
|
+
// construction time (dynamic-import-or-throw).
|
|
13
|
+
// * Structured output goes through the Ollama provider's own
|
|
14
|
+
// standard-JSON-schema converter (`./structured-output.ts`), not
|
|
15
|
+
// the OpenAI strict-mode converter.
|
|
16
|
+
// * `reasoningEffort` is ignored (no Ollama analogue);
|
|
17
|
+
// `maxOutputTokens` maps to `options.num_predict` (positive values
|
|
18
|
+
// only — never 0; -1/-2 are Ollama sentinels we never emit).
|
|
19
|
+
// * Errors are classified by `./errors.ts` #classifyOllamaError, which
|
|
20
|
+
// carries the same `retryReason` tags + lib failure-codes as the
|
|
21
|
+
// OpenAI provider. No `ollama → openai` dependency, no lib change.
|
|
22
|
+
//
|
|
23
|
+
// `AbortSignal` is honored by registering an abort listener that calls
|
|
24
|
+
// the SDK client's `abort()`; the SDK then rejects the in-flight
|
|
25
|
+
// `chat()` with an `AbortError`, which the provider re-throws verbatim
|
|
26
|
+
// so `llmStage`'s mid-flight-abort detector marks the stage `skipped`.
|
|
27
|
+
import { debugLlmFailure, debugLlmRequest, debugLlmResponse, } from "../../lib/pipelines/debug-log.js";
|
|
28
|
+
import { typeboxToJsonSchema } from "./structured-output.js";
|
|
29
|
+
import { NonRetryableLlmError, SchemaValidationLlmError, ToolLoopExhaustedError, classifyOllamaError, } from "./errors.js";
|
|
30
|
+
const STAGE_ID_MARKER = /<!--\s*stage-id:\s*([^\s>]+)\s*-->/;
|
|
31
|
+
const DEFAULT_BASE_URL = "http://localhost:11434";
|
|
32
|
+
const DEFAULT_MAX_TOOL_ROUNDS = 6;
|
|
33
|
+
// Generous default context window. Ollama silently truncates prompts
|
|
34
|
+
// longer than `num_ctx` (no error — the model emits schema-valid JSON
|
|
35
|
+
// from a truncated prompt), and its per-model default is often ~4096,
|
|
36
|
+
// well under a real multi-KB ingestion prompt. See `TOllamaProviderConfig.numCtx`.
|
|
37
|
+
const DEFAULT_NUM_CTX = 32768;
|
|
38
|
+
export class OllamaProvider {
|
|
39
|
+
config;
|
|
40
|
+
clientPromise = null;
|
|
41
|
+
maxToolRounds;
|
|
42
|
+
numCtx;
|
|
43
|
+
constructor(config) {
|
|
44
|
+
this.config = config ?? {};
|
|
45
|
+
this.maxToolRounds =
|
|
46
|
+
this.config.maxToolCallRounds ?? DEFAULT_MAX_TOOL_ROUNDS;
|
|
47
|
+
this.numCtx = this.config.numCtx ?? DEFAULT_NUM_CTX;
|
|
48
|
+
}
|
|
49
|
+
async respond(req) {
|
|
50
|
+
// Already-aborted short-circuit — don't even construct the
|
|
51
|
+
// client or call the daemon.
|
|
52
|
+
if (req.signal?.aborted) {
|
|
53
|
+
throw abortError();
|
|
54
|
+
}
|
|
55
|
+
const client = await this.getClient();
|
|
56
|
+
const convertedSchema = typeboxToJsonSchema(req.outputSchema);
|
|
57
|
+
const tools = req.tools ? translateTools(req.tools) : undefined;
|
|
58
|
+
const stageIdMatch = STAGE_ID_MARKER.exec(req.systemPrompt);
|
|
59
|
+
const debugStageId = stageIdMatch ? stageIdMatch[1] : null;
|
|
60
|
+
// Wire the AbortSignal to the SDK client's abort(). The SDK
|
|
61
|
+
// rejects the in-flight chat() with an AbortError when this
|
|
62
|
+
// fires.
|
|
63
|
+
const onAbort = () => {
|
|
64
|
+
client.abort();
|
|
65
|
+
};
|
|
66
|
+
req.signal?.addEventListener("abort", onAbort, { once: true });
|
|
67
|
+
try {
|
|
68
|
+
return await this.runChatLoop({
|
|
69
|
+
client,
|
|
70
|
+
req,
|
|
71
|
+
convertedSchema,
|
|
72
|
+
tools,
|
|
73
|
+
debugStageId,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
req.signal?.removeEventListener("abort", onAbort);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async runChatLoop(args) {
|
|
81
|
+
const { client, req, convertedSchema, tools, debugStageId } = args;
|
|
82
|
+
// Running message array. Tool-call rounds append the model's
|
|
83
|
+
// tool_calls echo + the tool result before re-calling.
|
|
84
|
+
const messages = [
|
|
85
|
+
{ role: "system", content: req.systemPrompt },
|
|
86
|
+
{ role: "user", content: req.userMessage },
|
|
87
|
+
];
|
|
88
|
+
let lastUsage = { input: 0, output: 0 };
|
|
89
|
+
for (let round = 0; round < this.maxToolRounds; round += 1) {
|
|
90
|
+
const chatRequest = {
|
|
91
|
+
model: req.model,
|
|
92
|
+
messages,
|
|
93
|
+
// Build `format` from the single converted object so the
|
|
94
|
+
// schema can't drift from any prompt-grounding copy.
|
|
95
|
+
format: convertedSchema,
|
|
96
|
+
stream: false,
|
|
97
|
+
};
|
|
98
|
+
if (tools) {
|
|
99
|
+
chatRequest.tools = tools;
|
|
100
|
+
}
|
|
101
|
+
// `temperature: 0` for deterministic structured output;
|
|
102
|
+
// `num_ctx` set generously so Ollama doesn't silently
|
|
103
|
+
// truncate a real multi-KB ingestion prompt (its per-model
|
|
104
|
+
// default is often ~4096). `maxOutputTokens` → num_predict,
|
|
105
|
+
// positive only: 0 means "generate nothing"; -1/-2 are Ollama
|
|
106
|
+
// sentinels we never emit.
|
|
107
|
+
const options = {
|
|
108
|
+
temperature: 0,
|
|
109
|
+
num_ctx: this.numCtx,
|
|
110
|
+
};
|
|
111
|
+
if (req.maxOutputTokens !== undefined && req.maxOutputTokens > 0) {
|
|
112
|
+
options.num_predict = req.maxOutputTokens;
|
|
113
|
+
}
|
|
114
|
+
chatRequest.options = options;
|
|
115
|
+
debugLlmRequest({
|
|
116
|
+
stageId: debugStageId,
|
|
117
|
+
model: req.model,
|
|
118
|
+
maxOutputTokens: req.maxOutputTokens,
|
|
119
|
+
reasoningEffort: req.reasoningEffort,
|
|
120
|
+
systemPromptLen: req.systemPrompt.length,
|
|
121
|
+
userMessageLen: req.userMessage.length,
|
|
122
|
+
systemPromptHead: req.systemPrompt,
|
|
123
|
+
userMessageHead: req.userMessage,
|
|
124
|
+
});
|
|
125
|
+
let response;
|
|
126
|
+
try {
|
|
127
|
+
response = await client.chat(chatRequest);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
// Mid-flight abort: the SDK rejects with an AbortError
|
|
131
|
+
// when our signal listener called client.abort().
|
|
132
|
+
// Re-throw verbatim so llmStage marks the stage skipped.
|
|
133
|
+
if (isAbortError(err) || req.signal?.aborted) {
|
|
134
|
+
throw abortError();
|
|
135
|
+
}
|
|
136
|
+
const classified = classifyOllamaError(err);
|
|
137
|
+
debugLlmFailure({
|
|
138
|
+
stageId: debugStageId,
|
|
139
|
+
model: req.model,
|
|
140
|
+
errorName: classified.name,
|
|
141
|
+
errorMessage: classified.message,
|
|
142
|
+
tokenUsage: lastUsage,
|
|
143
|
+
});
|
|
144
|
+
throw classified;
|
|
145
|
+
}
|
|
146
|
+
lastUsage = mergeUsage(lastUsage, {
|
|
147
|
+
input: response.prompt_eval_count ?? 0,
|
|
148
|
+
output: response.eval_count ?? 0,
|
|
149
|
+
});
|
|
150
|
+
const toolCalls = response.message.tool_calls ?? [];
|
|
151
|
+
if (toolCalls.length > 0) {
|
|
152
|
+
// Echo the assistant tool-call message, then append one
|
|
153
|
+
// tool-result message per call before looping.
|
|
154
|
+
messages.push({
|
|
155
|
+
role: "assistant",
|
|
156
|
+
content: response.message.content,
|
|
157
|
+
tool_calls: toolCalls,
|
|
158
|
+
});
|
|
159
|
+
for (const call of toolCalls) {
|
|
160
|
+
const handler = findFunctionHandler(req.tools, call.function.name);
|
|
161
|
+
if (!handler) {
|
|
162
|
+
throw new NonRetryableLlmError({
|
|
163
|
+
message: `Ollama requested unknown function tool "${call.function.name}".`,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
const handlerResult = await handler.handler(call.function.arguments);
|
|
167
|
+
messages.push({
|
|
168
|
+
role: "tool",
|
|
169
|
+
content: typeof handlerResult === "string"
|
|
170
|
+
? handlerResult
|
|
171
|
+
: JSON.stringify(handlerResult),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const text = response.message.content;
|
|
177
|
+
if (text === undefined || text === "") {
|
|
178
|
+
throw new SchemaValidationLlmError({
|
|
179
|
+
message: "Ollama chat response carried no assistant text content.",
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const parsed = safeParseJson(text);
|
|
183
|
+
debugLlmResponse({
|
|
184
|
+
stageId: debugStageId,
|
|
185
|
+
outputTextLen: text.length,
|
|
186
|
+
tokenUsage: lastUsage,
|
|
187
|
+
});
|
|
188
|
+
return {
|
|
189
|
+
output: parsed,
|
|
190
|
+
tokenUsage: lastUsage,
|
|
191
|
+
// The Ollama chat response is not request-id-bearing;
|
|
192
|
+
// `rawResponseId` is optional, so leaving it undefined is
|
|
193
|
+
// contract-legal. Do not fabricate one.
|
|
194
|
+
rawResponseId: undefined,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
throw new ToolLoopExhaustedError({
|
|
198
|
+
message: `Function-tool agent loop exceeded ${this.maxToolRounds.toString()} rounds without a final response.`,
|
|
199
|
+
rounds: this.maxToolRounds,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Resolve the SDK client: the injected one, or a freshly imported
|
|
204
|
+
* `Ollama` instance. Memoized so the dynamic import + construction
|
|
205
|
+
* runs at most once.
|
|
206
|
+
*/
|
|
207
|
+
getClient() {
|
|
208
|
+
if (this.config.client) {
|
|
209
|
+
return Promise.resolve(this.config.client);
|
|
210
|
+
}
|
|
211
|
+
this.clientPromise ??= this.importAndConstructClient();
|
|
212
|
+
return this.clientPromise;
|
|
213
|
+
}
|
|
214
|
+
async importAndConstructClient() {
|
|
215
|
+
const baseUrl = this.config.baseUrl ?? DEFAULT_BASE_URL;
|
|
216
|
+
let mod;
|
|
217
|
+
try {
|
|
218
|
+
mod = (await import("ollama"));
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
throw new Error("OllamaProvider: the optional `ollama` package is not installed. " +
|
|
222
|
+
"Run `pnpm add ollama` (it is declared as an optional peerDependency) " +
|
|
223
|
+
"or pass a pre-built `client` via the provider config. " +
|
|
224
|
+
`Original import error: ${err instanceof Error ? err.message : String(err)}`);
|
|
225
|
+
}
|
|
226
|
+
return new mod.Ollama({ host: baseUrl });
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// -- helpers --------------------------------------------------------------
|
|
230
|
+
function abortError() {
|
|
231
|
+
const e = new Error("The Ollama request was aborted.");
|
|
232
|
+
e.name = "AbortError";
|
|
233
|
+
return e;
|
|
234
|
+
}
|
|
235
|
+
function isAbortError(err) {
|
|
236
|
+
return (typeof err === "object" &&
|
|
237
|
+
err !== null &&
|
|
238
|
+
err.name === "AbortError");
|
|
239
|
+
}
|
|
240
|
+
function safeParseJson(raw) {
|
|
241
|
+
try {
|
|
242
|
+
return JSON.parse(raw);
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
throw new SchemaValidationLlmError({
|
|
246
|
+
message: `Ollama returned malformed JSON in structured-output content: ${err instanceof Error ? err.message : String(err)}`,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function mergeUsage(accumulated, next) {
|
|
251
|
+
return {
|
|
252
|
+
input: accumulated.input + next.input,
|
|
253
|
+
output: accumulated.output + next.output,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function translateTools(tools) {
|
|
257
|
+
return tools.map((tool) => {
|
|
258
|
+
if (tool.kind === "function") {
|
|
259
|
+
return {
|
|
260
|
+
type: "function",
|
|
261
|
+
function: {
|
|
262
|
+
name: tool.name,
|
|
263
|
+
description: tool.description,
|
|
264
|
+
parameters: typeboxToJsonSchema(tool.parameters),
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
// Hosted-tool kinds (web_search / file_search / mcp) have no
|
|
269
|
+
// local Ollama equivalent. Fail fast and legibly.
|
|
270
|
+
throw new NonRetryableLlmError({
|
|
271
|
+
message: `Tool kind "${tool.kind}" is not supported by the Ollama provider. Only kind "function" (local handler) is supported.`,
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
function findFunctionHandler(tools, name) {
|
|
276
|
+
if (!tools)
|
|
277
|
+
return undefined;
|
|
278
|
+
for (const tool of tools) {
|
|
279
|
+
if (tool.kind === "function" && tool.name === name) {
|
|
280
|
+
return tool;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/extensions/ollama/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TSchema } from "typebox";
|
|
2
|
+
/**
|
|
3
|
+
* The output shape is intentionally typed as a plain object literal
|
|
4
|
+
* (not a full JSON-Schema TS type). Ollama's `format` accepts this
|
|
5
|
+
* shape and we round-trip it through the SDK request body. Keeping the
|
|
6
|
+
* return type loose avoids dragging a JSON-Schema dependency into the
|
|
7
|
+
* converter.
|
|
8
|
+
*/
|
|
9
|
+
export type TOllamaJsonSchema = Record<string, unknown>;
|
|
10
|
+
/**
|
|
11
|
+
* Convert a TypeBox schema into a standard JSON Schema document
|
|
12
|
+
* suitable for Ollama's `format` parameter.
|
|
13
|
+
*
|
|
14
|
+
* Throws `UnsupportedSchemaError` when the source schema contains a
|
|
15
|
+
* TypeBox primitive outside the supported subset.
|
|
16
|
+
*/
|
|
17
|
+
export declare function typeboxToJsonSchema(schema: TSchema): TOllamaJsonSchema;
|
|
18
|
+
//# sourceMappingURL=structured-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-output.d.ts","sourceRoot":"","sources":["../../../src/extensions/ollama/structured-output.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AA6BvD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,iBAAiB,CA0BtE"}
|