@nemesis-oss/ollama-sdk 1.12.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2851,7 +2851,11 @@ var ModelsClient = class {
2851
2851
  var OpenAIResponsesStreamError = class extends OllamaClientError {
2852
2852
  responsePayload;
2853
2853
  constructor(message, responsePayload) {
2854
- super(message, { code: "openai_responses_stream_error", retryable: false, response: { body: responsePayload } });
2854
+ super(message, {
2855
+ code: "openai_responses_stream_error",
2856
+ retryable: false,
2857
+ response: { body: responsePayload }
2858
+ });
2855
2859
  this.responsePayload = responsePayload;
2856
2860
  }
2857
2861
  };
@@ -2993,7 +2997,9 @@ var OpenAIChatCompletionStream = class {
2993
2997
  } finally {
2994
2998
  if (!completed) {
2995
2999
  this.source.abort?.();
2996
- this.rejectFinal(new OllamaAbortError("OpenAI Chat Completion stream ended before completion"));
3000
+ this.rejectFinal(
3001
+ new OllamaAbortError("OpenAI Chat Completion stream ended before completion")
3002
+ );
2997
3003
  }
2998
3004
  }
2999
3005
  }
@@ -3122,7 +3128,14 @@ var OpenAIResponsesStream = class {
3122
3128
  existing.kind = kind;
3123
3129
  return existing;
3124
3130
  }
3125
- const state = { itemId, kind, content: /* @__PURE__ */ new Map(), summary: /* @__PURE__ */ new Map(), arguments: "", reasoningText: "" };
3131
+ const state = {
3132
+ itemId,
3133
+ kind,
3134
+ content: /* @__PURE__ */ new Map(),
3135
+ summary: /* @__PURE__ */ new Map(),
3136
+ arguments: "",
3137
+ reasoningText: ""
3138
+ };
3126
3139
  outputs.set(outputIndex, state);
3127
3140
  return state;
3128
3141
  };
