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