modelpact-providers 1.0.0 → 1.2.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/README.md +264 -11
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/ollama.d.ts +39 -0
- package/dist/ollama.d.ts.map +1 -0
- package/dist/ollama.js +442 -0
- package/dist/ollama.js.map +1 -0
- package/dist/openai.d.ts +60 -0
- package/dist/openai.d.ts.map +1 -0
- package/dist/openai.js +488 -0
- package/dist/openai.js.map +1 -0
- package/dist/prompt-api.d.ts +26 -0
- package/dist/prompt-api.d.ts.map +1 -0
- package/dist/prompt-api.js +261 -0
- package/dist/prompt-api.js.map +1 -0
- package/dist/webgpu.d.ts +73 -0
- package/dist/webgpu.d.ts.map +1 -0
- package/dist/webgpu.js +214 -0
- package/dist/webgpu.js.map +1 -0
- package/package.json +29 -5
package/README.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# modelpact-providers
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/modelpact-providers)
|
|
4
|
+
[](https://github.com/AvdienkoSergey/modelpact-providers/actions/workflows/ci.yml)
|
|
5
|
+

|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
**The transports for [modelpact](https://github.com/AvdienkoSergey/modelpact):
|
|
9
|
+
a daemon on your machine, any OpenAI-compatible server, the model inside
|
|
10
|
+
Chrome, and a model in the tab itself. Four backends, one contract, and that
|
|
11
|
+
contract's suite green on each.**
|
|
12
|
+
|
|
13
|
+
The engine holds the contract, the lifecycle and one backend with nothing
|
|
14
|
+
behind it. This package holds the ones with something behind them. They are
|
|
15
|
+
apart because they change for different reasons: a daemon's JSON, a hosted
|
|
16
|
+
API's dialect, a browser's origin trial and a WebGPU runtime each move on their
|
|
17
|
+
own clock, and none of them should move the contract.
|
|
4
18
|
|
|
5
19
|
## Install
|
|
6
20
|
|
|
@@ -8,19 +22,258 @@ Language-model backends written against the modelpact contract — one transport
|
|
|
8
22
|
npm install modelpact-providers modelpact
|
|
9
23
|
```
|
|
10
24
|
|
|
11
|
-
`modelpact` is a peer dependency: this package is
|
|
12
|
-
and
|
|
25
|
+
`modelpact` is a peer dependency: this package is written against its contract
|
|
26
|
+
and carries no copy of it.
|
|
27
|
+
|
|
28
|
+
## The four
|
|
29
|
+
|
|
30
|
+
| Provider | Reaches | Wants | Import from |
|
|
31
|
+
| ----------------------- | ----------------------------------------- | -------------------------------------------------- | ---------------------------- |
|
|
32
|
+
| `makeOllamaProvider` | a daemon over HTTP, usually local | Ollama on `127.0.0.1:11434` | `modelpact-providers` |
|
|
33
|
+
| `makeOpenAiProvider` | anything speaking the OpenAI HTTP dialect | a `baseUrl`; a key only where the server wants one | `modelpact-providers` |
|
|
34
|
+
| `makePromptApiProvider` | Chrome's built-in Gemini Nano | Chrome, and the weights downloaded once | `modelpact-providers` |
|
|
35
|
+
| `makeWebGpuProvider` | a model in the tab, on WebGPU | `@mlc-ai/web-llm`, and a GPU | `modelpact-providers/webgpu` |
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { makeOllamaProvider } from "modelpact-providers";
|
|
39
|
+
|
|
40
|
+
const access = await makeOllamaProvider({ model: "granite4:350m" }).access();
|
|
41
|
+
if (access.kind !== "ready") return;
|
|
42
|
+
const opened = await access.open({ system: "Answer in one sentence." });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Everything after the provider line is the contract's, and identical across the
|
|
46
|
+
four — see [modelpact's README](https://github.com/AvdienkoSergey/modelpact#readme)
|
|
47
|
+
for what a session promises.
|
|
48
|
+
|
|
49
|
+
## Two entries, and the reason
|
|
50
|
+
|
|
51
|
+
`modelpact-providers` is the three that cost a consumer nothing: `fetch` and
|
|
52
|
+
JSON for the daemon and for the OpenAI dialect, a global for the browser's own
|
|
53
|
+
model, no runtime dependency behind any of them.
|
|
54
|
+
`modelpact-providers/webgpu` is the fourth, because it carries
|
|
55
|
+
`@mlc-ai/web-llm` — an optional peer dependency, so an app on the daemon never
|
|
56
|
+
installs it. The split is by dependency, not by kind: the same reason
|
|
57
|
+
`modelpact/testing` is a separate entry for `vitest`.
|
|
58
|
+
|
|
59
|
+
## What each one is
|
|
60
|
+
|
|
61
|
+
**Ollama.** Three endpoints are the whole backend — `/api/tags` says what is
|
|
62
|
+
downloaded, `/api/pull` downloads, `/api/chat` generates. Shapes were read off
|
|
63
|
+
a running daemon, not off the docs: a chat stream is NDJSON whose last line
|
|
64
|
+
carries the counts, a pull line carries `completed` and `total` per layer, and
|
|
65
|
+
an error is an HTTP status with a body. The daemon keeps nothing between
|
|
66
|
+
requests, so the session's record is resent whole every turn.
|
|
67
|
+
|
|
68
|
+
**An OpenAI-compatible server.** A dialect rather than a company:
|
|
69
|
+
`https://api.openai.com/v1` is the default and one instance of it, and the same
|
|
70
|
+
two endpoints answer on vLLM, llama.cpp, LM Studio, OpenRouter, Groq and
|
|
71
|
+
Ollama's own `/v1`. So `baseUrl` is the whole difference between them and
|
|
72
|
+
`apiKey` is optional — a model on your machine wants no key, and a type that
|
|
73
|
+
demanded one would be describing a service instead of a protocol. It is also
|
|
74
|
+
the only backend here that never answers `needs-download`: the weights are the
|
|
75
|
+
server's problem, and there is nothing this side could fetch.
|
|
76
|
+
|
|
77
|
+
Two things the wire does that the daemon next door does not, and both are
|
|
78
|
+
handled rather than assumed: a tool call arrives fragmented across frames,
|
|
79
|
+
keyed by `index`, with its arguments as a JSON string rather than an object;
|
|
80
|
+
and the counts arrive in a frame of their own after the last one carrying text,
|
|
81
|
+
which is what `stream_options: { include_usage: true }` asks for.
|
|
82
|
+
|
|
83
|
+
`contextWindow` is optional, and absent it `usage()` answers `unknown`. No
|
|
84
|
+
server in this dialect reports the window it loaded a model with, so a number
|
|
85
|
+
there is your declaration, not a discovery — and being a declaration is what
|
|
86
|
+
makes it a budget too: a transcript past it is an overflow, told by the counts
|
|
87
|
+
rather than by the server.
|
|
88
|
+
|
|
89
|
+
**Chrome's built-in model.** The one backend that keeps the conversation
|
|
90
|
+
itself: `LanguageModel` is a session object and `prompt()` appends to it, so
|
|
91
|
+
the record travels with the session rather than in the request. It fires its
|
|
92
|
+
own `contextoverflow`, which is forwarded rather than re-derived, and reports
|
|
93
|
+
usage against a window it decides — 9 216 tokens on Chrome 152, measured.
|
|
94
|
+
The declarations are `@types/dom-chromium-ai`, patched under
|
|
95
|
+
[`patches/`](patches) because the IDL is looser than the spec: several states
|
|
96
|
+
the algorithm rejects at runtime are writable in the types, and a TS error at
|
|
97
|
+
the keyboard beats a `TypeError` in the browser.
|
|
98
|
+
|
|
99
|
+
**WebGPU.** A model in the tab through `@mlc-ai/web-llm`, and the only backend
|
|
100
|
+
whose download costs the user their bandwidth rather than a daemon's. It was
|
|
101
|
+
written before this package existed, in a directory one repository over, to
|
|
102
|
+
answer one question: is the published API enough to write a backend with. It
|
|
103
|
+
was, and it needed nothing added to the contract.
|
|
104
|
+
|
|
105
|
+
## Tools
|
|
106
|
+
|
|
107
|
+
All four accept `ModelRequest.tools`, and each executes them the way its
|
|
108
|
+
transport can.
|
|
109
|
+
|
|
110
|
+
| Provider | How a call happens |
|
|
111
|
+
| ---------- | --------------------------------------------------------------------------------------------------- |
|
|
112
|
+
| Ollama | native `tool_calls`, answered under the `tool` role, in rounds bounded by `maxToolRounds` |
|
|
113
|
+
| OpenAI | the same, tied by `tool_call_id` rather than by name, so two calls to one tool in a turn stay apart |
|
|
114
|
+
| Prompt API | handed to `create()`, and the browser calls `execute` itself |
|
|
115
|
+
| WebGPU | not yet: the request is refused at `access`, which is the contract's answer for a backend without |
|
|
116
|
+
|
|
117
|
+
Chrome 152 answers `available` to `availability()` with tools and then throws
|
|
118
|
+
`InvalidStateError` from `create()` — measured, and it arrives as a refusal at
|
|
119
|
+
`open`. A loop above should expect a refusal in both places and fall back to a
|
|
120
|
+
schema-constrained answer.
|
|
121
|
+
|
|
122
|
+
## The guard
|
|
123
|
+
|
|
124
|
+
[`src/surface.ts`](src/surface.ts) names every published type on both sides —
|
|
125
|
+
the engine's and this package's — and
|
|
126
|
+
[`tsconfig.surface.json`](tsconfig.surface.json) compiles it with
|
|
127
|
+
`skipLibCheck` off and `types: []`, which is how a consumer reads a `.d.ts`. A
|
|
128
|
+
declaration that needs an ambient global fails there and nowhere else.
|
|
129
|
+
|
|
130
|
+
That guard has found the same bug three times, in three packages. A published
|
|
131
|
+
type naming `LanguageModel` broke a consumer who never installed
|
|
132
|
+
`@types/dom-chromium-ai`. A `WebGpuConfig.engine` typed with
|
|
133
|
+
`MLCEngineInterface` broke one the same way, through `@mlc-ai/web-llm`'s own
|
|
134
|
+
declarations, which name packages they do not depend on. Both fixes are the
|
|
135
|
+
same: a structural type of exactly what the backend uses, named locally, and no
|
|
136
|
+
third-party type in any exported signature.
|
|
137
|
+
|
|
138
|
+
Moving here found a third. `@mlc-ai/web-llm`'s `interruptGenerate()` returns a
|
|
139
|
+
promise, though its own published interface says it returns nothing; the
|
|
140
|
+
adapter called it and dropped that promise on the floor. It is marked `void`
|
|
141
|
+
now, deliberately, because by the time it runs the lifecycle has already
|
|
142
|
+
answered the caller.
|
|
143
|
+
|
|
144
|
+
Three tsconfigs, and each has one job:
|
|
145
|
+
|
|
146
|
+
| File | Checks |
|
|
147
|
+
| ------------------------------------------------ | -------------------------------------------------------------------------- |
|
|
148
|
+
| [`tsconfig.json`](tsconfig.json) | the source. `skipLibCheck` on, because `@mlc-ai/web-llm` cannot survive it |
|
|
149
|
+
| [`tsconfig.patched.json`](tsconfig.patched.json) | everything but WebGPU, with `skipLibCheck` off — the patch, still applying |
|
|
150
|
+
| [`tsconfig.surface.json`](tsconfig.surface.json) | the emitted declarations, as a consumer receives them |
|
|
151
|
+
|
|
152
|
+
[`demo/tsconfig.json`](demo/tsconfig.json) is the fourth, and the only one that
|
|
153
|
+
is an application rather than a check: `types: ["vite/client"]`, no ambient
|
|
154
|
+
Prompt API and no `@mlc-ai/web-llm`, which is the same claim made by code that
|
|
155
|
+
actually imports and calls the things. It is where the demo caught the
|
|
156
|
+
`MLCEngineInterface` leak the first time.
|
|
13
157
|
|
|
14
158
|
## Scripts
|
|
15
159
|
|
|
16
|
-
| Script
|
|
17
|
-
|
|
|
18
|
-
| `npm run typecheck`
|
|
19
|
-
| `npm run lint`
|
|
20
|
-
| `npm run format:check`
|
|
21
|
-
| `npm test`
|
|
22
|
-
| `npm run test:
|
|
23
|
-
| `npm run
|
|
160
|
+
| Script | What it does |
|
|
161
|
+
| ----------------------- | ------------------------------------------------------ |
|
|
162
|
+
| `npm run typecheck` | both source configs, and the specs |
|
|
163
|
+
| `npm run lint` | ESLint, type-aware |
|
|
164
|
+
| `npm run format:check` | Prettier, check only |
|
|
165
|
+
| `npm test` | Vitest; the Ollama contract suite skips with no daemon |
|
|
166
|
+
| `npm run test:e2e` | Playwright; starts the demo itself |
|
|
167
|
+
| `npm run check:surface` | builds, then reads the declarations from outside |
|
|
168
|
+
| `npm run demo` | the demo on a dev server |
|
|
169
|
+
| `npm run demo:check` | the demo's own tsconfig — a consumer with no `@types` |
|
|
170
|
+
| `npm run build` | `dist/` — JS, declarations, maps |
|
|
171
|
+
|
|
172
|
+
The Ollama suite wants a daemon on `127.0.0.1:11434` holding `granite4:350m`,
|
|
173
|
+
and the OpenAI suite wants an OpenAI-compatible server — that same daemon's
|
|
174
|
+
`/v1`, by default, which is a genuine third-party implementation of the dialect
|
|
175
|
+
and already there. Without one, each skips loudly rather than passing quietly.
|
|
176
|
+
|
|
177
|
+
## The demo
|
|
178
|
+
|
|
179
|
+
[`demo/`](demo) is a chat with all four transports behind one picker, and
|
|
180
|
+
nothing else behind it: no mock, because the engine's demo has one and this
|
|
181
|
+
repository is about what happens when there is something on the other end. On a
|
|
182
|
+
machine with no daemon, no Gemini Nano and no GPU, every entry therefore answers
|
|
183
|
+
`unavailable` — honest, and dull. A daemon on `127.0.0.1:11434` holding
|
|
184
|
+
`granite4:350m` is what makes two of the four entries answer.
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
npm install
|
|
188
|
+
npm run demo
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
It takes `modelpact` from npm, at the version a stranger would get, and this
|
|
192
|
+
package from `file:..` through its own `exports` — so what runs in the page is
|
|
193
|
+
`dist/`, never `src/`. Both land on one copy of the engine because `demo` is a
|
|
194
|
+
workspace of this repository; the reason that matters, and what breaks without
|
|
195
|
+
it, is in [`demo/README.md`](demo/README.md).
|
|
196
|
+
|
|
197
|
+
Export `OPENAI_API_KEY` before `npm run demo` and the `openai` entry reaches
|
|
198
|
+
`api.openai.com` instead of the daemon, through a dev-server proxy that holds
|
|
199
|
+
the key in Node — the page is never told it, and a build never carries it. See
|
|
200
|
+
[`demo/README.md`](demo/README.md#pointing-it-at-hosted-openai).
|
|
201
|
+
|
|
202
|
+
It also type-checks itself with `types: ["vite/client"]` and nothing else,
|
|
203
|
+
which makes it the second half of the surface guard above: a declaration that
|
|
204
|
+
needs an ambient global fails in an app that never installed one.
|
|
205
|
+
|
|
206
|
+
## The browser suite
|
|
207
|
+
|
|
208
|
+
[`e2e/demo-e2e.spec.ts`](e2e/demo-e2e.spec.ts) drives the demo in Chromium.
|
|
209
|
+
|
|
210
|
+
```sh
|
|
211
|
+
npx playwright install chromium # once
|
|
212
|
+
npm run test:e2e # the demo server starts itself
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Eleven specs. The vitest suites next to each backend check its logic against
|
|
216
|
+
the contract from node; these check what node cannot see:
|
|
217
|
+
|
|
218
|
+
- a page is not node. `fetch` held on its own throws `Illegal invocation` in
|
|
219
|
+
one and works in the other, and that bug is invisible to any vitest run;
|
|
220
|
+
- `LanguageModel` and `navigator.gpu` exist in a browser and nowhere else, so
|
|
221
|
+
the Prompt API and WebGPU backends have their first real `availability()`
|
|
222
|
+
call here;
|
|
223
|
+
- the emitted `.d.ts` files, a bundler, and React sit between the app and the
|
|
224
|
+
backend, which no unit test reproduces.
|
|
225
|
+
|
|
226
|
+
Seven of them want a daemon and skip without one — everything that needs a
|
|
227
|
+
session to actually open, which since the mock left the picker means every
|
|
228
|
+
promise the contract makes about a session. That is the cost of a demo about
|
|
229
|
+
transports, and it is paid where it belongs: CI installs a daemon for this job.
|
|
230
|
+
|
|
231
|
+
The other four assert a branch rather than a machine, and are green anywhere. A
|
|
232
|
+
runner with no Gemini Nano and no GPU still has `unavailable` to land on, and
|
|
233
|
+
landing on it is the claim. Both HTTP transports get their refusal answer on
|
|
234
|
+
every machine too, including a laptop with Ollama running, because that spec
|
|
235
|
+
refuses the connection itself rather than waiting for a machine without one.
|
|
236
|
+
|
|
237
|
+
## CI
|
|
238
|
+
|
|
239
|
+
[`.github/workflows/ci.yml`](.github/workflows/ci.yml) has three jobs, and each
|
|
240
|
+
can go red on its own:
|
|
241
|
+
|
|
242
|
+
| Job | Runs |
|
|
243
|
+
| -------- | ------------------------------------------------------------------------ |
|
|
244
|
+
| `check` | typecheck, lint, format, vitest, `check:surface` — one install, no model |
|
|
245
|
+
| `ollama` | the same vitest suites with a daemon answering |
|
|
246
|
+
| `e2e` | Playwright against the demo, with a daemon, in Chromium |
|
|
247
|
+
|
|
248
|
+
**Adding the browser suite to a fork or another pipeline** is four steps:
|
|
249
|
+
|
|
250
|
+
```yaml
|
|
251
|
+
- uses: actions/setup-node@v7
|
|
252
|
+
with:
|
|
253
|
+
node-version-file: .nvmrc
|
|
254
|
+
cache: npm
|
|
255
|
+
# `demo` is a workspace, so this installs it too — and puts one copy of
|
|
256
|
+
# `modelpact` where both it and this package find it.
|
|
257
|
+
- run: npm ci
|
|
258
|
+
- run: npx playwright install --with-deps chromium
|
|
259
|
+
- run: npm run test:e2e
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`npm run test:e2e` starts the demo itself, and the demo's `predev` builds
|
|
263
|
+
`dist/` first, so there is no build step to add and no server to start.
|
|
264
|
+
|
|
265
|
+
Two options on top of that:
|
|
266
|
+
|
|
267
|
+
- **A daemon**, which is not really optional any more: half the specs skip
|
|
268
|
+
without one. Install Ollama, `ollama serve`, `ollama pull granite4:350m`, and
|
|
269
|
+
cache `~/.ollama/models` — the `e2e` job does exactly this, restore-only,
|
|
270
|
+
sharing the key the `ollama` job saves. Without it the suite still passes,
|
|
271
|
+
on the four specs that assert a branch rather than a session.
|
|
272
|
+
- **The report on failure**, which is `actions/upload-artifact` over
|
|
273
|
+
`playwright-report/`. Playwright writes it whether or not anyone collects it.
|
|
274
|
+
|
|
275
|
+
Nothing here needs a GPU or a Chrome with Gemini Nano. Those two backends
|
|
276
|
+
answer `unavailable` on a plain runner, and the specs assert the branch.
|
|
24
277
|
|
|
25
278
|
## Releases
|
|
26
279
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The transports that cost a consumer nothing but this package: `fetch` and
|
|
3
|
+
* JSON for the daemon and for the OpenAI dialect, a global for the browser's
|
|
4
|
+
* own model, no runtime dependency behind any of them. Import one and a
|
|
5
|
+
* bundler drops the rest.
|
|
6
|
+
*
|
|
7
|
+
* The WebGPU backend is `modelpact-providers/webgpu` instead, because it
|
|
8
|
+
* carries `@mlc-ai/web-llm` — a separate entry for a separate dependency, the
|
|
9
|
+
* way `modelpact/testing` is separate for `vitest`.
|
|
10
|
+
*/
|
|
11
|
+
export { makeOllamaProvider, type OllamaConfig } from "./ollama.js";
|
|
12
|
+
export { makeOpenAiProvider, type OpenAiConfig } from "./openai.js";
|
|
13
|
+
export { makePromptApiProvider } from "./prompt-api.js";
|
|
2
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The transports that cost a consumer nothing but this package: `fetch` and
|
|
3
|
+
* JSON for the daemon and for the OpenAI dialect, a global for the browser's
|
|
4
|
+
* own model, no runtime dependency behind any of them. Import one and a
|
|
5
|
+
* bundler drops the rest.
|
|
6
|
+
*
|
|
7
|
+
* The WebGPU backend is `modelpact-providers/webgpu` instead, because it
|
|
8
|
+
* carries `@mlc-ai/web-llm` — a separate entry for a separate dependency, the
|
|
9
|
+
* way `modelpact/testing` is separate for `vitest`.
|
|
10
|
+
*/
|
|
11
|
+
export { makeOllamaProvider } from "./ollama.js";
|
|
12
|
+
export { makeOpenAiProvider } from "./openai.js";
|
|
13
|
+
export { makePromptApiProvider } from "./prompt-api.js";
|
|
2
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,kBAAkB,EAAqB,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAqB,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/ollama.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama on a machine you can reach over HTTP.
|
|
3
|
+
*
|
|
4
|
+
* The daemon keeps nothing between requests: `/api/chat` is handed the whole
|
|
5
|
+
* conversation every time, which is what `request.history` is for. Three
|
|
6
|
+
* endpoints are the whole backend — `/api/tags` says what is downloaded,
|
|
7
|
+
* `/api/pull` downloads, `/api/chat` generates — and everything else the
|
|
8
|
+
* contract promises is the lifecycle's, back in `modelpact`.
|
|
9
|
+
*
|
|
10
|
+
* Shapes here were read off a running daemon, not off the docs: a chat stream
|
|
11
|
+
* is NDJSON whose last line carries the counts, a pull line carries `completed`
|
|
12
|
+
* and `total` per layer, and an error is an HTTP status with `{"error": "…"}`.
|
|
13
|
+
*/
|
|
14
|
+
import { type AiProvider } from "modelpact/backend";
|
|
15
|
+
export interface OllamaConfig {
|
|
16
|
+
/** The tag as `/api/tags` lists it, such as `granite4:350m`. */
|
|
17
|
+
readonly model: string;
|
|
18
|
+
/**
|
|
19
|
+
* `127.0.0.1` and not `localhost`: the daemon binds the one, and the name
|
|
20
|
+
* can resolve to the other family first and refuse the connection.
|
|
21
|
+
*/
|
|
22
|
+
readonly host?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Sent as `num_ctx`, and therefore the window in force rather than a guess
|
|
25
|
+
* at one. The default matches the daemon's own; a model that can take more
|
|
26
|
+
* will, at the price of the memory the cache for it costs.
|
|
27
|
+
*/
|
|
28
|
+
readonly contextWindow?: number;
|
|
29
|
+
/** For a proxy, an auth header, or a test with no daemon behind it. */
|
|
30
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
31
|
+
/**
|
|
32
|
+
* How many times one turn may come back with tool calls before it is failed.
|
|
33
|
+
* Per turn, not per session: a model that keeps asking spends the window on
|
|
34
|
+
* its own questions and never answers.
|
|
35
|
+
*/
|
|
36
|
+
readonly maxToolRounds?: number;
|
|
37
|
+
}
|
|
38
|
+
export declare function makeOllamaProvider(config: OllamaConfig): AiProvider;
|
|
39
|
+
//# sourceMappingURL=ollama.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../src/ollama.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAaL,KAAK,UAAU,EAUhB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,uEAAuE;IACvE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAsiBD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CASnE"}
|