@nemesis-oss/ollama-sdk 1.7.0 → 1.8.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 (39) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/dist/anthropic-B_UXplNF.d.ts +1647 -0
  3. package/dist/anthropic-CVDFy_a0.d.cts +1647 -0
  4. package/dist/generated-api.cjs +74 -6
  5. package/dist/generated-api.cjs.map +1 -1
  6. package/dist/generated-api.d.cts +230 -629
  7. package/dist/generated-api.d.ts +230 -629
  8. package/dist/generated-api.js +72 -7
  9. package/dist/generated-api.js.map +1 -1
  10. package/dist/generated-models-schemas.cjs +89 -1
  11. package/dist/generated-models-schemas.cjs.map +1 -1
  12. package/dist/generated-models-schemas.d.cts +121 -1
  13. package/dist/generated-models-schemas.d.ts +121 -1
  14. package/dist/generated-models-schemas.js +79 -2
  15. package/dist/generated-models-schemas.js.map +1 -1
  16. package/dist/generated-runtime.cjs +576 -57
  17. package/dist/generated-runtime.cjs.map +1 -1
  18. package/dist/generated-runtime.d.cts +21 -23
  19. package/dist/generated-runtime.d.ts +21 -23
  20. package/dist/generated-runtime.js +575 -58
  21. package/dist/generated-runtime.js.map +1 -1
  22. package/dist/index.cjs +1078 -75
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +378 -874
  25. package/dist/index.d.ts +378 -874
  26. package/dist/index.js +1075 -76
  27. package/dist/index.js.map +1 -1
  28. package/dist/mcp/tools.json +287 -73
  29. package/dist/mcp-generated.cjs +96 -7
  30. package/dist/mcp-generated.cjs.map +1 -1
  31. package/dist/mcp-generated.d.cts +1 -1
  32. package/dist/mcp-generated.d.ts +1 -1
  33. package/dist/mcp-generated.js +96 -7
  34. package/dist/mcp-generated.js.map +1 -1
  35. package/dist/{runtime-qwD72cpn.d.ts → runtime-C6UYtBRB.d.ts} +218 -4
  36. package/dist/{runtime-bQ48I-RC.d.cts → runtime-DTmUeU6K.d.cts} +218 -4
  37. package/dist/skills.cjs.map +1 -1
  38. package/dist/skills.js.map +1 -1
  39. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -182,6 +182,35 @@ var OllamaRequestValidationError = class extends OllamaClientError {
182
182
  this.issues = options.issues;
183
183
  }
184
184
  };
185
+ var OllamaRequestTooLargeError = class extends OllamaClientError {
186
+ operationId;
187
+ actualBytes;
188
+ maxBytes;
189
+ constructor(message, options) {
190
+ super(message, { ...options, code: "request_too_large", retryable: false, status: 413 });
191
+ this.operationId = options.operationId;
192
+ this.actualBytes = options.actualBytes;
193
+ this.maxBytes = options.maxBytes;
194
+ }
195
+ };
196
+ var OllamaResponseValidationError = class extends OllamaClientError {
197
+ operationId;
198
+ issues;
199
+ constructor(message, options) {
200
+ super(message, { ...options, code: "response_validation_error", retryable: false });
201
+ this.operationId = options.operationId;
202
+ this.issues = options.issues;
203
+ }
204
+ };
205
+ var OllamaServerVersionUnknownError = class extends OllamaClientError {
206
+ operationId;
207
+ minRequiredVersion;
208
+ constructor(message, options) {
209
+ super(message, { ...options, code: "server_version_unknown", retryable: false });
210
+ this.operationId = options.operationId;
211
+ this.minRequiredVersion = options.minRequiredVersion;
212
+ }
213
+ };
185
214
  var OllamaToolTimeoutError = class extends OllamaClientError {
186
215
  toolName;
187
216
  timeoutMs;
@@ -1885,8 +1914,9 @@ var ModelsClient = class {
1885
1914
  { singleEndpoint: true }
1886
1915
  );
1887
1916
  return true;
1888
- } catch {
1889
- return false;
1917
+ } catch (err) {
1918
+ if (err instanceof OllamaNotFoundError) return false;
1919
+ throw err;
1890
1920
  }
1891
1921
  }
1892
1922
  };
@@ -2796,28 +2826,45 @@ var ChatRequestSchema = z.object({
2796
2826
  logprobs: z.boolean().optional(),
2797
2827
  top_logprobs: z.number().optional()
2798
2828
  });