@@ -3153,9 +3166,33 @@ var OpenAIResponsesStream = class {
3153
3166
  const reconstructedOutput = () => [...outputs.entries()].sort(([a], [b]) => a - b).map(([outputIndex, state]) => {
3154
3167
  const canonical = canonicalOutputItems.get(outputIndex);
3155
3168
  if (canonical) return canonical;
3156
- if (state.kind === "message") return { type: "message", ...state.itemId ? { id: state.itemId } : {}, ...state.status ? { status: state.status } : {}, role: state.role ?? "assistant", ...state.phase ? { phase: state.phase } : {}, content: [...state.content.entries()].sort(([a], [b]) => a - b).map(([, p]) => p) };
3157
- if (state.kind === "function_call") return { type: "function_call", ...state.itemId ? { id: state.itemId } : {}, ...state.callId ? { call_id: state.callId } : {}, ...state.status ? { status: state.status } : {}, name: state.name ?? "", arguments: state.arguments };
3158
- return { type: "reasoning", ...state.itemId ? { id: state.itemId } : {}, ...state.status ? { status: state.status } : {}, ...state.summary.size ? { summary: [...state.summary.entries()].sort(([a], [b]) => a - b).map(([, text]) => ({ type: "summary_text", text })) } : {}, ...state.reasoningText ? { text: state.reasoningText } : {} };
3169
+ if (state.kind === "message")
3170
+ return {
3171
+ type: "message",
3172
+ ...state.itemId ? { id: state.itemId } : {},
3173
+ ...state.status ? { status: state.status } : {},
3174
+ role: state.role ?? "assistant",
3175
+ ...state.phase ? { phase: state.phase } : {},
3176
+ content: [...state.content.entries()].sort(([a], [b]) => a - b).map(([, p]) => p)
3177
+ };
3178
+ if (state.kind === "function_call")
3179
+ return {
3180
+ type: "function_call",
3181
+ ...state.itemId ? { id: state.itemId } : {},
3182
+ ...state.callId ? { call_id: state.callId } : {},
3183
+ ...state.status ? { status: state.status } : {},
3184
+ name: state.name ?? "",
3185
+ arguments: state.arguments
3186
+ };
3187
+ return {
3188
+ type: "reasoning",
3189
+ ...state.itemId ? { id: state.itemId } : {},
3190
+ ...state.status ? { status: state.status } : {},
3191
+ ...state.summary.size ? {
3192
+ summary: [...state.summary.entries()].sort(([a], [b]) => a - b).map(([, text]) => ({ type: "summary_text", text }))
3193
+ } : {},
3194
+ ...state.reasoningText ? { text: state.reasoningText } : {}
3195
+ };
3159
3196
  });
3160
3197
  try {
3161
3198
  for await (const event of this.source) {
@@ -3199,7 +3236,12 @@ var OpenAIResponsesStream = class {
3199
3236
  case "response.content_part.done": {
3200
3237
  const e = payload;
3201
3238
  if (e.part.type === "output_text" && "text" in e.part && typeof e.part.text === "string" || e.part.type === "refusal" && "refusal" in e.part && typeof e.part.refusal === "string") {
3202
- applyContentPart(e.output_index, e.item_id, e.content_index, e.part);
3239
+ applyContentPart(
3240
+ e.output_index,
3241
+ e.item_id,
3242
+ e.content_index,
3243
+ e.part
3244
+ );
3203
3245
  }
3204
3246
  break;
3205
3247
  }
@@ -3207,7 +3249,10 @@ var OpenAIResponsesStream = class {
3207
3249
  const e = payload;
3208
3250
  const s = ensureState(e.output_index, e.item_id, "message");
3209
3251
  const p = s.content.get(e.content_index);
3210
- s.content.set(e.content_index, { type: "output_text", text: (p?.type === "output_text" ? p.text : "") + e.delta });
3252
+ s.content.set(e.content_index, {
3253
+ type: "output_text",
3254
+ text: (p?.type === "output_text" ? p.text : "") + e.delta
3255
+ });
3211
3256
  break;
3212
3257
  }
3213
3258
  case "response.output_text.done": {
@@ -3220,7 +3265,10 @@ var OpenAIResponsesStream = class {
3220
3265
  const e = payload;
3221
3266
  const s = ensureState(e.output_index, e.item_id, "message");
3222
3267
  const p = s.content.get(e.content_index);
3223
- s.content.set(e.content_index, { type: "refusal", refusal: (p?.type === "refusal" ? p.refusal : "") + e.delta });
3268
+ s.content.set(e.content_index, {
3269
+ type: "refusal",
3270
+ refusal: (p?.type === "refusal" ? p.refusal : "") + e.delta
3271
+ });
3224
3272
  break;
3225
3273
  }
3226
3274
  case "response.refusal.done": {
@@ -3282,20 +3330,31 @@ var OpenAIResponsesStream = class {
3282
3330
  const response = terminalFailure ?? terminalIncomplete;
3283
3331
  const status = terminalFailure ? "failed" : "incomplete";
3284
3332
  const detail = response.error?.message ?? response.incomplete_details?.reason ?? "unknown error";
3285
- throw new OpenAIResponsesStreamError("OpenAI Responses stream " + status + ": " + detail, response);
3333
+ throw new OpenAIResponsesStreamError(
3334
+ "OpenAI Responses stream " + status + ": " + detail,
3335
+ response
3336
+ );
3286
3337
  }
3287
3338
  if (!finalResponse) {
3288
- if (!responseMeta) throw new Error("OpenAI Responses stream ended without a terminal response payload");
3339
+ if (!responseMeta)
3340
+ throw new Error("OpenAI Responses stream ended without a terminal response payload");
3289
3341
  if (responseMeta.status === "failed" || responseMeta.status === "incomplete") {
3290
3342
  const detail = responseMeta.error?.message ?? responseMeta.incomplete_details?.reason ?? "unknown error";
3291
- throw new OpenAIResponsesStreamError("OpenAI Responses stream " + responseMeta.status + ": " + detail, responseMeta);
3343
+ throw new OpenAIResponsesStreamError(
3344
+ "OpenAI Responses stream " + responseMeta.status + ": " + detail,
3345
+ responseMeta
3346
+ );
3292
3347
  }
3293
3348
  finalResponse = { ...responseMeta, output: reconstructedOutput(), status: "completed" };
3294
3349
  } else if (finalResponse.status === "failed" || finalResponse.status === "incomplete") {
3295
3350
  const detail = finalResponse.error?.message ?? finalResponse.incomplete_details?.reason ?? "unknown error";
3296
- throw new OpenAIResponsesStreamError("OpenAI Responses stream " + finalResponse.status + ": " + detail, finalResponse);
3351
+ throw new OpenAIResponsesStreamError(
3352
+ "OpenAI Responses stream " + finalResponse.status + ": " + detail,
3353
+ finalResponse
3354
+ );
3297
3355
  }
3298
- if (finalResponse.output.length === 0 && outputs.size > 0) finalResponse = { ...finalResponse, output: reconstructedOutput() };
3356
+ if (finalResponse.output.length === 0 && outputs.size > 0)
3357
+ finalResponse = { ...finalResponse, output: reconstructedOutput() };
3299
3358
  completed = true;
3300
3359
  this.removeAbortListener?.();
3301
3360
  this.removeAbortListener = void 0;
@@ -3320,14 +3379,11 @@ var OpenAICompatClient = class {
3320
3379
  }
3321
3380
  request(operation, model, signal, holdUntil) {
3322
3381
  if (this.runner) {
3323
- return this.runner(
3324
- (http, runnerSignal) => operation(http, runnerSignal),
3325
- {
3326
- ...model !== void 0 ? { model } : {},
3327
- ...signal !== void 0 ? { signal } : {},
3328
- ...holdUntil !== void 0 ? { holdUntil } : {}
3329
- }
3330
- );
3382
+ return this.runner((http, runnerSignal) => operation(http, runnerSignal), {
3383
+ ...model !== void 0 ? { model } : {},
3384
+ ...signal !== void 0 ? { signal } : {},
3385
+ ...holdUntil !== void 0 ? { holdUntil } : {}
3386
+ });
3331
3387
  }
3332
3388
  return operation(this.http, signal);
3333
3389
  }
@@ -3956,7 +4012,7 @@ var SystemOneContentSchema = zod.z.union([
3956
4012
  var SystemOneChoiceQuestionSchema = zod.z.object({
3957
4013
  type: zod.z.enum(["choice"]),
3958
4014
  instructions: SystemOneContentSchema,
3959
- 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)), {
4015
+ 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 <= 255, { message: "must have at most 255 properties" }).refine((v) => Object.keys(v).every((k) => new RegExp("\\S").test(k)), {
3960
4016
  message: 'property names must match pattern "\\S"'
3961
4017
  })
3962
4018
  });
@@ -4095,6 +4151,7 @@ var requestSchemas = {
4095
4151
  var responseSchemas = {
4096
4152
  balance: BalanceResponseSchema,
4097
4153
  chat: ChatResponseSchema,
4154
+ copy: StatusResponseSchema,
4098
4155
  create: StatusResponseSchema,
4099
4156
  embed: EmbedResponseSchema,
4100
4157
  generate: GenerateResponseSchema,
@@ -5001,6 +5058,7 @@ var copyOp = {
5001
5058
  method: "POST",
5002
5059
  path: "/api/copy",
5003
5060
  request: { $ref: "#/schemas/CopyRequest" },
5061
+ response: { $ref: "#/schemas/StatusResponse" },
5004
5062
  environment: { local: true, cloud: false },
5005
5063
  transport: { mode: "json", streaming: false },
5006
5064
  capabilities: {},
@@ -6887,6 +6945,93 @@ var ToolRegistry = class {
6887
6945
  };
6888
6946
  }
6889
6947
  };
6948
+ var WEB_SEARCH_TOOL_NAME = "web_search";
6949
+ var WEB_FETCH_TOOL_NAME = "web_fetch";
6950
+ var DEFAULT_MAX_OUTPUT_CHARS = 2e3 * 4;
6951
+ var DEFAULT_MAX_LINKS = 25;
6952
+ var TRUNCATION_MARKER = "\u2026[truncated]";
6953
+ var webSearchSchema = zod.z.object({
6954
+ query: zod.z.string().min(1).describe("The search query string"),
6955
+ max_results: zod.z.number().int().min(1).max(10).optional().describe("Maximum results to return (default 5, max 10)")
6956
+ });
6957
+ var webFetchSchema = zod.z.object({
6958
+ url: zod.z.string().min(1).describe("The URL of the web page to fetch")
6959
+ });
6960
+ function positiveInt2(value, fallback, name) {
6961
+ if (value === void 0) return fallback;
6962
+ if (!Number.isInteger(value) || value < 1) {
6963
+ throw new RangeError(`${name} must be a positive integer, received ${String(value)}`);
6964
+ }
6965
+ return value;
6966
+ }
6967
+ function truncate(text, maxChars) {
6968
+ if (text.length <= maxChars) return text;
6969
+ if (maxChars <= TRUNCATION_MARKER.length) return text.slice(0, maxChars);
6970
+ return text.slice(0, maxChars - TRUNCATION_MARKER.length) + TRUNCATION_MARKER;
6971
+ }
6972
+ function formatWebSearchResult(res, maxChars) {
6973
+ const results = res.results.map(({ title, url, content }) => ({ title, url, content }));
6974
+ const full = JSON.stringify({ results });
6975
+ if (full.length <= maxChars || results.length === 0) return truncate(full, maxChars);
6976
+ const overhead = JSON.stringify({
6977
+ results: results.map((r) => ({ ...r, content: "" }))
6978
+ }).length;
6979
+ const perResult = Math.max(0, Math.floor((maxChars - overhead) / results.length));
6980
+ const trimmed = JSON.stringify({
6981
+ results: results.map((r) => ({ ...r, content: truncate(r.content, perResult) }))
6982
+ });
6983
+ return trimmed.length <= maxChars ? trimmed : truncate(trimmed, maxChars);
6984
+ }
6985
+ function formatWebFetchResult(res, maxChars, maxLinks = DEFAULT_MAX_LINKS) {
6986
+ const page = {
6987
+ title: res.title ?? "",
6988
+ content: res.content,
6989
+ links: (res.links ?? []).slice(0, maxLinks)
6990
+ };
6991
+ const full = JSON.stringify(page);
6992
+ if (full.length <= maxChars) return full;
6993
+ const overhead = JSON.stringify({ ...page, content: "" }).length;
6994
+ const trimmed = JSON.stringify({
6995
+ ...page,
6996
+ content: truncate(page.content, Math.max(0, maxChars - overhead))
6997
+ });
6998
+ return trimmed.length <= maxChars ? trimmed : truncate(trimmed, maxChars);
6999
+ }
7000
+ function createWebSearchTool(client, options = {}) {
7001
+ const maxChars = positiveInt2(options.maxOutputChars, DEFAULT_MAX_OUTPUT_CHARS, "maxOutputChars");
7002
+ const defaultMaxResults = options.defaultMaxResults === void 0 ? void 0 : Math.min(positiveInt2(options.defaultMaxResults, 5, "defaultMaxResults"), 10);
7003
+ return defineTool({
7004
+ name: WEB_SEARCH_TOOL_NAME,
7005
+ description: "Search the web for current information. Returns a list of results, each with a title, url, and relevant content snippet.",
7006
+ schema: webSearchSchema,
7007
+ timeoutMs: options.timeoutMs,
7008
+ execute: async ({ query, max_results }, { signal }) => {
7009
+ const res = await client.webSearch({
7010
+ query,
7011
+ ...(max_results ?? defaultMaxResults) !== void 0 ? { max_results: max_results ?? defaultMaxResults } : {},
7012
+ ...signal !== void 0 ? { signal } : {}
7013
+ });
7014
+ return formatWebSearchResult(res, maxChars);
7015
+ }
7016
+ });
7017
+ }
7018
+ function createWebFetchTool(client, options = {}) {
7019
+ const maxChars = positiveInt2(options.maxOutputChars, DEFAULT_MAX_OUTPUT_CHARS, "maxOutputChars");
7020
+ const maxLinks = positiveInt2(options.maxLinks, DEFAULT_MAX_LINKS, "maxLinks");
7021
+ return defineTool({
7022
+ name: WEB_FETCH_TOOL_NAME,
7023
+ description: "Fetch a single web page by URL. Returns the page title, its main content, and links found on the page.",
7024
+ schema: webFetchSchema,
7025
+ timeoutMs: options.timeoutMs,
7026
+ execute: async ({ url }, { signal }) => {
7027
+ const res = await client.webFetch({ url, ...signal !== void 0 ? { signal } : {} });
7028
+ return formatWebFetchResult(res, maxChars, maxLinks);
7029
+ }
7030
+ });
7031
+ }
7032
+ function createWebTools(client, options = {}) {
7033
+ return [createWebSearchTool(client, options), createWebFetchTool(client, options)];
7034
+ }
6890
7035
 
6891
7036
  // src/mcp/json-schema.ts
6892
7037
  function label(path) {
@@ -7823,6 +7968,8 @@ exports.RETRYABLE_STATUS_CODES = RETRYABLE_STATUS_CODES;
7823
7968
  exports.ResponsesModule = ResponsesModule;
7824
7969
  exports.ToolCallAccumulator = ToolCallAccumulator;
7825
7970
  exports.ToolRegistry = ToolRegistry;
7971
+ exports.WEB_FETCH_TOOL_NAME = WEB_FETCH_TOOL_NAME;
7972
+ exports.WEB_SEARCH_TOOL_NAME = WEB_SEARCH_TOOL_NAME;
7826
7973
  exports.addSpanEvent = addSpanEvent;
7827
7974
  exports.applySkill = applySkill;
7828
7975
  exports.batchEmbed = batchEmbed;
@@ -7839,6 +7986,9 @@ exports.createDecision = createDecision;
7839
7986
  exports.createModelAffinityScheduler = createModelAffinityScheduler;
7840
7987
  exports.createOllamaCloudFreeTierQuota = createOllamaCloudFreeTierQuota;
7841
7988
  exports.createTimeoutSignal = createTimeoutSignal;
7989
+ exports.createWebFetchTool = createWebFetchTool;
7990
+ exports.createWebSearchTool = createWebSearchTool;
7991
+ exports.createWebTools = createWebTools;
7842
7992
  exports.defineTool = defineTool;
7843
7993
  exports.detectModelCapabilities = detectModelCapabilities;
7844
7994
  exports.embedBatchOverflowMessage = embedBatchOverflowMessage;
@@ -7855,6 +8005,8 @@ exports.fetchWithBackoff = fetchWithBackoff;
7855
8005
  exports.findOversizedEmbedInputs = findOversizedEmbedInputs;
7856
8006
  exports.findRunningModelContextLength = findRunningModelContextLength;
7857
8007
  exports.formatTelemetry = formatTelemetry;
8008
+ exports.formatWebFetchResult = formatWebFetchResult;
8009
+ exports.formatWebSearchResult = formatWebSearchResult;
7858
8010
  exports.imageStringNeedsResolution = imageStringNeedsResolution;
7859
8011
  exports.inferRuntimeMode = inferRuntimeMode;
7860
8012
  exports.isKeepAliveSugar = isKeepAliveSugar;