@nemesis-oss/ollama-sdk 1.13.0 → 1.15.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/CHANGELOG.md +43 -0
- package/README.md +170 -4
- package/dist/{anthropic-B9AFyzXI.d.ts → anthropic-DrDUfbfQ.d.ts} +1 -1
- package/dist/{anthropic-CYy_ECam.d.cts → anthropic-UeaVjLeP.d.cts} +1 -1
- package/dist/{compose-6UOPEknN.d.ts → compose-CeFbHJeO.d.ts} +1 -1
- package/dist/{compose-DhvoUrWa.d.cts → compose-DFkmtUOP.d.cts} +1 -1
- package/dist/generated-api.d.cts +5 -5
- package/dist/generated-api.d.ts +5 -5
- package/dist/generated-runtime.d.cts +2 -2
- package/dist/generated-runtime.d.ts +2 -2
- package/dist/index.cjs +140 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +185 -11
- package/dist/index.d.ts +185 -11
- package/dist/index.js +140 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-generated.d.cts +2 -2
- package/dist/mcp-generated.d.ts +2 -2
- package/dist/{runtime-CIQYCRL3.d.ts → runtime-BIjr5ME4.d.ts} +1 -1
- package/dist/{runtime-DmI1cOEq.d.cts → runtime-C4RRHqOs.d.cts} +1 -1
- package/dist/skills.d.cts +3 -3
- package/dist/skills.d.ts +3 -3
- package/dist/testing.cjs +283 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +376 -0
- package/dist/testing.d.ts +376 -0
- package/dist/testing.js +277 -0
- package/dist/testing.js.map +1 -0
- package/dist/{types-B57ZZfp3.d.cts → types-DbPnfVh-.d.cts} +20 -3
- package/dist/{types-B57ZZfp3.d.ts → types-DbPnfVh-.d.ts} +20 -3
- package/package.json +14 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/testing/mock-server.ts"],"names":[],"mappings":"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","file":"testing.js","sourcesContent":["/**\n * In-memory Ollama mock server for deterministic, zero-network CI testing.\n *\n * This is the SDK's own mock engine, promoted from the internal test fixture\n * (`test/mocks/ollama-mock-server.ts`) to a public entry point\n * (`@nemesis-oss/ollama-sdk/testing`) so consumers don't have to hand-roll\n * ad-hoc HTTP stubs to test their Ollama integrations — see ADR 0029.\n * The internal fixture re-exports this module, so the SDK's own test suite\n * exercises the exact same code consumers get.\n *\n * The VCR cassette system (`test/vcr.ts` in the repo) replays recorded HTTP\n * interactions, but cassettes are static. This mock server covers what\n * cassettes can't:\n *\n * - programmable inter-chunk delays (backpressure handling)\n * - mid-stream **in-band error injection** — an `{\"error\": \"...\"}` NDJSON\n * frame emitted mid-response with HTTP 200 still, exactly how a real\n * Ollama daemon reports GPU OOM / driver crashes mid-generation\n * - connection drops mid-stream (`dropConnectionMidStream`)\n * - 503/502/429 error status codes with custom bodies\n * - arbitrary NDJSON chunk payloads (tool calls, thinking, partial frames)\n *\n * On top of the raw engine, the public surface adds the conveniences a\n * consumer test suite wants on day one:\n *\n * - {@link createMockOllamaServer} factory (the recommended entry point)\n * - built-in **default routes** — the official liveness probe (`HEAD /`\n * and `GET /` → \"Ollama is running\") and `GET /api/version` — so\n * `client.ping()` and friends work before any route is registered.\n * Explicit `register()` calls always win.\n * - **request recording** (`server.requests`, `clearRequests()`) for\n * wire-level assertions without per-route callbacks\n * - **request-aware routes** (`responder`) — per-request responses computed\n * from the recorded method/path/body: fail-twice-then-succeed retry\n * drills, body-dependent payloads, call-count scenarios\n * - NDJSON **chunk builders** ({@link mockChatChunk}, {@link mockTextChunks},\n * {@link mockToolCallChunks}) that produce correctly-shaped `/api/chat`\n * frames — including parallel tool calls in one frame, the documented\n * native behavior\n *\n * ## Usage\n *\n * ```ts\n * import { createMockOllamaServer, mockToolCallChunks } from '@nemesis-oss/ollama-sdk/testing';\n * import { OllamaClient } from '@nemesis-oss/ollama-sdk';\n *\n * const server = createMockOllamaServer(); // ephemeral port, default routes on\n * await server.start();\n *\n * server.register('/api/chat', {\n * chunks: mockToolCallChunks([\n * { name: 'get_weather', arguments: { city: 'Tokyo' } },\n * { name: 'get_time', arguments: { tz: 'Asia/Tokyo' } },\n * ]),\n * });\n *\n * const client = new OllamaClient({ baseUrl: server.baseUrl });\n * // ... exercise the client; assert on server.requests ...\n *\n * await server.stop();\n * ```\n *\n * ## Environment\n *\n * Node.js only — the module builds on `node:http`, which is why it lives in\n * a dedicated subpath export: importing it from the browser/Edge-safe main\n * entry would drag a Node built-in into every bundle. Never re-export this\n * module from `src/index.ts`; the Edge Runtime verification\n * (`npm run verify:edge-runtime`) exists to catch exactly that.\n *\n * Designed for Vitest/Jest: `start()` resolves once the server listens and\n * `stop()` is idempotent, so `beforeEach`/`afterEach` hooks manage the\n * lifecycle without tracking whether `start()` ran.\n */\n\nimport { createServer, type Server, type IncomingMessage, type ServerResponse } from 'node:http';\nimport type { AddressInfo } from 'node:net';\n\n/** One recorded incoming request, for wire-level test assertions. */\nexport interface MockRequestRecord {\n /** HTTP method (`GET`, `POST`, `HEAD`, ...). */\n readonly method: string;\n /** Request path with the query string stripped. */\n readonly path: string;\n /** Parsed request body (JSON-parsed when possible, raw string otherwise); `undefined` for body-less methods. */\n readonly body?: unknown;\n /** ISO-8601 timestamp of when the request arrived. */\n readonly timestamp: string;\n}\n\n/**\n * The response a mock route emits. {@link MockEndpointOptions} extends this\n * with hooks, and a {@link MockEndpointOptions.responder} computes one of\n * these per request. All fields optional — `chunks` defaults to `[]` (useful\n * for testing the \"stream closed without data\" case).\n */\nexport interface MockRouteResponse {\n /** HTTP status code. Defaults to 200. */\n readonly status?: number | undefined;\n /**\n * NDJSON chunks to emit, in order. Each chunk is emitted as a separate\n * `res.write()` call followed by `\\n`. Pass `[]` to emit no body (useful\n * for testing the \"stream closed without data\" case).\n */\n readonly chunks?: readonly string[] | undefined;\n /**\n * Delay (ms) before emitting each chunk. Defaults to 0 (no delay). Set to\n * a small value (5-50ms) to test backpressure handling; set to a large\n * value (10_000ms) to test timeout/cancellation.\n */\n readonly chunkDelayMs?: number | undefined;\n /**\n * Custom response headers. Defaults to\n * `{ 'content-type': 'application/x-ndjson' }` for streaming endpoints.\n * Override for non-JSON responses (e.g. blob uploads).\n */\n readonly headers?: Record<string, string> | undefined;\n /**\n * When `true`, the server closes the connection mid-stream after emitting\n * the first chunk. Use this to test connection-drop recovery. Defaults to\n * `false`.\n */\n readonly dropConnectionMidStream?: boolean | undefined;\n /**\n * Emit this exact string as the whole response body — no NDJSON newline\n * framing. Overrides `chunks` (use it for non-JSON responses such as the\n * plain-text liveness body or raw blob bytes).\n */\n readonly rawBody?: string | undefined;\n /**\n * Inject an in-band error frame — `{\"error\": \"<message>\"}` — into the\n * NDJSON response while the HTTP status stays 200. This is how a real\n * Ollama daemon reports mid-generation failures (GPU OOM, driver crash,\n * context overflow): the status code never changes, the parser has to\n * catch the frame. The SDK's stream readers raise `OllamaStreamError` on\n * it.\n *\n * `after` is the number of chunks emitted before the error frame. The\n * default is `chunks.length - 1` — every content chunk, then the error\n * frame, with the final `done` frame never emitted, exactly what a\n * mid-generation crash looks like on the wire (an error frame *after* the\n * done frame would be unread: the stream has already completed cleanly).\n * `after: 0` errors before any content; an explicit `after >=\n * chunks.length` emits every chunk and then the error. Chunks at or after\n * the injection point are never emitted: the server \"crashed\".\n */\n readonly injectErrorFrame?:\n | {\n readonly after?: number | undefined;\n readonly message: string;\n }\n | undefined;\n}\n\n/**\n * A single mock route handler. The server matches on the request path\n * (query string stripped — Ollama's API doesn't use query params for the\n * routes we care about).\n */\nexport interface MockEndpointOptions extends MockRouteResponse {\n /**\n * Optional callback fired when a request arrives at this route. Receives\n * the parsed request body (or `undefined` if the body wasn't valid JSON).\n * Useful for assertions like \"the client sent the right `model` field\".\n * For global capture across routes see {@link OllamaMockServer.requests}.\n */\n readonly onRequest?: ((body: unknown) => void) | undefined;\n /**\n * Compute this route's response **per request** — request-aware scenario\n * scripting without subclassing. Receives the same {@link MockRequestRecord}\n * that lands in {@link OllamaMockServer.requests} (method, path, parsed\n * body, timestamp); the return value is the complete response for that\n * request, or `undefined` to fall back to the route's static fields.\n * Typical scenarios:\n *\n * ```ts\n * // Fail twice, then serve — retry/backoff drills:\n * let hits = 0;\n * server.register('/api/chat', {\n * chunks: mockTextChunks('recovered'),\n * responder: () =>\n * hits++ < 2 ? { status: 503, chunks: ['{\"error\":\"server queue is full\"}'] } : undefined,\n * });\n *\n * // Body-dependent — answer differently by request payload:\n * server.register('/api/generate', {\n * responder: (record) => ({\n * chunks: [frameFor((record.body as { options?: { draft_num_predict?: number } })\n * .options?.draft_num_predict ?? 0)],\n * }),\n * });\n * ```\n *\n * The return value replaces the static response fields for that request\n * (the fallback only happens on `undefined`), and it feeds the full\n * emission pipeline — `chunkDelayMs`, `injectErrorFrame`,\n * `dropConnectionMidStream`, and `rawBody` all keep their semantics.\n */\n readonly responder?: ((record: MockRequestRecord) => MockRouteResponse | undefined) | undefined;\n}\n\n/** Options for {@link createMockOllamaServer} and the `OllamaMockServer` constructor. */\nexport interface MockServerOptions {\n /** TCP port to listen on. `0` (the default) picks an ephemeral port. */\n readonly port?: number | undefined;\n /**\n * Serve the built-in default routes when no route is explicitly registered\n * for a path: `HEAD /` and `GET /` → `200` (the official liveness probe —\n * `GET /` answers the plain-text body \"Ollama is running\") and\n * `GET /api/version` → `200 {\"version\": \"<version>\"}`. Defaults to `true`.\n * Explicit `register()` calls always take precedence.\n */\n readonly defaultRoutes?: boolean | undefined;\n /** Version reported by the default `GET /api/version` route. Defaults to `'0.14.0'`. */\n readonly version?: string | undefined;\n}\n\n/** Shape accepted by {@link mockToolCallChunks} for each tool call. */\nexport interface MockToolCallSpec {\n /** Tool-call id; auto-generated (`call-0`, `call-1`, …) when omitted. */\n readonly id?: string | undefined;\n /** Tool name, as the model would emit it. */\n readonly name: string;\n /** Tool arguments — an object (stringified by the builder) or a pre-encoded string. */\n readonly arguments: Record<string, unknown> | string;\n}\n\n/** Options for {@link mockTextChunks}. */\nexport interface MockTextChunksOptions {\n /** Split the text into content frames of at most this many characters. Default: one frame with the whole text. */\n readonly chunkSize?: number | undefined;\n /** Model name stamped on each frame. Defaults to `'mock-model'`. */\n readonly model?: string | undefined;\n}\n\n/** Options for {@link mockToolCallChunks}. */\nexport interface MockToolCallChunksOptions {\n /** Model name stamped on each frame. Defaults to `'mock-model'`. */\n readonly model?: string | undefined;\n /** Assistant text to carry on the tool-call frame (some models emit a preamble). Defaults to `''`. */\n readonly content?: string | undefined;\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\n/**\n * One `/api/chat` NDJSON frame as a ready-to-emit string. Sensible defaults:\n * `model: 'mock-model'`, a fresh `created_at`, `done: false`.\n *\n * ```ts\n * server.register('/api/chat', {\n * chunks: [\n * mockChatChunk({ content: 'Hel' }),\n * mockChatChunk({ content: 'lo' }),\n * mockChatChunk({ done: true, evalCount: 2, evalDurationNs: 20_000_000 }),\n * ],\n * });\n * ```\n */\nexport function mockChatChunk(frame: {\n readonly content?: string | undefined;\n readonly toolCalls?: readonly MockToolCallSpec[] | undefined;\n readonly done?: boolean | undefined;\n readonly model?: string | undefined;\n readonly evalCount?: number | undefined;\n readonly evalDurationNs?: number | undefined;\n readonly promptEvalCount?: number | undefined;\n readonly promptEvalDurationNs?: number | undefined;\n readonly promptEvalCachedCount?: number | undefined;\n readonly totalDurationNs?: number | undefined;\n readonly loadDurationNs?: number | undefined;\n}): string {\n const done = frame.done ?? false;\n const message: Record<string, unknown> = {\n role: 'assistant',\n content: frame.content ?? '',\n };\n if (frame.toolCalls !== undefined && frame.toolCalls.length > 0) {\n message['tool_calls'] = frame.toolCalls.map((call, i) => ({\n id: call.id ?? `call-${i}`,\n function: {\n name: call.name,\n arguments:\n typeof call.arguments === 'string' ? call.arguments : JSON.stringify(call.arguments),\n },\n }));\n }\n const payload: Record<string, unknown> = {\n model: frame.model ?? 'mock-model',\n created_at: nowIso(),\n message,\n done,\n };\n if (done) {\n // Counters on the final frame — shaped exactly like the official\n // /api/chat streaming examples so telemetry code paths see real fields.\n payload['total_duration'] = frame.totalDurationNs ?? 50_000_000;\n if (frame.loadDurationNs !== undefined) payload['load_duration'] = frame.loadDurationNs;\n if (frame.promptEvalCount !== undefined) payload['prompt_eval_count'] = frame.promptEvalCount;\n if (frame.promptEvalDurationNs !== undefined) {\n payload['prompt_eval_duration'] = frame.promptEvalDurationNs;\n }\n if (frame.promptEvalCachedCount !== undefined) {\n payload['prompt_eval_cached_count'] = frame.promptEvalCachedCount;\n }\n payload['eval_count'] = frame.evalCount ?? 2;\n payload['eval_duration'] = frame.evalDurationNs ?? 20_000_000;\n }\n return JSON.stringify(payload);\n}\n\n/**\n * Content frames + a final `done` frame for a plain-text `/api/chat` reply.\n * With `chunkSize`, the text is split into that many characters per frame —\n * the shape streaming code needs to exercise incremental assembly.\n *\n * ```ts\n * server.register('/api/chat', {\n * chunks: mockTextChunks('Hello, world!', { chunkSize: 5 }),\n * });\n * ```\n */\nexport function mockTextChunks(text: string, opts: MockTextChunksOptions = {}): string[] {\n const model = opts.model ?? 'mock-model';\n const size = opts.chunkSize && opts.chunkSize > 0 ? opts.chunkSize : text.length || 1;\n const frames: string[] = [];\n if (text.length > 0) {\n for (let i = 0; i < text.length; i += size) {\n frames.push(mockChatChunk({ content: text.slice(i, i + size), model }));\n }\n }\n frames.push(\n mockChatChunk({\n model,\n done: true,\n evalCount: Math.max(1, Math.ceil(text.length / Math.max(1, size))),\n evalDurationNs: 20_000_000,\n totalDurationNs: 50_000_000,\n }),\n );\n return frames;\n}\n\n/**\n * Tool-call frames for `/api/chat` — the documented native shape: tool calls\n * arrive **complete in one frame** (parallel calls = one array with several\n * entries), followed by a final `done` frame. Pair with an `Agent` or tool\n * loop for deterministic tool-execution tests.\n *\n * ```ts\n * // Parallel tool calls, one round trip:\n * server.register('/api/chat', {\n * chunks: mockToolCallChunks([\n * { name: 'get_weather', arguments: { city: 'Tokyo' } },\n * { name: 'get_time', arguments: { tz: 'Asia/Tokyo' } },\n * ]),\n * });\n * ```\n */\nexport function mockToolCallChunks(\n toolCalls: readonly MockToolCallSpec[],\n opts: MockToolCallChunksOptions = {},\n): string[] {\n return [\n mockChatChunk({ model: opts.model, content: opts.content, toolCalls }),\n mockChatChunk({ model: opts.model, done: true, evalCount: 1, evalDurationNs: 10_000_000 }),\n ];\n}\n\n/**\n * Lightweight in-memory Ollama mock server.\n *\n * Spawns a real `node:http` server on a free port (or a fixed port if you\n * pass one). Tests register route handlers via `register()`, then point an\n * `OllamaClient` at `server.baseUrl`. The server emits the registered chunks\n * with the configured delay, status, and connection behavior; when no route\n * is registered the built-in liveness + version defaults answer (see\n * {@link MockServerOptions.defaultRoutes}).\n *\n * Prefer the {@link createMockOllamaServer} factory; the class is exported\n * for typed references and back-compatibility with the SDK's own suite.\n *\n * The server is **single-process** — it doesn't fork or use workers. It's\n * intended for unit/integration tests, not load testing.\n */\nexport class OllamaMockServer {\n private readonly server: Server;\n private readonly routes = new Map<string, MockEndpointOptions>();\n private readonly requestLog: MockRequestRecord[] = [];\n private readonly defaultsEnabled: boolean;\n private readonly defaultVersion: string;\n private port: number;\n\n /**\n * @param portOrOptions Either a TCP port (pass `0` for an ephemeral port —\n * recommended for parallel test runs) or a {@link MockServerOptions}\n * object. The actual port is exposed via {@link baseUrl} after\n * {@link start}.\n */\n constructor(portOrOptions: number | MockServerOptions = 0) {\n const options: MockServerOptions =\n typeof portOrOptions === 'number' ? { port: portOrOptions } : portOrOptions;\n this.port = options.port ?? 0;\n this.defaultsEnabled = options.defaultRoutes ?? true;\n this.defaultVersion = options.version ?? '0.14.0';\n this.server = createServer((req, res) => {\n void this.handleRequest(req, res);\n });\n // Disable Nagle's algorithm so chunks are emitted immediately rather\n // than being coalesced — makes delay/fracture behavior deterministic.\n this.server.on('connection', (socket) => {\n socket.setNoDelay(true);\n });\n }\n\n /**\n * Register a route handler. Replaces any existing handler for the same\n * path (including a built-in default). The path is matched against\n * `req.url` exactly (query string stripped, no template matching — for\n * `/api/blobs/{digest}`, register each specific digest value).\n */\n register(path: string, options: MockEndpointOptions): void {\n this.routes.set(path, options);\n }\n\n /** Clear all registered routes (built-in defaults remain). Useful in `beforeEach` hooks. */\n clear(): void {\n this.routes.clear();\n }\n\n /**\n * Every request this server has served, in arrival order — method, path,\n * parsed body, timestamp — including 404s and default-route hits. Assert\n * on what the client actually put on the wire; clear with\n * {@link clearRequests} (e.g. in `beforeEach`).\n */\n get requests(): readonly MockRequestRecord[] {\n return this.requestLog;\n }\n\n /** Empty the request log ({@link requests}). Routes are unaffected. */\n clearRequests(): void {\n this.requestLog.length = 0;\n }\n\n /**\n * Base URL to point an `OllamaClient` at. Only meaningful after\n * {@link start} has resolved.\n */\n get baseUrl(): string {\n const address = this.server.address() as AddressInfo | null;\n const port = address?.port ?? this.port;\n return `http://127.0.0.1:${port}`;\n }\n\n /**\n * Start listening. Resolves once the server is ready to accept\n * connections.\n */\n start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.server.once('error', reject);\n this.server.listen(this.port, '127.0.0.1', () => {\n this.server.removeListener('error', reject);\n const address = this.server.address() as AddressInfo | null;\n if (address !== null) {\n this.port = address.port;\n }\n resolve();\n });\n });\n }\n\n /**\n * Stop listening and close all active connections. Resolves once the\n * server is fully closed (no lingering sockets). Idempotent — calling\n * `stop()` on an already-stopped server resolves cleanly rather than\n * throwing `ERR_SERVER_NOT_RUNNING`.\n */\n stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n // `server.close()` errors with ERR_SERVER_NOT_RUNNING if the server\n // isn't currently listening. Treat that as a successful no-op so\n // callers can use stop() in afterEach hooks without tracking whether\n // start() was actually called.\n if (!this.server.listening) {\n resolve();\n return;\n }\n this.server.close((err) => {\n if (err && (err as NodeJS.ErrnoException).code !== 'ERR_SERVER_NOT_RUNNING') {\n reject(err);\n return;\n }\n resolve();\n });\n });\n }\n\n /**\n * Built-in default handler for a path, or `undefined` when defaults are\n * disabled or the path isn't one of the official liveness surfaces.\n * Registered routes are checked first and always win.\n */\n private defaultRouteFor(method: string, path: string): MockEndpointOptions | undefined {\n if (!this.defaultsEnabled) {\n return undefined;\n }\n // The official liveness probe: HEAD / → 200 (no body — Node suppresses\n // writes for HEAD responses); GET / → the plain-text body\n // \"Ollama is running\" (docs: the root endpoint answers exactly this).\n if (path === '/' && (method === 'HEAD' || method === 'GET')) {\n return {\n status: 200,\n headers: { 'content-type': 'text/plain' },\n // GET / answers the plain-text body byte-for-byte — no trailing\n // newline, hence rawBody rather than the NDJSON chunk emitter.\n // HEAD / carries no body at all (Node suppresses HEAD writes).\n ...(method === 'GET' ? { rawBody: 'Ollama is running' } : {}),\n };\n }\n if (path === '/api/version' && method === 'GET') {\n return {\n status: 200,\n headers: { 'content-type': 'application/json' },\n chunks: [JSON.stringify({ version: this.defaultVersion })],\n };\n }\n return undefined;\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = req.url ?? '/';\n // Strip query string for route matching — Ollama's API doesn't use\n // query params for the routes we care about, and stripping makes the\n // test setup simpler.\n const path = url.split('?')[0] ?? '/';\n const method = req.method ?? 'GET';\n\n // Capture the request body for recording + the route's onRequest.\n let parsedBody: unknown;\n if (method === 'POST' || method === 'PUT') {\n const bodyChunks: Buffer[] = [];\n for await (const chunk of req) {\n bodyChunks.push(chunk as Buffer);\n }\n const bodyText = Buffer.concat(bodyChunks).toString('utf-8');\n if (bodyText) {\n try {\n parsedBody = JSON.parse(bodyText);\n } catch {\n parsedBody = bodyText;\n }\n }\n }\n\n const record: MockRequestRecord = {\n method,\n path,\n ...(parsedBody !== undefined ? { body: parsedBody } : {}),\n timestamp: nowIso(),\n };\n this.requestLog.push(record);\n\n const route = this.routes.get(path) ?? this.defaultRouteFor(method, path);\n\n if (!route) {\n res.writeHead(404, { 'content-type': 'application/json' });\n res.end(JSON.stringify({ error: `Route not mocked: ${path}` }));\n return;\n }\n\n route.onRequest?.(parsedBody);\n\n // Request-aware routes: the responder computes the response for THIS\n // request (method/path/body in, response out); returning `undefined`\n // falls back to the route's static fields.\n const response: MockRouteResponse =\n route.responder !== undefined ? (route.responder(record) ?? route) : route;\n\n const status = response.status ?? 200;\n const chunks = response.chunks ?? [];\n const chunkDelayMs = response.chunkDelayMs ?? 0;\n const headers = response.headers ?? { 'content-type': 'application/x-ndjson' };\n\n res.writeHead(status, headers);\n\n if (response.rawBody !== undefined) {\n if (chunkDelayMs > 0) {\n await new Promise((r) => setTimeout(r, chunkDelayMs));\n }\n res.write(response.rawBody);\n res.end();\n return;\n }\n\n if (response.dropConnectionMidStream) {\n // Emit the first chunk (if any), then destroy the socket without\n // ending the response — a network drop mid-stream.\n if (chunks.length > 0) {\n if (chunkDelayMs > 0) {\n await new Promise((r) => setTimeout(r, chunkDelayMs));\n }\n res.write(chunks[0] + '\\n');\n }\n res.socket?.destroy();\n return;\n }\n\n // In-band injection point, measured in already-emitted chunks. See\n // MockRouteResponse.injectErrorFrame for the default rationale.\n const errorAt = response.injectErrorFrame\n ? (response.injectErrorFrame.after ?? Math.max(0, chunks.length - 1))\n : Number.POSITIVE_INFINITY;\n const errorMessage = response.injectErrorFrame?.message;\n\n for (let i = 0; i < chunks.length; i++) {\n if (i === errorAt && errorMessage !== undefined) {\n // The server \"crashed\": emit the error frame, never the remaining\n // chunks (no clean done frame — the stream just ends, HTTP 200).\n res.write(JSON.stringify({ error: errorMessage }) + '\\n');\n res.end();\n return;\n }\n if (chunkDelayMs > 0) {\n await new Promise((r) => setTimeout(r, chunkDelayMs));\n }\n res.write(chunks[i] + '\\n');\n }\n // Explicit `after` at or beyond the chunk count: everything, then error.\n if (errorMessage !== undefined && chunks.length <= errorAt) {\n res.write(JSON.stringify({ error: errorMessage }) + '\\n');\n }\n res.end();\n }\n}\n\n/**\n * Create an in-memory Ollama mock server — the recommended entry point for\n * consumer test suites. Ephemeral port, built-in liveness + version\n * defaults on, empty request log. Call `await server.start()` before\n * pointing an `OllamaClient` at `server.baseUrl`, and `await server.stop()`\n * in teardown.\n *\n * ```ts\n * const server = createMockOllamaServer();\n * await server.start();\n * // defaults already answer: HEAD / (ping) and GET /api/version\n * server.register('/api/chat', { chunks: mockTextChunks('Hi!') });\n * ```\n */\nexport function createMockOllamaServer(options: MockServerOptions = {}): OllamaMockServer {\n return new OllamaMockServer(options);\n}\n"]}
|
|
@@ -410,11 +410,22 @@ interface CreateRequestOptions extends RequestCancellationOptions {
|
|
|
410
410
|
readonly modelfile?: string | undefined;
|
|
411
411
|
readonly stream?: boolean | undefined;
|
|
412
412
|
readonly quantize?: string | undefined;
|
|
413
|
-
/**
|
|
413
|
+
/**
|
|
414
|
+
* Quantization level to apply to draft weights during import, independently of the
|
|
415
|
+
* primary `quantize` (e.g. `'nvfp4'`, `'mxfp8'`, `'q8_0'`). Speculative decoding
|
|
416
|
+
* only — draft tokens are verified, not returned, so aggressive compression of the
|
|
417
|
+
* draft network is usually safe.
|
|
418
|
+
*/
|
|
414
419
|
readonly draft_quantize?: string | undefined;
|
|
415
420
|
readonly from?: string | undefined;
|
|
416
421
|
readonly files?: Record<string, string> | undefined;
|
|
417
|
-
/**
|
|
422
|
+
/**
|
|
423
|
+
* Draft source file names mapped to their SHA-256 digests — the speculative-decoding
|
|
424
|
+
* draft network's shards. Ollama runs the small draft network first and batch-verifies
|
|
425
|
+
* its tokens against the primary weights in a single forward pass. Use
|
|
426
|
+
* {@link ModelsClient.createModelFromGguf}'s `draftGguf` to upload draft shards from
|
|
427
|
+
* local paths directly.
|
|
428
|
+
*/
|
|
418
429
|
readonly draft_files?: Record<string, string> | undefined;
|
|
419
430
|
readonly adapters?: Record<string, string> | undefined;
|
|
420
431
|
readonly template?: string | undefined;
|
|
@@ -422,7 +433,13 @@ interface CreateRequestOptions extends RequestCancellationOptions {
|
|
|
422
433
|
readonly parser?: string | undefined;
|
|
423
434
|
readonly license?: string | readonly string[] | undefined;
|
|
424
435
|
readonly system?: string | undefined;
|
|
425
|
-
/**
|
|
436
|
+
/**
|
|
437
|
+
* Modelfile `PARAMETER` instructions, e.g. `{ temperature: 0.7, stop: ['\n'] }`.
|
|
438
|
+
* For speculative decoding, set `draft_num_predict` here — how many tokens
|
|
439
|
+
* the draft network predicts per step (Ollama defaults separate draft
|
|
440
|
+
* models to 4; `0` disables drafting; models with embedded MTP tensors
|
|
441
|
+
* require setting it explicitly).
|
|
442
|
+
*/
|
|
426
443
|
readonly parameters?: Record<string, unknown> | undefined;
|
|
427
444
|
readonly messages?: readonly Message[] | undefined;
|
|
428
445
|
/** Minimum Ollama version required by the model. */
|
|
@@ -410,11 +410,22 @@ interface CreateRequestOptions extends RequestCancellationOptions {
|
|
|
410
410
|
readonly modelfile?: string | undefined;
|
|
411
411
|
readonly stream?: boolean | undefined;
|
|
412
412
|
readonly quantize?: string | undefined;
|
|
413
|
-
/**
|
|
413
|
+
/**
|
|
414
|
+
* Quantization level to apply to draft weights during import, independently of the
|
|
415
|
+
* primary `quantize` (e.g. `'nvfp4'`, `'mxfp8'`, `'q8_0'`). Speculative decoding
|
|
416
|
+
* only — draft tokens are verified, not returned, so aggressive compression of the
|
|
417
|
+
* draft network is usually safe.
|
|
418
|
+
*/
|
|
414
419
|
readonly draft_quantize?: string | undefined;
|
|
415
420
|
readonly from?: string | undefined;
|
|
416
421
|
readonly files?: Record<string, string> | undefined;
|
|
417
|
-
/**
|
|
422
|
+
/**
|
|
423
|
+
* Draft source file names mapped to their SHA-256 digests — the speculative-decoding
|
|
424
|
+
* draft network's shards. Ollama runs the small draft network first and batch-verifies
|
|
425
|
+
* its tokens against the primary weights in a single forward pass. Use
|
|
426
|
+
* {@link ModelsClient.createModelFromGguf}'s `draftGguf` to upload draft shards from
|
|
427
|
+
* local paths directly.
|
|
428
|
+
*/
|
|
418
429
|
readonly draft_files?: Record<string, string> | undefined;
|
|
419
430
|
readonly adapters?: Record<string, string> | undefined;
|
|
420
431
|
readonly template?: string | undefined;
|
|
@@ -422,7 +433,13 @@ interface CreateRequestOptions extends RequestCancellationOptions {
|
|
|
422
433
|
readonly parser?: string | undefined;
|
|
423
434
|
readonly license?: string | readonly string[] | undefined;
|
|
424
435
|
readonly system?: string | undefined;
|
|
425
|
-
/**
|
|
436
|
+
/**
|
|
437
|
+
* Modelfile `PARAMETER` instructions, e.g. `{ temperature: 0.7, stop: ['\n'] }`.
|
|
438
|
+
* For speculative decoding, set `draft_num_predict` here — how many tokens
|
|
439
|
+
* the draft network predicts per step (Ollama defaults separate draft
|
|
440
|
+
* models to 4; `0` disables drafting; models with embedded MTP tensors
|
|
441
|
+
* require setting it explicitly).
|
|
442
|
+
*/
|
|
426
443
|
readonly parameters?: Record<string, unknown> | undefined;
|
|
427
444
|
readonly messages?: readonly Message[] | undefined;
|
|
428
445
|
/** Minimum Ollama version required by the model. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nemesis-oss/ollama-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "Production-grade TypeScript SDK for Ollama with native fetch, high availability failover, multi-turn tool calling, structured outputs, reasoning stream tokens, OpenAI/Anthropic bridges, MCP, Web Stream adapters, and a contract-first hybrid architecture that generates TypeScript types, API classes, MCP tools, and Zod schemas from a single canonical IR.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ollama",
|
|
@@ -59,6 +59,16 @@
|
|
|
59
59
|
"default": "./dist/skills.cjs"
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
|
+
"./testing": {
|
|
63
|
+
"import": {
|
|
64
|
+
"types": "./dist/testing.d.ts",
|
|
65
|
+
"default": "./dist/testing.js"
|
|
66
|
+
},
|
|
67
|
+
"require": {
|
|
68
|
+
"types": "./dist/testing.d.cts",
|
|
69
|
+
"default": "./dist/testing.cjs"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
62
72
|
"./package.json": "./package.json",
|
|
63
73
|
"./mcp/stdio": {
|
|
64
74
|
"import": {
|
|
@@ -126,6 +136,9 @@
|
|
|
126
136
|
"skills": [
|
|
127
137
|
"dist/skills.d.ts"
|
|
128
138
|
],
|
|
139
|
+
"testing": [
|
|
140
|
+
"dist/testing.d.ts"
|
|
141
|
+
],
|
|
129
142
|
"mcp/stdio": [
|
|
130
143
|
"dist/mcp-stdio.d.ts"
|
|
131
144
|
],
|