2799
- var GenerateRequestSchema = z.object({
2800
- model: z.string(),
2801
- prompt: z.string().optional(),
2802
- suffix: z.string().optional(),
2803
- images: z.array(z.string()).optional(),
2804
- format: z.union([z.string(), z.object({})]).optional(),
2805
- system: z.string().optional(),
2806
- stream: z.boolean().optional(),
2807
- think: ThinkValueSchema.optional(),
2808
- raw: z.boolean().optional(),
2809
- keep_alive: z.union([z.string(), z.number()]).optional(),
2810
- options: ModelOptionsSchema.optional(),
2811
- logprobs: z.boolean().optional(),
2812
- top_logprobs: z.number().optional()
2829
+ var TokenLogprobSchema = z.object({
2830
+ token: z.string().optional(),
2831
+ logprob: z.number().optional(),
2832
+ bytes: z.array(z.number()).optional()
2813
2833
  });
2814
- var EmbedRequestSchema = z.object({
2815
- model: z.string(),
2816
- input: z.union([z.string(), z.array(z.string())]),
2817
- truncate: z.boolean().optional(),
2818
- dimensions: z.number().optional(),
2819
- keep_alive: z.string().optional(),
2820
- options: ModelOptionsSchema.optional()
2834
+
2835
+ // src/generated/models/Logprob.schema.ts
2836
+ var LogprobSchema = z.object({
2837
+ token: z.string().optional(),
2838
+ logprob: z.number().optional(),
2839
+ bytes: z.array(z.number()).optional(),
2840
+ top_logprobs: z.array(TokenLogprobSchema).optional()
2841
+ });
2842
+
2843
+ // src/generated/models/ChatResponse.schema.ts
2844
+ var ChatResponseSchema = z.object({
2845
+ model: z.string().optional(),
2846
+ created_at: z.string().optional(),
2847
+ message: z.object({
2848
+ role: z.enum(["assistant"]).optional(),
2849
+ content: z.string().optional(),
2850
+ thinking: z.string().optional(),
2851
+ tool_calls: z.array(ToolCallSchema).optional(),
2852
+ images: z.array(z.string()).optional()
2853
+ }).optional(),
2854
+ done: z.boolean().optional(),
2855
+ done_reason: z.string().optional(),
2856
+ total_duration: z.number().optional(),
2857
+ load_duration: z.number().optional(),
2858
+ prompt_eval_count: z.number().optional(),
2859
+ prompt_eval_cached_count: z.number().optional(),
2860
+ prompt_eval_duration: z.number().optional(),
2861
+ eval_count: z.number().optional(),
2862
+ eval_duration: z.number().optional(),
2863
+ logprobs: z.array(LogprobSchema).optional()
2864
+ });
2865
+ var CopyRequestSchema = z.object({
2866
+ source: z.string(),
2867
+ destination: z.string()
2821
2868
  });
2822
2869
  var CreateRequestSchema = z.object({
2823
2870
  model: z.string(),
@@ -2836,13 +2883,91 @@ var CreateRequestSchema = z.object({
2836
2883
  requires: z.string().optional(),
2837
2884
  stream: z.boolean().optional()
2838
2885
  });
2839
- var CopyRequestSchema = z.object({
2840
- source: z.string(),
2841
- destination: z.string()
2842
- });
2843
2886
  var DeleteRequestSchema = z.object({
2844
2887
  model: z.string()
2845
2888
  });
2889
+ var EmbedRequestSchema = z.object({
2890
+ model: z.string(),
2891
+ input: z.union([z.string(), z.array(z.string())]),
2892
+ truncate: z.boolean().optional(),
2893
+ dimensions: z.number().optional(),
2894
+ keep_alive: z.string().optional(),
2895
+ options: ModelOptionsSchema.optional()
2896
+ });
2897
+ var EmbedResponseSchema = z.object({
2898
+ model: z.string().optional(),
2899
+ embeddings: z.array(z.array(z.number())).optional(),
2900
+ total_duration: z.number().optional(),
2901
+ load_duration: z.number().optional(),
2902
+ prompt_eval_count: z.number().optional()
2903
+ });
2904
+ var GenerateRequestSchema = z.object({
2905
+ model: z.string(),
2906
+ prompt: z.string().optional(),
2907
+ suffix: z.string().optional(),
2908
+ images: z.array(z.string()).optional(),
2909
+ format: z.union([z.string(), z.object({})]).optional(),
2910
+ system: z.string().optional(),
2911
+ stream: z.boolean().optional(),
2912
+ think: ThinkValueSchema.optional(),
2913
+ raw: z.boolean().optional(),
2914
+ keep_alive: z.union([z.string(), z.number()]).optional(),
2915
+ options: ModelOptionsSchema.optional(),
2916
+ logprobs: z.boolean().optional(),
2917
+ top_logprobs: z.number().optional()
2918
+ });
2919
+ var GenerateResponseSchema = z.object({
2920
+ model: z.string().optional(),
2921
+ created_at: z.string().optional(),
2922
+ response: z.string().optional(),
2923
+ thinking: z.string().optional(),
2924
+ done: z.boolean().optional(),
2925
+ done_reason: z.string().optional(),
2926
+ total_duration: z.number().optional(),
2927
+ load_duration: z.number().optional(),
2928
+ prompt_eval_count: z.number().optional(),
2929
+ prompt_eval_cached_count: z.number().optional(),
2930
+ prompt_eval_duration: z.number().optional(),
2931
+ eval_count: z.number().optional(),
2932
+ eval_duration: z.number().optional(),
2933
+ logprobs: z.array(LogprobSchema).optional()
2934
+ });
2935
+ var ModelSummarySchema = z.object({
2936
+ name: z.string().optional(),
2937
+ model: z.string().optional(),
2938
+ remote_model: z.string().optional(),
2939
+ remote_host: z.string().optional(),
2940
+ modified_at: z.string().optional(),
2941
+ size: z.number().optional(),
2942
+ digest: z.string().optional(),
2943
+ details: z.object({
2944
+ format: z.string().optional(),
2945
+ family: z.string().optional(),
2946
+ families: z.array(z.string()).optional(),
2947
+ parameter_size: z.string().optional(),
2948
+ quantization_level: z.string().optional()
2949
+ }).optional()
2950
+ });
2951
+
2952
+ // src/generated/models/ListResponse.schema.ts
2953
+ var ListResponseSchema = z.object({
2954
+ models: z.array(ModelSummarySchema).optional()
2955
+ });
2956
+ var PsSchema = z.object({
2957
+ name: z.string().optional(),
2958
+ model: z.string().optional(),
2959
+ size: z.number().optional(),
2960
+ digest: z.string().optional(),
2961
+ details: z.object({}).optional(),
2962
+ expires_at: z.string().optional(),
2963
+ size_vram: z.number().optional(),
2964
+ context_length: z.number().optional()
2965
+ });
2966
+
2967
+ // src/generated/models/PsResponse.schema.ts
2968
+ var PsResponseSchema = z.object({
2969
+ models: z.array(PsSchema).optional()
2970
+ });
2846
2971
  var PullRequestSchema = z.object({
2847
2972
  model: z.string(),
2848
2973
  insecure: z.boolean().optional(),
@@ -2857,27 +2982,164 @@ var ShowRequestSchema = z.object({
2857
2982
  model: z.string(),
2858
2983
  verbose: z.boolean().optional()
2859
2984
  });
2985
+ var ThinkingSchema = z.object({
2986
+ values: z.array(z.union([z.boolean(), z.string()])),
2987
+ default: z.union([z.boolean(), z.string()])
2988
+ });
2989
+
2990
+ // src/generated/models/ShowResponse.schema.ts
2991
+ var ShowResponseSchema = z.object({
2992
+ thinking: ThinkingSchema.optional(),
2993
+ parameters: z.string().optional(),
2994
+ license: z.string().optional(),
2995
+ modified_at: z.string().optional(),
2996
+ details: z.object({}).optional(),
2997
+ template: z.string().optional(),
2998
+ capabilities: z.array(z.string()).optional(),
2999
+ model_info: z.object({}).optional()
3000
+ });
3001
+ var StatusResponseSchema = z.object({
3002
+ status: z.string().optional()
3003
+ });
3004
+ var SystemOneContentSchema = z.union([
3005
+ z.string().regex(new RegExp("\\S")),
3006
+ z.object({}).catchall(z.unknown()),
3007
+ z.array(z.unknown())
3008
+ ]);
3009
+
3010
+ // src/generated/models/SystemOneChoiceQuestion.schema.ts
3011
+ var SystemOneChoiceQuestionSchema = z.object({
3012
+ type: z.enum(["choice"]),
3013
+ instructions: SystemOneContentSchema,
3014
+ criteria: z.object({}).catchall(z.union([z.string(), z.null()])).refine((v) => Object.keys(v).length >= 2, { message: "must have at least 2 properties" }).refine((v) => Object.keys(v).length <= 26, { message: "must have at most 26 properties" }).refine((v) => Object.keys(v).every((k) => new RegExp("\\S").test(k)), {
3015
+ message: 'property names must match pattern "\\S"'
3016
+ })
3017
+ });
3018
+ var SystemOneNoulQuestionSchema = z.object({
3019
+ type: z.enum(["noul"]),
3020
+ instructions: SystemOneContentSchema,
3021
+ criteria: z.object({
3022
+ false: z.string().optional(),
3023
+ true: z.string().optional()
3024
+ }).optional()
3025
+ });
3026
+ var SystemOneScoreQuestionSchema = z.object({
3027
+ type: z.enum(["score"]),
3028
+ instructions: SystemOneContentSchema,
3029
+ criteria: z.array(z.string()).min(2).max(26)
3030
+ });
3031
+
3032
+ // src/generated/models/SystemOneRequest.schema.ts
3033
+ var SystemOneRequestSchema = z.object({
3034
+ model: z.string().regex(new RegExp("\\S")),
3035
+ state: SystemOneContentSchema,
3036
+ images: z.array(z.string()).optional(),
3037
+ questions: z.object({}).catchall(
3038
+ z.union([
3039
+ SystemOneChoiceQuestionSchema,
3040
+ SystemOneNoulQuestionSchema,
3041
+ SystemOneScoreQuestionSchema
3042
+ ])
3043
+ ).refine((v) => Object.keys(v).length >= 1, { message: "must have at least 1 properties" }).refine((v) => Object.keys(v).length <= 64, { message: "must have at most 64 properties" }).refine((v) => Object.keys(v).every((k) => new RegExp("\\S").test(k)), {
3044
+ message: 'property names must match pattern "\\S"'
3045
+ }),
3046
+ keep_alive: z.union([z.string(), z.number()]).optional()
3047
+ });
3048
+ var SystemOneConfidenceSchema = z.number().min(0).max(1);
3049
+ var SystemOneProbabilitiesSchema = z.object({}).catchall(z.number().min(0).max(1));
3050
+
3051
+ // src/generated/models/SystemOneChoiceAnswer.schema.ts
3052
+ var SystemOneChoiceAnswerSchema = z.object({
3053
+ type: z.enum(["choice"]),
3054
+ choice: z.string(),
3055
+ probabilities: SystemOneProbabilitiesSchema,
3056
+ confidence: SystemOneConfidenceSchema
3057
+ });
3058
+ var SystemOneNoulAnswerSchema = z.object({
3059
+ type: z.enum(["noul"]),
3060
+ noul: z.number().min(0).max(1)
3061
+ });
3062
+ var SystemOneScoreAnswerSchema = z.object({
3063
+ type: z.enum(["score"]),
3064
+ score: z.number().min(0).max(25),
3065
+ legend: z.object({}).catchall(z.string()),
3066
+ probabilities: SystemOneProbabilitiesSchema,
3067
+ confidence: SystemOneConfidenceSchema
3068
+ });
3069
+
3070
+ // src/generated/models/SystemOneResponse.schema.ts
3071
+ var SystemOneResponseSchema = z.object({
3072
+ model: z.string(),
3073
+ answers: z.object({}).catchall(
3074
+ z.union([SystemOneChoiceAnswerSchema, SystemOneNoulAnswerSchema, SystemOneScoreAnswerSchema])
3075
+ ),
3076
+ usage: z.object({
3077
+ input_tokens: z.number().min(0),
3078
+ output_tokens: z.number().min(0)
3079
+ })
3080
+ });
3081
+ var VersionResponseSchema = z.object({
3082
+ version: z.string().optional()
3083
+ });
3084
+ var WebFetchRequestSchema = z.object({
3085
+ url: z.string()
3086
+ });
3087
+ var WebFetchResponseSchema = z.object({
3088
+ title: z.string().optional(),
3089
+ content: z.string().optional(),
3090
+ links: z.array(z.string()).optional()
3091
+ });
3092
+ var WebSearchRequestSchema = z.object({
3093
+ query: z.string(),
3094
+ max_results: z.number().min(1).max(10).optional()
3095
+ });
3096
+ var WebSearchResultSchema = z.object({
3097
+ title: z.string().optional(),
3098
+ url: z.string().optional(),
3099
+ content: z.string().optional()
3100
+ });
3101
+
3102
+ // src/generated/models/WebSearchResponse.schema.ts
3103
+ var WebSearchResponseSchema = z.object({
3104
+ results: z.array(WebSearchResultSchema).optional()
3105
+ });
2860
3106
 
2861
3107
  // src/generated/runtime/schema-registry.ts
2862
3108
  var requestSchemas = {
2863
3109
  chat: ChatRequestSchema,
2864
- generate: GenerateRequestSchema,
2865
- embed: EmbedRequestSchema,
2866
- create: CreateRequestSchema,
2867
3110
  copy: CopyRequestSchema,
3111
+ create: CreateRequestSchema,
2868
3112
  delete: DeleteRequestSchema,
3113
+ embed: EmbedRequestSchema,
3114
+ generate: GenerateRequestSchema,
2869
3115
  pull: PullRequestSchema,
2870
3116
  push: PushRequestSchema,
2871
- show: ShowRequestSchema
2872
- // Operations without a registered request schema (blobs, ps, tags,
2873
- // version, systemOne, openai*, anthropic*) skip validation. This is
2874
- // deliberate — the OpenAPI spec doesn't define request bodies for
2875
- // GET/HEAD operations, and the compat-surface request schemas (OpenAI,
2876
- // Anthropic) are richer than what the IR currently models.
3117
+ show: ShowRequestSchema,
3118
+ systemOne: SystemOneRequestSchema,
3119
+ webFetch: WebFetchRequestSchema,
3120
+ webSearch: WebSearchRequestSchema
3121
+ };
3122
+ var responseSchemas = {
3123
+ chat: ChatResponseSchema,
3124
+ create: StatusResponseSchema,
3125
+ embed: EmbedResponseSchema,
3126
+ generate: GenerateResponseSchema,
3127
+ ps: PsResponseSchema,
3128
+ pull: StatusResponseSchema,
3129
+ push: StatusResponseSchema,
3130
+ show: ShowResponseSchema,
3131
+ systemOne: SystemOneResponseSchema,
3132
+ tags: ListResponseSchema,
3133
+ version: VersionResponseSchema,
3134
+ webFetch: WebFetchResponseSchema,
3135
+ webSearch: WebSearchResponseSchema
2877
3136
  };
2878
3137
  function getRequestSchema(operationId) {
2879
3138
  return requestSchemas[operationId];
2880
3139
  }
3140
+ function getResponseSchema(operationId) {
3141
+ return responseSchemas[operationId];
3142
+ }
2881
3143
 
2882
3144
  // src/generated/runtime/runtime.ts
2883
3145
  function compareVersions(a, b) {
@@ -2890,18 +3152,13 @@ function compareVersions(a, b) {
2890
3152
  }
2891
3153
  return 0;
2892
3154
  }
2893
- function assertOperationAllowed(operation, options) {
2894
- const localMode = options.localMode ?? true;
2895
- if (!localMode && !operation.environment.cloud) {
2896
- throw new OllamaGenericClientError(
2897
- `Operation ${operation.operationId} (${operation.method} ${operation.path}) is local-only and not supported in cloud mode.`
2898
- );
2899
- }
2900
- if (operation.constraints?.minOllamaVersion && options.serverVersion && compareVersions(options.serverVersion, operation.constraints.minOllamaVersion) < 0) {
2901
- throw new OllamaGenericClientError(
2902
- `Operation ${operation.operationId} (${operation.method} ${operation.path}) requires Ollama >= ${operation.constraints.minOllamaVersion} (server reports ${options.serverVersion}).`
2903
- );
2904
- }
3155
+ async function fetchServerVersion(http) {
3156
+ const result = await http.request({
3157
+ path: "/api/version",
3158
+ method: "GET"
3159
+ });
3160
+ if (result && typeof result.version === "string") return result.version;
3161
+ return void 0;
2905
3162
  }
2906
3163
  function shouldStream(req) {
2907
3164
  if (req.body && typeof req.body === "object" && "stream" in req.body) {
@@ -2924,6 +3181,35 @@ var OllamaRuntime = class {
2924
3181
  this.options = options;
2925
3182
  }
2926
3183
  options;
3184
+ /**
3185
+ * Cached promise of the Ollama server version, populated lazily the first
3186
+ * time a version-gated operation is invoked. `undefined` until then.
3187
+ *
3188
+ * Wave 12 (P0 #5): see {@link OllamaRuntimeOptions.enforceVersion}.
3189
+ */
3190
+ serverVersionCache;
3191
+ /**
3192
+ * Wave 15 (P0): resolve the HTTP backend for a given operation.
3193
+ *
3194
+ * Operations with a declared `host` (e.g. web search/fetch at
3195
+ * https://ollama.com) must route to a HttpClient pointed at that host,
3196
+ * not the default one. The runtime accepts an optional `cloudHttp`
3197
+ * backend for this purpose — if the operation declares a host and no
3198
+ * cloud backend is configured, the runtime throws rather than silently
3199
+ * sending the request to the wrong server.
3200
+ */
3201
+ resolveHttpBackend(operation) {
3202
+ if (operation.host) {
3203
+ const cloudHttp = this.options.cloudHttp;
3204
+ if (!cloudHttp) {
3205
+ throw new OllamaGenericClientError(
3206
+ `Operation ${operation.operationId} (${operation.method} ${operation.path}) targets host "${operation.host}" but the runtime has no cloudHttp backend configured. Use OllamaClient.webSearch() / OllamaClient.webFetch() for cloud-hosted operations, or construct OllamaRuntime with a cloudHttp option.`
3207
+ );
3208
+ }
3209
+ return cloudHttp;
3210
+ }
3211
+ return this.options.http;
3212
+ }
2927
3213
  /**
2928
3214
  * Invoke an operation. Called by every generated API method.
2929
3215
  *
@@ -2932,7 +3218,7 @@ var OllamaRuntime = class {
2932
3218
  * class's overloads pick the right return type at compile time.
2933
3219
  */
2934
3220
  async invoke(req) {
2935
- assertOperationAllowed(req.operation, this.options);
3221
+ await this.assertOperationAllowed(req.operation);
2936
3222
  let body = buildBody(req);
2937
3223
  if (this.options.validateRequests === true && body !== void 0) {
2938
3224
  const schema = getRequestSchema(req.operation.operationId);
@@ -2951,32 +3237,668 @@ var OllamaRuntime = class {
2951
3237
  body = result.data;
2952
3238
  }
2953
3239
  }
3240
+ if (body !== void 0) {
3241
+ const serialized = serializeForByteCount(body);
3242
+ const hasImages = bodyHasImages(body);
3243
+ const maxBytesWithImages = req.operation.constraints?.maxRequestBytesWithImages;
3244
+ const maxBytesBase = req.operation.constraints?.maxRequestBytes;
3245
+ const applicableLimit = hasImages && maxBytesWithImages !== void 0 ? maxBytesWithImages : maxBytesBase;
3246
+ if (applicableLimit !== void 0 && serialized.byteLength > applicableLimit) {
3247
+ throw new OllamaRequestTooLargeError(
3248
+ `Operation ${req.operation.operationId} (${req.operation.method} ${req.operation.path}) request body is ${serialized.byteLength} bytes, exceeding the contract limit of ${applicableLimit} bytes` + (hasImages ? " (images limit)." : "."),
3249
+ {
3250
+ operationId: req.operation.operationId,
3251
+ actualBytes: serialized.byteLength,
3252
+ maxBytes: applicableLimit,
3253
+ request: { method: req.operation.method, url: req.operation.path }
3254
+ }
3255
+ );
3256
+ }
3257
+ }
2954
3258
  const streaming = shouldStream(req);
3259
+ const resolvedPath = resolvePathParams(req.operation.path, req.pathParams);
3260
+ const model = req.model ?? extractModelFromBody(body);
2955
3261
  const httpReq = {
2956
- path: req.operation.path,
3262
+ path: resolvedPath,
2957
3263
  method: req.operation.method,
2958
3264
  ...body !== void 0 ? { body } : {},
2959
3265
  ...req.signal !== void 0 ? { signal: req.signal } : {},
2960
- // For streaming calls, request the raw Response so we can pipe it
2961
- // through parseNdjsonStream directly. This inherits middleware,
2962
- // retry, telemetry, and error-mapping from HttpClient — the
2963
- // previous Wave 3 implementation bypassed them with a direct
2964
- // `fetch()` call.
2965
- ...streaming ? { raw: true } : {}
3266
+ ...streaming ? { raw: true } : {},
3267
+ ...model !== void 0 ? { model } : {}
2966
3268
  };
2967
3269
  if (!streaming) {
2968
- return await this.options.http.request(httpReq);
3270
+ const result = await this.resolveHttpBackend(req.operation).request(httpReq);
3271
+ if (this.options.validateResponses === true) {
3272
+ const responseSchema = getResponseSchema(req.operation.operationId);
3273
+ if (responseSchema) {
3274
+ const result2 = responseSchema.safeParse(result);
3275
+ if (!result2.success) {
3276
+ throw new OllamaResponseValidationError(
3277
+ `Response validation failed for operation "${req.operation.operationId}" (${req.operation.method} ${req.operation.path}): ` + result2.error.issues.map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`).join("; "),
3278
+ {
3279
+ operationId: req.operation.operationId,
3280
+ issues: result2.error.issues,
3281
+ request: { method: req.operation.method, url: req.operation.path }
3282
+ }
3283
+ );
3284
+ }
3285
+ }
3286
+ }
3287
+ return result;
2969
3288
  }
2970
- const response = await this.options.http.request(httpReq);
3289
+ const response = await this.resolveHttpBackend(req.operation).request(httpReq);
2971
3290
  if (!response.body) {
2972
3291
  throw new OllamaGenericClientError(
2973
3292
  `Operation ${req.operation.operationId}: streaming response had no body.`
2974
3293
  );
2975
3294
  }
2976
- return parseNdjsonStream(response.body);
3295
+ return parseStreamByMode(req.operation.transport.mode, response.body);
3296
+ }
3297
+ /**
3298
+ * Apply environment + version guards before delegating to HttpClient.
3299
+ *
3300
+ * Throws {@link OllamaGenericClientError} when:
3301
+ * - The operation is local-only and the runtime is in cloud mode.
3302
+ * - The operation has `constraints.minOllamaVersion` and the server is older.
3303
+ *
3304
+ * Wave 12 (P0 #5): when `minOllamaVersion` is declared but the runtime's
3305
+ * `serverVersion` is unknown AND `enforceVersion` is `'auto'` or
3306
+ * `'strict'`, the runtime lazily fetches `/api/version` (cached on the
3307
+ * runtime instance) so the constraint is actually enforced even when the
3308
+ * caller didn't supply it. Previously the constraint was only enforced
3309
+ * when `serverVersion` was manually supplied — meaning in practice it was
3310
+ * almost never enforced.
3311
+ */
3312
+ async assertOperationAllowed(operation) {
3313
+ const localMode = this.options.localMode ?? true;
3314
+ if (!localMode && !operation.environment.cloud) {
3315
+ throw new OllamaGenericClientError(
3316
+ `Operation ${operation.operationId} (${operation.method} ${operation.path}) is local-only and not supported in cloud mode.`
3317
+ );
3318
+ }
3319
+ const minVersion = operation.constraints?.minOllamaVersion;
3320
+ if (!minVersion) return;
3321
+ let serverVersion = this.options.serverVersion;
3322
+ const policy = this.options.enforceVersion ?? "auto";
3323
+ if (!serverVersion && policy !== "off") {
3324
+ if (!this.serverVersionCache) {
3325
+ const p = fetchServerVersion(this.options.http).catch((err) => {
3326
+ if (policy === "strict") {
3327
+ throw new OllamaServerVersionUnknownError(
3328
+ `Operation ${operation.operationId} requires Ollama >= ${minVersion} but the runtime could not determine the server version (enforceVersion: 'strict').`,
3329
+ {
3330
+ operationId: operation.operationId,
3331
+ minRequiredVersion: minVersion,
3332
+ cause: err
3333
+ }
3334
+ );
3335
+ }
3336
+ return void 0;
3337
+ });
3338
+ this.serverVersionCache = p;
3339
+ }
3340
+ serverVersion = await this.serverVersionCache ?? void 0;
3341
+ }
3342
+ if (serverVersion && compareVersions(serverVersion, minVersion) < 0) {
3343
+ throw new OllamaGenericClientError(
3344
+ `Operation ${operation.operationId} (${operation.method} ${operation.path}) requires Ollama >= ${minVersion} (server reports ${serverVersion}).`
3345
+ );
3346
+ }
3347
+ }
3348
+ };
3349
+ function parseStreamByMode(mode, body) {
3350
+ if (mode === "ndjson") {
3351
+ return parseNdjsonStream(body);
3352
+ }
3353
+ if (mode === "sse") {
3354
+ return parseSseStreamAsJson(body);
3355
+ }
3356
+ throw new OllamaGenericClientError(
3357
+ `Transport mode "${mode}" is not a streaming mode; cannot parse a stream for it.`
3358
+ );
3359
+ }
3360
+ async function* parseSseStreamAsJson(body) {
3361
+ for await (const event of parseSseStream(body)) {
3362
+ const data = event.data;
3363
+ if (!data) continue;
3364
+ if (data === "[DONE]") return;
3365
+ try {
3366
+ yield JSON.parse(data);
3367
+ } catch (err) {
3368
+ throw new OllamaGenericClientError(`Failed to parse SSE event data as JSON: ${data}`, {
3369
+ cause: err
3370
+ });
3371
+ }
3372
+ }
3373
+ }
3374
+ function serializeForByteCount(body) {
3375
+ if (body instanceof Uint8Array) return body;
3376
+ if (typeof body === "string") return new TextEncoder().encode(body);
3377
+ const json = JSON.stringify(body);
3378
+ return new TextEncoder().encode(json);
3379
+ }
3380
+ function bodyHasImages(body) {
3381
+ if (typeof body !== "object" || body === null) return false;
3382
+ const obj = body;
3383
+ const images = obj.images;
3384
+ return Array.isArray(images) && images.length > 0;
3385
+ }
3386
+ function resolvePathParams(pathTemplate, pathParams) {
3387
+ if (!pathTemplate.includes("{")) return pathTemplate;
3388
+ const params = pathParams ?? {};
3389
+ return pathTemplate.replace(/\{([^}]+)\}/g, (_match, name) => {
3390
+ const value = params[name];
3391
+ if (value === void 0) {
3392
+ throw new OllamaGenericClientError(
3393
+ `Missing path parameter "${name}" for path template "${pathTemplate}". Provide it via the pathParams field on the invoke() request.`
3394
+ );
3395
+ }
3396
+ return encodeURIComponent(value);
3397
+ });
3398
+ }
3399
+ function extractModelFromBody(body) {
3400
+ if (typeof body !== "object" || body === null) return void 0;
3401
+ const obj = body;
3402
+ const model = obj.model;
3403
+ return typeof model === "string" ? model : void 0;
3404
+ }
3405
+
3406
+ // src/generated/api/operations.ts
3407
+ var blobsOp = {
3408
+ operationId: "blobs",
3409
+ method: "HEAD",
3410
+ path: "/api/blobs/{digest}",
3411
+ environment: { local: true, cloud: false },
3412
+ parameters: [{ name: "digest", in: "path", required: true, schema: { type: "string" } }],
3413
+ transport: { mode: "json", streaming: false },
3414
+ capabilities: {},
3415
+ status: { documented: true },
3416
+ domain: "native",
3417
+ notes: [
3418
+ "HEAD-only endpoint for blob existence checks; declared in OpenAPI but not in the legacy parity manifest."
3419
+ ]
3420
+ };
3421
+ var chatOp = {
3422
+ operationId: "chat",
3423
+ method: "POST",
3424
+ path: "/api/chat",
3425
+ request: { $ref: "#/schemas/ChatRequest" },
3426
+ response: { $ref: "#/schemas/ChatResponse" },
3427
+ environment: { local: true, cloud: true },
3428
+ transport: { mode: "ndjson", streaming: true, streamingDefault: true },
3429
+ capabilities: {
3430
+ thinking: "model-dependent",
3431
+ tools: "model-dependent",
3432
+ vision: "model-dependent",
3433
+ structuredOutput: "supported",
3434
+ logprobs: "supported"
3435
+ },
3436
+ status: { documented: true },
3437
+ domain: "native",
3438
+ notes: [
3439
+ "Use /api/show to discover model-specific thinking values and defaults.",
3440
+ "Structured output (format field) is rejected by Ollama Cloud."
3441
+ ]
3442
+ };
3443
+ var copyOp = {
3444
+ operationId: "copy",
3445
+ method: "POST",
3446
+ path: "/api/copy",
3447
+ request: { $ref: "#/schemas/CopyRequest" },
3448
+ environment: { local: true, cloud: false },
3449
+ transport: { mode: "json", streaming: false },
3450
+ capabilities: {},
3451
+ status: { documented: true },
3452
+ domain: "native"
3453
+ };
3454
+ var createOp = {
3455
+ operationId: "create",
3456
+ method: "POST",
3457
+ path: "/api/create",
3458
+ request: { $ref: "#/schemas/CreateRequest" },
3459
+ response: { $ref: "#/schemas/StatusResponse" },
3460
+ environment: { local: true, cloud: false },
3461
+ transport: { mode: "ndjson", streaming: true, streamingDefault: true },
3462
+ capabilities: { thinking: "unsupported", tools: "unsupported" },
3463
+ status: { documented: true },
3464
+ domain: "native",
3465
+ notes: ["Model creation is local-only; Ollama Cloud does not support it."]
3466
+ };
3467
+ var deleteOp = {
3468
+ operationId: "delete",
3469
+ method: "DELETE",
3470
+ path: "/api/delete",
3471
+ request: { $ref: "#/schemas/DeleteRequest" },
3472
+ environment: { local: true, cloud: false },
3473
+ transport: { mode: "json", streaming: false },
3474
+ capabilities: {},
3475
+ status: { documented: true },
3476
+ domain: "native"
3477
+ };
3478
+ var embedOp = {
3479
+ operationId: "embed",
3480
+ method: "POST",
3481
+ path: "/api/embed",
3482
+ request: { $ref: "#/schemas/EmbedRequest" },
3483
+ response: { $ref: "#/schemas/EmbedResponse" },
3484
+ environment: { local: true, cloud: true },
3485
+ transport: { mode: "json", streaming: false },
3486
+ capabilities: { embeddings: "supported" },
3487
+ status: { documented: true },
3488
+ domain: "native"
3489
+ };
3490
+ var generateOp = {
3491
+ operationId: "generate",
3492
+ method: "POST",
3493
+ path: "/api/generate",
3494
+ request: { $ref: "#/schemas/GenerateRequest" },
3495
+ response: { $ref: "#/schemas/GenerateResponse" },
3496
+ environment: { local: true, cloud: true },
3497
+ transport: { mode: "ndjson", streaming: true, streamingDefault: true },
3498
+ capabilities: {
3499
+ thinking: "model-dependent",
3500
+ vision: "supported",
3501
+ structuredOutput: "supported",
3502
+ logprobs: "supported"
3503
+ },
3504
+ status: { documented: true },
3505
+ domain: "native"
3506
+ };
3507
+ var psOp = {
3508
+ operationId: "ps",
3509
+ method: "GET",
3510
+ path: "/api/ps",
3511
+ response: { $ref: "#/schemas/PsResponse" },
3512
+ environment: { local: true, cloud: true },
3513
+ transport: { mode: "json", streaming: false },
3514
+ capabilities: {},
3515
+ status: { documented: true },
3516
+ domain: "native"
3517
+ };
3518
+ var pullOp = {
3519
+ operationId: "pull",
3520
+ method: "POST",
3521
+ path: "/api/pull",
3522
+ request: { $ref: "#/schemas/PullRequest" },
3523
+ response: { $ref: "#/schemas/StatusResponse" },
3524
+ environment: { local: true, cloud: false },
3525
+ transport: { mode: "ndjson", streaming: true, streamingDefault: true },
3526
+ capabilities: {},
3527
+ status: { documented: true },
3528
+ domain: "native"
3529
+ };
3530
+ var pushOp = {
3531
+ operationId: "push",
3532
+ method: "POST",
3533
+ path: "/api/push",
3534
+ request: { $ref: "#/schemas/PushRequest" },
3535
+ response: { $ref: "#/schemas/StatusResponse" },
3536
+ environment: { local: true, cloud: false },
3537
+ transport: { mode: "ndjson", streaming: true, streamingDefault: true },
3538
+ capabilities: {},
3539
+ status: { documented: true },
3540
+ domain: "native"
3541
+ };
3542
+ var showOp = {
3543
+ operationId: "show",
3544
+ method: "POST",
3545
+ path: "/api/show",
3546
+ request: { $ref: "#/schemas/ShowRequest" },
3547
+ response: { $ref: "#/schemas/ShowResponse" },
3548
+ environment: { local: true, cloud: true },
3549
+ transport: { mode: "json", streaming: false },
3550
+ capabilities: {},
3551
+ status: { documented: true },
3552
+ domain: "native",
3553
+ notes: [
3554
+ "Capabilities source: /api/show is the runtime source of truth for model-dependent capability values (tools, vision, thinking, embeddings)."
3555
+ ]
3556
+ };
3557
+ var systemOneOp = {
3558
+ operationId: "systemOne",
3559
+ method: "POST",
3560
+ path: "/v1/systemone",
3561
+ request: { $ref: "#/schemas/SystemOneRequest" },
3562
+ response: { $ref: "#/schemas/SystemOneResponse" },
3563
+ environment: { local: true, cloud: false },
3564
+ transport: { mode: "json", streaming: false },
3565
+ capabilities: {
3566
+ thinking: "unsupported",
3567
+ tools: "unsupported",
3568
+ vision: "model-dependent",
3569
+ structuredOutput: "unsupported",
3570
+ logprobs: "unsupported",
3571
+ embeddings: "unsupported"
3572
+ },
3573
+ constraints: {
3574
+ minOllamaVersion: "0.35.0",
3575
+ maxRequestBytes: 65536,
3576
+ maxRequestBytesWithImages: 33554432
3577
+ },
3578
+ status: { documented: true, experimental: true },
3579
+ domain: "native",
3580
+ notes: [
3581
+ "Local-only; Ollama Cloud rejects /v1/systemone.",
3582
+ "64 KiB request limit without images, 32 MiB with images (includes JSON/base64 overhead).",
3583
+ "No tools, no generation controls (temperature, top_p, etc.).",
3584
+ "Vision is model-dependent: images are accepted by vision-weighted models (Clef/Clef Flash) but not by text-only models.",
3585
+ "Experimental: behavioral surface may change between Ollama releases."
3586
+ ]
3587
+ };
3588
+ var tagsOp = {
3589
+ operationId: "tags",
3590
+ method: "GET",
3591
+ path: "/api/tags",
3592
+ response: { $ref: "#/schemas/ListResponse" },
3593
+ environment: { local: true, cloud: true },
3594
+ transport: { mode: "json", streaming: false },
3595
+ capabilities: {},
3596
+ status: { documented: true },
3597
+ domain: "native"
3598
+ };
3599
+ var versionOp = {
3600
+ operationId: "version",
3601
+ method: "GET",
3602
+ path: "/api/version",
3603
+ response: { $ref: "#/schemas/VersionResponse" },
3604
+ environment: { local: true, cloud: true },
3605
+ transport: { mode: "json", streaming: false },
3606
+ capabilities: {},
3607
+ status: { documented: true },
3608
+ domain: "native"
3609
+ };
3610
+
3611
+ // src/generated/api/native-api.ts
3612
+ var NativeApi = class {
3613
+ constructor(runtime) {
3614
+ this.runtime = runtime;
3615
+ }
3616
+ runtime;
3617
+ blobs(digest, options) {
3618
+ return this.runtime.invoke({
3619
+ operation: blobsOp,
3620
+ body: void 0,
3621
+ pathParams: { digest },
3622
+ ...options?.signal !== void 0 ? { signal: options.signal } : {}
3623
+ });
3624
+ }
3625
+ chat(request) {
3626
+ return this.runtime.invoke({
3627
+ operation: chatOp,
3628
+ body: request,
3629
+ streamingDefault: true
3630
+ });
3631
+ }
3632
+ copy(request) {
3633
+ return this.runtime.invoke({
3634
+ operation: copyOp,
3635
+ body: request
3636
+ });
3637
+ }
3638
+ create(request) {
3639
+ return this.runtime.invoke({
3640
+ operation: createOp,
3641
+ body: request,
3642
+ streamingDefault: true
3643
+ });
3644
+ }
3645
+ delete(request) {
3646
+ return this.runtime.invoke({
3647
+ operation: deleteOp,
3648
+ body: request
3649
+ });
3650
+ }
3651
+ embed(request) {
3652
+ return this.runtime.invoke({
3653
+ operation: embedOp,
3654
+ body: request
3655
+ });
3656
+ }
3657
+ generate(request) {
3658
+ return this.runtime.invoke({
3659
+ operation: generateOp,
3660
+ body: request,
3661
+ streamingDefault: true
3662
+ });
3663
+ }
3664
+ ps(options) {
3665
+ return this.runtime.invoke({
3666
+ operation: psOp,
3667
+ body: void 0,
3668
+ ...options?.signal !== void 0 ? { signal: options.signal } : {}
3669
+ });
3670
+ }
3671
+ pull(request) {
3672
+ return this.runtime.invoke({
3673
+ operation: pullOp,
3674
+ body: request,
3675
+ streamingDefault: true
3676
+ });
3677
+ }
3678
+ push(request) {
3679
+ return this.runtime.invoke({
3680
+ operation: pushOp,
3681
+ body: request,
3682
+ streamingDefault: true
3683
+ });
3684
+ }
3685
+ show(request) {
3686
+ return this.runtime.invoke({
3687
+ operation: showOp,
3688
+ body: request
3689
+ });
3690
+ }
3691
+ systemOne(request) {
3692
+ return this.runtime.invoke({
3693
+ operation: systemOneOp,
3694
+ body: request
3695
+ });
3696
+ }
3697
+ tags(options) {
3698
+ return this.runtime.invoke({
3699
+ operation: tagsOp,
3700
+ body: void 0,
3701
+ ...options?.signal !== void 0 ? { signal: options.signal } : {}
3702
+ });
3703
+ }
3704
+ version(options) {
3705
+ return this.runtime.invoke({
3706
+ operation: versionOp,
3707
+ body: void 0,
3708
+ ...options?.signal !== void 0 ? { signal: options.signal } : {}
3709
+ });
3710
+ }
3711
+ };
3712
+
3713
+ // src/failover-http-client.ts
3714
+ var FailoverHttpClient = class {
3715
+ constructor(client, baseUrl) {
3716
+ this.client = client;
3717
+ this.baseUrl = baseUrl;
3718
+ }
3719
+ client;
3720
+ /**
3721
+ * The first candidate endpoint's base URL. Used for inferRuntimeMode()
3722
+ * checks (local vs cloud). The actual request routing picks the best
3723
+ * healthy endpoint per call.
3724
+ */
3725
+ baseUrl;
3726
+ /**
3727
+ * Route a request through OllamaClient's failover machinery.
3728
+ *
3729
+ * Each call to request() goes through executeWithFailover, which:
3730
+ * - Picks the best healthy endpoint from the registry
3731
+ * - Applies retry/backoff within that endpoint
3732
+ * - Fails over to the next candidate on retryable errors
3733
+ * - Reports success/failure to the endpoint health tracker
3734
+ *
3735
+ * Wave 15 (P1): the model is extracted from the request body by the
3736
+ * runtime and passed via the `model` field on the options. This lets
3737
+ * the failover layer filter endpoints by `OllamaEndpoint.models`
3738
+ * (credential-scoped routing). If no model is provided, all endpoints
3739
+ * are considered.
3740
+ *
3741
+ * The `raw` option (for streaming responses) is passed through
3742
+ * unchanged — executeWithFailover returns whatever the operation
3743
+ * callback returns, including raw Response objects.
3744
+ */
3745
+ async request(options) {
3746
+ const { model, ...httpOptions } = options;
3747
+ return this.client.executeWithFailover(
3748
+ async (http, signal) => {
3749
+ const mergedOptions = {
3750
+ ...httpOptions,
3751
+ ...httpOptions.signal !== void 0 ? { signal } : { signal }
3752
+ };
3753
+ return http.request(mergedOptions);
3754
+ },
3755
+ {
3756
+ singleEndpoint: false,
3757
+ ...model !== void 0 ? { model } : {}
3758
+ }
3759
+ );
2977
3760
  }
2978
3761
  };
2979
3762
 
3763
+ // src/decision.ts
3764
+ function createDecision(client) {
3765
+ return {
3766
+ async choice(params) {
3767
+ const response = await client.systemOne({
3768
+ model: params.model,
3769
+ state: params.state,
3770
+ ...params.images ? { images: params.images } : {},
3771
+ questions: {
3772
+ decision: {
3773
+ type: "choice",
3774
+ instructions: params.instructions,
3775
+ criteria: params.criteria
3776
+ }
3777
+ },
3778
+ ...params.keepAlive !== void 0 ? { keep_alive: params.keepAlive } : {}
3779
+ });
3780
+ const answer = response.answers.decision;
3781
+ return {
3782
+ choice: answer.choice,
3783
+ probabilities: answer.probabilities,
3784
+ confidence: answer.confidence,
3785
+ usage: response.usage
3786
+ };
3787
+ },
3788
+ async noul(params) {
3789
+ const response = await client.systemOne({
3790
+ model: params.model,
3791
+ state: params.state,
3792
+ ...params.images ? { images: params.images } : {},
3793
+ questions: {
3794
+ decision: {
3795
+ type: "noul",
3796
+ instructions: params.instructions
3797
+ }
3798
+ },
3799
+ ...params.keepAlive !== void 0 ? { keep_alive: params.keepAlive } : {}
3800
+ });
3801
+ const answer = response.answers.decision;
3802
+ return {
3803
+ noul: answer.noul,
3804
+ bool: answer.noul >= 0.5,
3805
+ usage: response.usage
3806
+ };
3807
+ },
3808
+ async score(params) {
3809
+ const response = await client.systemOne({
3810
+ model: params.model,
3811
+ state: params.state,
3812
+ ...params.images ? { images: params.images } : {},
3813
+ questions: {
3814
+ decision: {
3815
+ type: "score",
3816
+ instructions: params.instructions,
3817
+ criteria: params.criteria
3818
+ }
3819
+ },
3820
+ ...params.keepAlive !== void 0 ? { keep_alive: params.keepAlive } : {}
3821
+ });
3822
+ const answer = response.answers.decision;
3823
+ return {
3824
+ score: answer.score,
3825
+ legend: answer.legend,
3826
+ probabilities: answer.probabilities,
3827
+ confidence: answer.confidence,
3828
+ usage: response.usage
3829
+ };
3830
+ },
3831
+ async route(params) {
3832
+ const response = await client.systemOne({
3833
+ model: params.model,
3834
+ state: params.state,
3835
+ ...params.images ? { images: params.images } : {},
3836
+ questions: {
3837
+ decision: {
3838
+ type: "choice",
3839
+ instructions: params.instructions,
3840
+ criteria: params.criteria
3841
+ }
3842
+ },
3843
+ ...params.keepAlive !== void 0 ? { keep_alive: params.keepAlive } : {}
3844
+ });
3845
+ const answer = response.answers.decision;
3846
+ return {
3847
+ route: answer.choice,
3848
+ confidence: answer.confidence
3849
+ };
3850
+ },
3851
+ async verify(params) {
3852
+ const state = {
3853
+ claim: params.claim,
3854
+ evidence: params.evidence
3855
+ };
3856
+ const response = await client.systemOne({
3857
+ model: params.model,
3858
+ state,
3859
+ ...params.images ? { images: params.images } : {},
3860
+ questions: {
3861
+ decision: {
3862
+ type: "noul",
3863
+ instructions: params.instructions ?? "Is the claim supported by the evidence?"
3864
+ }
3865
+ },
3866
+ ...params.keepAlive !== void 0 ? { keep_alive: params.keepAlive } : {}
3867
+ });
3868
+ const answer = response.answers.decision;
3869
+ return {
3870
+ verified: answer.noul >= 0.5,
3871
+ probability: answer.noul
3872
+ };
3873
+ },
3874
+ async rank(params) {
3875
+ const promises = params.candidates.map(async (candidate) => {
3876
+ const response = await client.systemOne({
3877
+ model: params.model,
3878
+ state: candidate.state,
3879
+ ...params.images ? { images: params.images } : {},
3880
+ questions: {
3881
+ decision: {
3882
+ type: "score",
3883
+ instructions: params.instructions,
3884
+ criteria: params.criteria
3885
+ }
3886
+ },
3887
+ ...params.keepAlive !== void 0 ? { keep_alive: params.keepAlive } : {}
3888
+ });
3889
+ const answer = response.answers.decision;
3890
+ return {
3891
+ candidate: candidate.id,
3892
+ score: answer.score,
3893
+ confidence: answer.confidence
3894
+ };
3895
+ });
3896
+ const results = await Promise.all(promises);
3897
+ return results.sort((a, b) => b.score - a.score);
3898
+ }
3899
+ };
3900
+ }
3901
+
2980
3902
  // src/client.ts
2981
3903
  var logicalRequestSequence = 0;
2982
3904
  function createLogicalRequestId() {
@@ -3037,42 +3959,82 @@ var OllamaClient = class {
3037
3959
  * API with the generated `NativeApi` / `OpenAIApi` / `AnthropicApi`
3038
3960
  * surface without configuring two separate HttpClient instances.
3039
3961
  *
3040
- * The returned runtime is bound to the registry's first candidate
3041
- * endpoint (or the resolved single-endpoint config if no `endpoints`
3042
- * array was provided). For multi-endpoint configs that need per-call
3043
- * routing, prefer constructing `OllamaRuntime` directly with a
3044
- * specific HttpClient:
3045
- *
3046
- * ```ts
3047
- * const http = new HttpClient({ baseUrl: 'http://host-a:11434' });
3048
- * const runtime = new OllamaRuntime({ http });
3049
- * const api = new NativeApi(runtime);
3050
- * ```
3962
+ * Wave 14: the runtime now participates in multi-endpoint failover.
3963
+ * Each request is routed through this client's `executeWithFailover`
3964
+ * machinery via a {@link FailoverHttpClient} wrapper. If the first
3965
+ * candidate endpoint is down, requests automatically fail over to
3966
+ * the next healthy candidate — matching the behavior of the
3967
+ * hand-written OllamaClient methods (chat, generate, etc.).
3051
3968
  *
3052
3969
  * The runtime is cached on first call — subsequent calls return the
3053
- * same instance.
3970
+ * same instance. The `FailoverHttpClient` holds a reference to this
3971
+ * client, so it always sees the current endpoint registry state.
3054
3972
  */
3055
3973
  get runtime() {
3056
3974
  if (this._runtime === void 0) {
3057
3975
  const candidates = this.registry.candidates();
3058
3976
  const endpoint = candidates[0];
3059
3977
  const baseUrl = endpoint?.baseUrl ?? "http://localhost:11434";
3060
- const http = new HttpClient({
3061
- baseUrl,
3062
- ...endpoint?.apiKey !== void 0 ? { apiKey: endpoint.apiKey } : {},
3063
- ...endpoint?.headers !== void 0 ? { headers: endpoint.headers } : {},
3978
+ const http = new FailoverHttpClient(this, baseUrl);
3979
+ const cloudHttp = new HttpClient({
3980
+ baseUrl: OLLAMA_CLOUD_BASE_URL,
3981
+ ...this.cloudApiKey !== void 0 ? { apiKey: this.cloudApiKey } : {},
3064
3982
  fetch: this.fetchImpl,
3065
3983
  ...this.middleware !== void 0 ? { middleware: this.middleware } : {},
3066
3984
  ...this.onLifecycleEvent !== void 0 ? { onLifecycleEvent: this.onLifecycleEvent } : {}
3067
3985
  });
3068
3986
  this._runtime = new OllamaRuntime({
3069
3987
  http,
3988
+ cloudHttp,
3070
3989
  localMode: inferRuntimeMode(baseUrl) === "local"
3071
3990
  });
3072
3991
  }
3073
3992
  return this._runtime;
3074
3993
  }
3075
3994
  _runtime;
3995
+ /**
3996
+ * Lazily-constructed `NativeApi` bound to this client's runtime. Exposes
3997
+ * the full generated native API surface (chat, generate, embed, systemOne,
3998
+ * etc.) with contract-driven types and runtime enforcement.
3999
+ *
4000
+ * Wave 13: `systemOne()` delegates to this accessor.
4001
+ */
4002
+ get native() {
4003
+ if (this._nativeApi === void 0) {
4004
+ this._nativeApi = new NativeApi(this.runtime);
4005
+ }
4006
+ return this._nativeApi;
4007
+ }
4008
+ _nativeApi;
4009
+ /**
4010
+ * Higher-level System One decision helpers (Wave 14B).
4011
+ *
4012
+ * Ergonomic wrappers around `systemOne()` for the six most common
4013
+ * decision patterns: `choice()`, `noul()`, `score()`, `route()`,
4014
+ * `verify()`, `rank()`. Each constructs a single-question request
4015
+ * and extracts the typed answer.
4016
+ *
4017
+ * ```ts
4018
+ * const result = await client.decision.choice({
4019
+ * model: 'tev1:4b',
4020
+ * state: 'Customer was charged twice',
4021
+ * instructions: 'What is the primary intent?',
4022
+ * criteria: {
4023
+ * refund: 'Customer wants a refund',
4024
+ * duplicate_charge: 'Customer reports multiple charges',
4025
+ * },
4026
+ * });
4027
+ * console.log(result.choice); // 'duplicate_charge'
4028
+ * console.log(result.confidence); // 0.89
4029
+ * ```
4030
+ */
4031
+ get decision() {
4032
+ if (this._decision === void 0) {
4033
+ this._decision = createDecision(this);
4034
+ }
4035
+ return this._decision;
4036
+ }
4037
+ _decision;
3076
4038
  /**
3077
4039
  * Fail-fast guard for `format` (structured output) requests: throws before any network
3078
4040
  * call if the candidate endpoint is inferred as Ollama Cloud, which does not currently
@@ -3345,6 +4307,43 @@ var OllamaClient = class {
3345
4307
  version = () => this.models.version();
3346
4308
  createBlob = (digest, data) => this.models.createBlob(digest, data);
3347
4309
  checkBlob = (digest) => this.models.checkBlob(digest);
4310
+ // --- System One (Wave 13) ---
4311
+ /**
4312
+ * Ollama's System One decision layer (`POST /v1/systemone`) — evaluates
4313
+ * 1–64 typed questions (choice, noul, or score) against a provided state
4314
+ * and returns typed answers with probabilities and confidence.
4315
+ *
4316
+ * Local-only; requires Ollama >= 0.35.0. The runtime enforces the
4317
+ * version constraint automatically (lazily fetching `/api/version` when
4318
+ * `enforceVersion` is `'auto'` or `'strict'`) and rejects cloud-mode
4319
+ * calls. Request size is checked client-side: 64 KiB without images,
4320
+ * 32 MiB with images.
4321
+ *
4322
+ * The generic `Q` parameter captures the caller's question map at
4323
+ * compile time, giving key-safe answer access:
4324
+ *
4325
+ * ```ts
4326
+ * const result = await ollama.systemOne({
4327
+ * model: 'tev1:4b',
4328
+ * state: { ticket: 'Customer was charged twice' },
4329
+ * questions: {
4330
+ * intent: { type: 'choice', instructions: '...', criteria: { ... } },
4331
+ * urgent: { type: 'noul', instructions: '...' },
4332
+ * },
4333
+ * });
4334
+ * result.answers.intent // ✓ SystemOneAnswer (choice)
4335
+ * result.answers.urgent // ✓ SystemOneAnswer (noul)
4336
+ * result.answers.typo // ✗ TypeScript error
4337
+ * ```
4338
+ *
4339
+ * For the low-level generated API (without the generic wrapper), use
4340
+ * `client.native.systemOne(request)` directly.
4341
+ */
4342
+ async systemOne(request) {
4343
+ return this.native.systemOne(
4344
+ request
4345
+ );
4346
+ }
3348
4347
  // --- Web Endpoints ---
3349
4348
  /**
3350
4349
  * Ollama's hosted web search tool (`POST https://ollama.com/api/web_search`) — a fixed
@@ -4496,6 +5495,6 @@ var Agent = class {
4496
5495
  }
4497
5496
  };
4498
5497
 
4499
- export { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_REQUEST_MODEL, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_USAGE_INPUT_TOKENS, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_OLLAMA_AGENT_ITERATION, ATTR_OLLAMA_AGENT_MAX_ITERATIONS, ATTR_OLLAMA_ENDPOINT_ATTEMPT, ATTR_OLLAMA_ENDPOINT_NAME, ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT, ATTR_URL_FULL, Agent, AnthropicCompatClient, AnthropicMessagesStream, DEFAULT_BACKOFF, DEFAULT_BASE_URL, DEFAULT_FAILOVER_CODES, DEFAULT_RETRY_CONFIG, DEFAULT_TIMEOUT_MS, EndpointRegistry, GEN_AI_SYSTEM_OLLAMA, HttpClient, McpBridge, ModelsClient, NANOS_PER_MS, NANOS_PER_SECOND, NOOP_LOGGER, OLLAMA_CLOUD_BASE_URL, OllamaAbortError, OllamaAgentMaxIterationsError, OllamaAgentMaxToolCallsError, OllamaAuthError, OllamaClient, OllamaClientError, OllamaGenericClientError, OllamaIncompatibleModelError, OllamaMcpError, OllamaModelRoutingError, OllamaNetworkError, OllamaNotFoundError, OllamaQuotaExceededError, OllamaRateLimitError, OllamaRequestValidationError, OllamaServerError, OllamaSkillInvalidError, OllamaSkillNotFoundError, OllamaStream, OllamaTimeoutError, OllamaToolTimeoutError, OllamaToolValidationError, OllamaUnsupportedCapabilityError, OpenAIChatCompletionStream, OpenAICompatClient, OpenAICompletionStream, OpenAIResponsesStream, OpenAIResponsesStreamError, QuotaManager, ToolRegistry, addSpanEvent, applySkill, calculateBackoff, checkEndpointHealth, composeMiddleware, createConsoleLogger, createOllamaCloudFreeTierQuota, createTimeoutSignal, defineTool, detectModelCapabilities, encodeImage, extractUsage, inferRuntimeMode, listAllMcpTools, listAvailableModels, loadMcpTools, mapError, normalizeChatStream, normalizeGenerateStream, normalizeProgressStream, parseFrontmatter, parseNdjsonStream, parseSseStream, parseStructuredOutput, registerMcpTools, resolveCredentialEndpoints, setSpanError, toDataStream, toResponse, toTextStream, withRetry, withSpan, zodToJsonSchema };
5498
+ export { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_REQUEST_MODEL, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_USAGE_INPUT_TOKENS, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_OLLAMA_AGENT_ITERATION, ATTR_OLLAMA_AGENT_MAX_ITERATIONS, ATTR_OLLAMA_ENDPOINT_ATTEMPT, ATTR_OLLAMA_ENDPOINT_NAME, ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT, ATTR_URL_FULL, Agent, AnthropicCompatClient, AnthropicMessagesStream, DEFAULT_BACKOFF, DEFAULT_BASE_URL, DEFAULT_FAILOVER_CODES, DEFAULT_RETRY_CONFIG, DEFAULT_TIMEOUT_MS, EndpointRegistry, GEN_AI_SYSTEM_OLLAMA, HttpClient, McpBridge, ModelsClient, NANOS_PER_MS, NANOS_PER_SECOND, NOOP_LOGGER, OLLAMA_CLOUD_BASE_URL, OllamaAbortError, OllamaAgentMaxIterationsError, OllamaAgentMaxToolCallsError, OllamaAuthError, OllamaClient, OllamaClientError, OllamaGenericClientError, OllamaIncompatibleModelError, OllamaMcpError, OllamaModelRoutingError, OllamaNetworkError, OllamaNotFoundError, OllamaQuotaExceededError, OllamaRateLimitError, OllamaRequestTooLargeError, OllamaRequestValidationError, OllamaResponseValidationError, OllamaServerError, OllamaServerVersionUnknownError, OllamaSkillInvalidError, OllamaSkillNotFoundError, OllamaStream, OllamaTimeoutError, OllamaToolTimeoutError, OllamaToolValidationError, OllamaUnsupportedCapabilityError, OpenAIChatCompletionStream, OpenAICompatClient, OpenAICompletionStream, OpenAIResponsesStream, OpenAIResponsesStreamError, QuotaManager, ToolRegistry, addSpanEvent, applySkill, calculateBackoff, checkEndpointHealth, composeMiddleware, createConsoleLogger, createDecision, createOllamaCloudFreeTierQuota, createTimeoutSignal, defineTool, detectModelCapabilities, encodeImage, extractUsage, inferRuntimeMode, listAllMcpTools, listAvailableModels, loadMcpTools, mapError, normalizeChatStream, normalizeGenerateStream, normalizeProgressStream, parseFrontmatter, parseNdjsonStream, parseSseStream, parseStructuredOutput, registerMcpTools, resolveCredentialEndpoints, setSpanError, toDataStream, toResponse, toTextStream, withRetry, withSpan, zodToJsonSchema };
4500
5499
  //# sourceMappingURL=index.js.map
4501
5500
  //# sourceMappingURL=index.js.map