opencode-ext-connector 0.3.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 +39 -0
- package/LICENSE +29 -0
- package/README.md +207 -0
- package/THIRD_PARTY_NOTICES.md +201 -0
- package/dist/catalog/parse-ids.d.ts +2 -0
- package/dist/catalog/parse-ids.js +49 -0
- package/dist/core/adapter.d.ts +16 -0
- package/dist/core/adapter.js +20 -0
- package/dist/core/clock.d.ts +7 -0
- package/dist/core/clock.js +1 -0
- package/dist/core/deadline.d.ts +13 -0
- package/dist/core/deadline.js +54 -0
- package/dist/core/errors.d.ts +57 -0
- package/dist/core/errors.js +81 -0
- package/dist/core/health.d.ts +22 -0
- package/dist/core/health.js +30 -0
- package/dist/core/http.d.ts +28 -0
- package/dist/core/http.js +1 -0
- package/dist/core/ids.d.ts +7 -0
- package/dist/core/ids.js +23 -0
- package/dist/core/lifecycle.d.ts +4 -0
- package/dist/core/lifecycle.js +16 -0
- package/dist/core/logger.d.ts +21 -0
- package/dist/core/logger.js +61 -0
- package/dist/core/models.d.ts +41 -0
- package/dist/core/models.js +59 -0
- package/dist/core/options.d.ts +31 -0
- package/dist/core/options.js +62 -0
- package/dist/core/process.d.ts +20 -0
- package/dist/core/process.js +1 -0
- package/dist/http/fetch-transport.d.ts +2 -0
- package/dist/http/fetch-transport.js +75 -0
- package/dist/http/package-version.d.ts +7 -0
- package/dist/http/package-version.js +46 -0
- package/dist/http/read-body.d.ts +9 -0
- package/dist/http/read-body.js +22 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/logging/logger.d.ts +4 -0
- package/dist/logging/logger.js +11 -0
- package/dist/opencode/auth-store.d.ts +19 -0
- package/dist/opencode/auth-store.js +107 -0
- package/dist/opencode/beta-api.d.ts +3 -0
- package/dist/opencode/beta-api.js +1 -0
- package/dist/opencode/catalog-bridge.d.ts +3 -0
- package/dist/opencode/catalog-bridge.js +85 -0
- package/dist/opencode/health-refresh.d.ts +16 -0
- package/dist/opencode/health-refresh.js +49 -0
- package/dist/opencode/host-options.d.ts +2 -0
- package/dist/opencode/host-options.js +49 -0
- package/dist/opencode/language-factory.d.ts +13 -0
- package/dist/opencode/language-factory.js +37 -0
- package/dist/opencode/ollama-probe.d.ts +2 -0
- package/dist/opencode/ollama-probe.js +15 -0
- package/dist/opencode/ollama-production.d.ts +4 -0
- package/dist/opencode/ollama-production.js +10 -0
- package/dist/opencode/plugin.d.ts +33 -0
- package/dist/opencode/plugin.js +40 -0
- package/dist/opencode/process-exit.d.ts +4 -0
- package/dist/opencode/process-exit.js +22 -0
- package/dist/opencode/provider-entry.d.ts +25 -0
- package/dist/opencode/provider-entry.js +1 -0
- package/dist/opencode/providers.d.ts +16 -0
- package/dist/opencode/providers.js +140 -0
- package/dist/opencode/register-integrations.d.ts +3 -0
- package/dist/opencode/register-integrations.js +8 -0
- package/dist/opencode/reload.d.ts +9 -0
- package/dist/opencode/reload.js +30 -0
- package/dist/opencode/v1-anthropic-auth.d.ts +9 -0
- package/dist/opencode/v1-anthropic-auth.js +55 -0
- package/dist/opencode/v1-catalog.d.ts +13 -0
- package/dist/opencode/v1-catalog.js +80 -0
- package/dist/opencode/v1-language.d.ts +3 -0
- package/dist/opencode/v1-language.js +64 -0
- package/dist/opencode/v1-module.d.ts +23 -0
- package/dist/opencode/v1-module.js +74 -0
- package/dist/opencode/v1-session-auth.d.ts +5 -0
- package/dist/opencode/v1-session-auth.js +98 -0
- package/dist/providers/claude/adapter.d.ts +7 -0
- package/dist/providers/claude/adapter.js +37 -0
- package/dist/providers/claude/atomic-private-file.d.ts +13 -0
- package/dist/providers/claude/atomic-private-file.js +94 -0
- package/dist/providers/claude/auth-json.d.ts +2 -0
- package/dist/providers/claude/auth-json.js +14 -0
- package/dist/providers/claude/auth.d.ts +24 -0
- package/dist/providers/claude/auth.js +200 -0
- package/dist/providers/claude/cli-version.d.ts +10 -0
- package/dist/providers/claude/cli-version.js +36 -0
- package/dist/providers/claude/compat-betas.d.ts +5 -0
- package/dist/providers/claude/compat-betas.js +54 -0
- package/dist/providers/claude/compat-config.d.ts +8 -0
- package/dist/providers/claude/compat-config.js +31 -0
- package/dist/providers/claude/compat-request.d.ts +12 -0
- package/dist/providers/claude/compat-request.js +151 -0
- package/dist/providers/claude/compat-response.d.ts +1 -0
- package/dist/providers/claude/compat-response.js +54 -0
- package/dist/providers/claude/compat-signing.d.ts +9 -0
- package/dist/providers/claude/compat-signing.js +24 -0
- package/dist/providers/claude/compat-transform.d.ts +3 -0
- package/dist/providers/claude/compat-transform.js +224 -0
- package/dist/providers/claude/credentials.d.ts +7 -0
- package/dist/providers/claude/credentials.js +37 -0
- package/dist/providers/claude/emit-stream.d.ts +2 -0
- package/dist/providers/claude/emit-stream.js +62 -0
- package/dist/providers/claude/keychain-account.d.ts +1 -0
- package/dist/providers/claude/keychain-account.js +14 -0
- package/dist/providers/claude/language-model.d.ts +8 -0
- package/dist/providers/claude/language-model.js +109 -0
- package/dist/providers/claude/models.d.ts +9 -0
- package/dist/providers/claude/models.js +24 -0
- package/dist/providers/claude/prompt.d.ts +42 -0
- package/dist/providers/claude/prompt.js +134 -0
- package/dist/providers/claude/refresh.d.ts +19 -0
- package/dist/providers/claude/refresh.js +85 -0
- package/dist/providers/claude/sse-convert.d.ts +6 -0
- package/dist/providers/claude/sse-convert.js +74 -0
- package/dist/providers/claude/sse.d.ts +71 -0
- package/dist/providers/claude/sse.js +123 -0
- package/dist/providers/claude/transform.d.ts +32 -0
- package/dist/providers/claude/transform.js +52 -0
- package/dist/providers/claude/writeback.d.ts +18 -0
- package/dist/providers/claude/writeback.js +140 -0
- package/dist/providers/command-code/adapter.d.ts +7 -0
- package/dist/providers/command-code/adapter.js +37 -0
- package/dist/providers/command-code/auth.d.ts +5 -0
- package/dist/providers/command-code/auth.js +88 -0
- package/dist/providers/command-code/cli-version.d.ts +10 -0
- package/dist/providers/command-code/cli-version.js +36 -0
- package/dist/providers/command-code/emit-stream.d.ts +2 -0
- package/dist/providers/command-code/emit-stream.js +226 -0
- package/dist/providers/command-code/errors.d.ts +33 -0
- package/dist/providers/command-code/errors.js +105 -0
- package/dist/providers/command-code/language-model.d.ts +15 -0
- package/dist/providers/command-code/language-model.js +203 -0
- package/dist/providers/command-code/models.d.ts +3 -0
- package/dist/providers/command-code/models.js +18 -0
- package/dist/providers/command-code/record-stream.d.ts +1 -0
- package/dist/providers/command-code/record-stream.js +61 -0
- package/dist/providers/command-code/request-lifecycle.d.ts +8 -0
- package/dist/providers/command-code/request-lifecycle.js +33 -0
- package/dist/providers/command-code/request.d.ts +14 -0
- package/dist/providers/command-code/request.js +167 -0
- package/dist/providers/command-code/session.d.ts +5 -0
- package/dist/providers/command-code/session.js +9 -0
- package/dist/providers/cursor/adapter.d.ts +7 -0
- package/dist/providers/cursor/adapter.js +37 -0
- package/dist/providers/cursor/auth.d.ts +6 -0
- package/dist/providers/cursor/auth.js +56 -0
- package/dist/providers/cursor/blob-store.d.ts +26 -0
- package/dist/providers/cursor/blob-store.js +119 -0
- package/dist/providers/cursor/bridge-client.d.ts +33 -0
- package/dist/providers/cursor/bridge-client.js +200 -0
- package/dist/providers/cursor/bridge-event-sanitize.d.ts +3 -0
- package/dist/providers/cursor/bridge-event-sanitize.js +49 -0
- package/dist/providers/cursor/bridge-limits.d.ts +3 -0
- package/dist/providers/cursor/bridge-limits.js +10 -0
- package/dist/providers/cursor/bridge-process.d.ts +45 -0
- package/dist/providers/cursor/bridge-process.js +211 -0
- package/dist/providers/cursor/bridge-protocol.d.ts +68 -0
- package/dist/providers/cursor/bridge-protocol.js +49 -0
- package/dist/providers/cursor/bridge-serialize.d.ts +3 -0
- package/dist/providers/cursor/bridge-serialize.js +53 -0
- package/dist/providers/cursor/bridge-wire.d.ts +3 -0
- package/dist/providers/cursor/bridge-wire.js +163 -0
- package/dist/providers/cursor/checkpoint-store.d.ts +28 -0
- package/dist/providers/cursor/checkpoint-store.js +94 -0
- package/dist/providers/cursor/connect-frame-stream.d.ts +19 -0
- package/dist/providers/cursor/connect-frame-stream.js +160 -0
- package/dist/providers/cursor/connect-frame.d.ts +31 -0
- package/dist/providers/cursor/connect-frame.js +121 -0
- package/dist/providers/cursor/credentials.d.ts +5 -0
- package/dist/providers/cursor/credentials.js +22 -0
- package/dist/providers/cursor/direct-run-types.d.ts +33 -0
- package/dist/providers/cursor/direct-run-types.js +1 -0
- package/dist/providers/cursor/direct-run.d.ts +5 -0
- package/dist/providers/cursor/direct-run.js +213 -0
- package/dist/providers/cursor/direct-runtime.d.ts +23 -0
- package/dist/providers/cursor/direct-runtime.js +111 -0
- package/dist/providers/cursor/direct-stream.d.ts +28 -0
- package/dist/providers/cursor/direct-stream.js +190 -0
- package/dist/providers/cursor/exec-reply.d.ts +13 -0
- package/dist/providers/cursor/exec-reply.js +102 -0
- package/dist/providers/cursor/h2-bridge-response.d.ts +9 -0
- package/dist/providers/cursor/h2-bridge-response.js +51 -0
- package/dist/providers/cursor/h2-bridge-session.d.ts +24 -0
- package/dist/providers/cursor/h2-bridge-session.js +197 -0
- package/dist/providers/cursor/h2-bridge.d.ts +2 -0
- package/dist/providers/cursor/h2-bridge.js +12865 -0
- package/dist/providers/cursor/http2.d.ts +18 -0
- package/dist/providers/cursor/http2.js +144 -0
- package/dist/providers/cursor/interaction-reply.d.ts +6 -0
- package/dist/providers/cursor/interaction-reply.js +52 -0
- package/dist/providers/cursor/language-generate.d.ts +2 -0
- package/dist/providers/cursor/language-generate.js +35 -0
- package/dist/providers/cursor/language-model.d.ts +13 -0
- package/dist/providers/cursor/language-model.js +77 -0
- package/dist/providers/cursor/legacy-stream.d.ts +11 -0
- package/dist/providers/cursor/legacy-stream.js +115 -0
- package/dist/providers/cursor/mcp-tools.d.ts +7 -0
- package/dist/providers/cursor/mcp-tools.js +15 -0
- package/dist/providers/cursor/models.d.ts +14 -0
- package/dist/providers/cursor/models.js +116 -0
- package/dist/providers/cursor/ndjson.d.ts +3 -0
- package/dist/providers/cursor/ndjson.js +100 -0
- package/dist/providers/cursor/prompt.d.ts +4 -0
- package/dist/providers/cursor/prompt.js +142 -0
- package/dist/providers/cursor/proto/checkpoint.d.ts +35 -0
- package/dist/providers/cursor/proto/checkpoint.js +114 -0
- package/dist/providers/cursor/proto/context.d.ts +64 -0
- package/dist/providers/cursor/proto/context.js +178 -0
- package/dist/providers/cursor/proto/errors.d.ts +16 -0
- package/dist/providers/cursor/proto/errors.js +26 -0
- package/dist/providers/cursor/proto/exec-control.d.ts +20 -0
- package/dist/providers/cursor/proto/exec-control.js +54 -0
- package/dist/providers/cursor/proto/exec.d.ts +47 -0
- package/dist/providers/cursor/proto/exec.js +154 -0
- package/dist/providers/cursor/proto/fields.d.ts +22 -0
- package/dist/providers/cursor/proto/fields.js +97 -0
- package/dist/providers/cursor/proto/interaction-query.d.ts +15 -0
- package/dist/providers/cursor/proto/interaction-query.js +79 -0
- package/dist/providers/cursor/proto/interaction-tool-update.d.ts +10 -0
- package/dist/providers/cursor/proto/interaction-tool-update.js +58 -0
- package/dist/providers/cursor/proto/interaction-turn-ended.d.ts +6 -0
- package/dist/providers/cursor/proto/interaction-turn-ended.js +18 -0
- package/dist/providers/cursor/proto/interaction.d.ts +65 -0
- package/dist/providers/cursor/proto/interaction.js +185 -0
- package/dist/providers/cursor/proto/kv.d.ts +25 -0
- package/dist/providers/cursor/proto/kv.js +109 -0
- package/dist/providers/cursor/proto/mcp-result.d.ts +40 -0
- package/dist/providers/cursor/proto/mcp-result.js +150 -0
- package/dist/providers/cursor/proto/mcp.d.ts +19 -0
- package/dist/providers/cursor/proto/mcp.js +78 -0
- package/dist/providers/cursor/proto/model.d.ts +11 -0
- package/dist/providers/cursor/proto/model.js +36 -0
- package/dist/providers/cursor/proto/output-location.d.ts +7 -0
- package/dist/providers/cursor/proto/output-location.js +53 -0
- package/dist/providers/cursor/proto/prewarm.d.ts +16 -0
- package/dist/providers/cursor/proto/prewarm.js +68 -0
- package/dist/providers/cursor/proto/request-context.d.ts +16 -0
- package/dist/providers/cursor/proto/request-context.js +58 -0
- package/dist/providers/cursor/proto/request.d.ts +44 -0
- package/dist/providers/cursor/proto/request.js +111 -0
- package/dist/providers/cursor/proto/run-request.d.ts +19 -0
- package/dist/providers/cursor/proto/run-request.js +68 -0
- package/dist/providers/cursor/proto/server.d.ts +35 -0
- package/dist/providers/cursor/proto/server.js +93 -0
- package/dist/providers/cursor/proto/unknown-field.d.ts +1 -0
- package/dist/providers/cursor/proto/unknown-field.js +22 -0
- package/dist/providers/cursor/proto-value.d.ts +3 -0
- package/dist/providers/cursor/proto-value.js +170 -0
- package/dist/providers/cursor/proto-wire.d.ts +22 -0
- package/dist/providers/cursor/proto-wire.js +224 -0
- package/dist/providers/cursor/protocol-failure.d.ts +18 -0
- package/dist/providers/cursor/protocol-failure.js +45 -0
- package/dist/providers/cursor/recovery.d.ts +48 -0
- package/dist/providers/cursor/recovery.js +102 -0
- package/dist/providers/cursor/request-blob-ownership.d.ts +15 -0
- package/dist/providers/cursor/request-blob-ownership.js +39 -0
- package/dist/providers/cursor/request-build.d.ts +18 -0
- package/dist/providers/cursor/request-build.js +123 -0
- package/dist/providers/cursor/request-history.d.ts +32 -0
- package/dist/providers/cursor/request-history.js +163 -0
- package/dist/providers/cursor/request-input.d.ts +75 -0
- package/dist/providers/cursor/request-input.js +123 -0
- package/dist/providers/cursor/run-events.d.ts +15 -0
- package/dist/providers/cursor/run-events.js +43 -0
- package/dist/providers/cursor/run-session-expiry.d.ts +15 -0
- package/dist/providers/cursor/run-session-expiry.js +21 -0
- package/dist/providers/cursor/run-session.d.ts +50 -0
- package/dist/providers/cursor/run-session.js +205 -0
- package/dist/providers/cursor/run.d.ts +9 -0
- package/dist/providers/cursor/run.js +151 -0
- package/dist/providers/cursor/runner.d.ts +1 -0
- package/dist/providers/cursor/runner.js +55 -0
- package/dist/providers/cursor/server-dispatch-types.d.ts +83 -0
- package/dist/providers/cursor/server-dispatch-types.js +1 -0
- package/dist/providers/cursor/server-dispatch.d.ts +3 -0
- package/dist/providers/cursor/server-dispatch.js +178 -0
- package/dist/providers/cursor/session-state.d.ts +21 -0
- package/dist/providers/cursor/session-state.js +118 -0
- package/dist/providers/cursor/session.d.ts +1 -0
- package/dist/providers/cursor/session.js +26 -0
- package/dist/providers/cursor/settle-cleanup.d.ts +1 -0
- package/dist/providers/cursor/settle-cleanup.js +11 -0
- package/dist/providers/cursor/stream-adapter.d.ts +17 -0
- package/dist/providers/cursor/stream-adapter.js +99 -0
- package/dist/providers/cursor/tool-continuation.d.ts +14 -0
- package/dist/providers/cursor/tool-continuation.js +134 -0
- package/dist/providers/cursor/tool-stream.d.ts +2 -0
- package/dist/providers/cursor/tool-stream.js +220 -0
- package/dist/providers/cursor/usage.d.ts +3 -0
- package/dist/providers/cursor/usage.js +35 -0
- package/dist/providers/ollama/adapter.d.ts +8 -0
- package/dist/providers/ollama/adapter.js +65 -0
- package/dist/providers/ollama/catalog-state.d.ts +17 -0
- package/dist/providers/ollama/catalog-state.js +40 -0
- package/dist/providers/ollama/cloud-catalog.d.ts +3 -0
- package/dist/providers/ollama/cloud-catalog.js +82 -0
- package/dist/providers/ollama/errors.d.ts +14 -0
- package/dist/providers/ollama/errors.js +19 -0
- package/dist/providers/ollama/generate.d.ts +2 -0
- package/dist/providers/ollama/generate.js +49 -0
- package/dist/providers/ollama/html-links.d.ts +1 -0
- package/dist/providers/ollama/html-links.js +30 -0
- package/dist/providers/ollama/http.d.ts +12 -0
- package/dist/providers/ollama/http.js +67 -0
- package/dist/providers/ollama/index.d.ts +8 -0
- package/dist/providers/ollama/index.js +8 -0
- package/dist/providers/ollama/language-model.d.ts +11 -0
- package/dist/providers/ollama/language-model.js +62 -0
- package/dist/providers/ollama/local-catalog.d.ts +3 -0
- package/dist/providers/ollama/local-catalog.js +38 -0
- package/dist/providers/ollama/ndjson.d.ts +3 -0
- package/dist/providers/ollama/ndjson.js +51 -0
- package/dist/providers/ollama/prompt.d.ts +8 -0
- package/dist/providers/ollama/prompt.js +141 -0
- package/dist/providers/ollama/protocol.d.ts +56 -0
- package/dist/providers/ollama/protocol.js +26 -0
- package/dist/providers/ollama/runtime.d.ts +11 -0
- package/dist/providers/ollama/runtime.js +128 -0
- package/dist/providers/ollama/stream.d.ts +8 -0
- package/dist/providers/ollama/stream.js +110 -0
- package/dist/sdk/command-code.d.ts +5 -0
- package/dist/sdk/command-code.js +6 -0
- package/dist/sdk/cursor.d.ts +5 -0
- package/dist/sdk/cursor.js +6 -0
- package/dist/sdk/ollama.d.ts +5 -0
- package/dist/sdk/ollama.js +6 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.js +94 -0
- package/docs/README.ko.md +189 -0
- package/package.json +75 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { OperationCancelledError } from "../../core/errors";
|
|
2
|
+
import { OllamaCatalogError } from "./errors";
|
|
3
|
+
const MAX_BODY_BYTES = 256 * 1024;
|
|
4
|
+
export const productionOllamaFetch = (url, init) => fetch(url, init);
|
|
5
|
+
function failureKind(status) {
|
|
6
|
+
return status >= 500 ? "transport-error" : "invalid-data";
|
|
7
|
+
}
|
|
8
|
+
async function readBoundedBody(response, operation) {
|
|
9
|
+
if (response.body === null)
|
|
10
|
+
return new Uint8Array();
|
|
11
|
+
const reader = response.body.getReader();
|
|
12
|
+
const chunks = [];
|
|
13
|
+
let length = 0;
|
|
14
|
+
while (true) {
|
|
15
|
+
const result = await reader.read();
|
|
16
|
+
if (result.done)
|
|
17
|
+
break;
|
|
18
|
+
length += result.value.byteLength;
|
|
19
|
+
if (length > MAX_BODY_BYTES) {
|
|
20
|
+
await reader.cancel();
|
|
21
|
+
throw new OllamaCatalogError(operation, "invalid-data");
|
|
22
|
+
}
|
|
23
|
+
chunks.push(result.value);
|
|
24
|
+
}
|
|
25
|
+
const body = new Uint8Array(length);
|
|
26
|
+
let offset = 0;
|
|
27
|
+
for (const chunk of chunks) {
|
|
28
|
+
body.set(chunk, offset);
|
|
29
|
+
offset += chunk.byteLength;
|
|
30
|
+
}
|
|
31
|
+
return body;
|
|
32
|
+
}
|
|
33
|
+
export async function requestOllamaCatalog(request) {
|
|
34
|
+
if (request.signal.aborted)
|
|
35
|
+
throw new OperationCancelledError(request.operation);
|
|
36
|
+
let response;
|
|
37
|
+
try {
|
|
38
|
+
response = await request.fetch(request.url, {
|
|
39
|
+
method: "GET",
|
|
40
|
+
headers: { accept: request.accept },
|
|
41
|
+
signal: request.signal,
|
|
42
|
+
redirect: "error",
|
|
43
|
+
credentials: "omit",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
if (request.signal.aborted)
|
|
48
|
+
throw new OperationCancelledError(request.operation);
|
|
49
|
+
throw new OllamaCatalogError(request.operation, "transport-error");
|
|
50
|
+
}
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new OllamaCatalogError(request.operation, failureKind(response.status));
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedBody(response, request.operation));
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (request.signal.aborted)
|
|
59
|
+
throw new OperationCancelledError(request.operation);
|
|
60
|
+
if (error instanceof OllamaCatalogError)
|
|
61
|
+
throw error;
|
|
62
|
+
if (error instanceof TypeError || error instanceof DOMException) {
|
|
63
|
+
throw new OllamaCatalogError(request.operation, "invalid-data");
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createOllamaAdapter, type OllamaAdapterOptions } from "./adapter";
|
|
2
|
+
export { createOllamaCatalogState, type OllamaCatalogLease, type OllamaCatalogState, type OllamaCatalogStateOptions, } from "./catalog-state";
|
|
3
|
+
export { discoverOllamaCloudModels } from "./cloud-catalog";
|
|
4
|
+
export { OllamaCatalogError, type OllamaCatalogErrorKind, OllamaGenerationError, type OllamaGenerationOperation, } from "./errors";
|
|
5
|
+
export { type OllamaFetch, productionOllamaFetch } from "./http";
|
|
6
|
+
export { createOllamaLanguageModel, type OllamaLanguageModelOptions, } from "./language-model";
|
|
7
|
+
export { listLocalOllamaModels } from "./local-catalog";
|
|
8
|
+
export { createOllamaRuntime, type OllamaRuntime, type OllamaRuntimeOptions } from "./runtime";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createOllamaAdapter } from "./adapter";
|
|
2
|
+
export { createOllamaCatalogState, } from "./catalog-state";
|
|
3
|
+
export { discoverOllamaCloudModels } from "./cloud-catalog";
|
|
4
|
+
export { OllamaCatalogError, OllamaGenerationError, } from "./errors";
|
|
5
|
+
export { productionOllamaFetch } from "./http";
|
|
6
|
+
export { createOllamaLanguageModel, } from "./language-model";
|
|
7
|
+
export { listLocalOllamaModels } from "./local-catalog";
|
|
8
|
+
export { createOllamaRuntime } from "./runtime";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LanguageModelV3 } from "@ai-sdk/provider";
|
|
2
|
+
import type { OllamaCatalogState } from "./catalog-state";
|
|
3
|
+
import type { OllamaFetch } from "./http";
|
|
4
|
+
import { type OllamaRuntime } from "./runtime";
|
|
5
|
+
export type OllamaLanguageModelOptions = {
|
|
6
|
+
readonly modelId: string;
|
|
7
|
+
readonly runtime?: OllamaRuntime;
|
|
8
|
+
readonly catalog?: OllamaCatalogState;
|
|
9
|
+
readonly fetch?: OllamaFetch;
|
|
10
|
+
};
|
|
11
|
+
export declare function createOllamaLanguageModel(options: OllamaLanguageModelOptions): LanguageModelV3;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { OperationCancelledError } from "../../core/errors";
|
|
2
|
+
import { generateFromOllamaStream } from "./generate";
|
|
3
|
+
import { buildOllamaCall } from "./prompt";
|
|
4
|
+
import { createOllamaRuntime } from "./runtime";
|
|
5
|
+
import { createOllamaChatStream } from "./stream";
|
|
6
|
+
function runtimeFromOptions(options) {
|
|
7
|
+
if (options.runtime !== undefined)
|
|
8
|
+
return options.runtime;
|
|
9
|
+
if (options.catalog === undefined)
|
|
10
|
+
throw new TypeError("Ollama catalog state is required");
|
|
11
|
+
return createOllamaRuntime({
|
|
12
|
+
catalog: options.catalog,
|
|
13
|
+
...(options.fetch === undefined ? {} : { fetch: options.fetch }),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function createOllamaLanguageModel(options) {
|
|
17
|
+
const runtime = runtimeFromOptions(options);
|
|
18
|
+
const doStream = async (call) => {
|
|
19
|
+
const built = buildOllamaCall(options.modelId, call);
|
|
20
|
+
if (call.abortSignal?.aborted === true)
|
|
21
|
+
throw new OperationCancelledError("ollama-chat");
|
|
22
|
+
const lifecycle = new AbortController();
|
|
23
|
+
let finalized = false;
|
|
24
|
+
const finalize = () => {
|
|
25
|
+
if (finalized)
|
|
26
|
+
return;
|
|
27
|
+
finalized = true;
|
|
28
|
+
call.abortSignal?.removeEventListener("abort", cancel);
|
|
29
|
+
};
|
|
30
|
+
const cancel = () => {
|
|
31
|
+
if (!lifecycle.signal.aborted) {
|
|
32
|
+
lifecycle.abort(new OperationCancelledError("ollama-chat"));
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
call.abortSignal?.addEventListener("abort", cancel, { once: true });
|
|
36
|
+
try {
|
|
37
|
+
const response = await runtime.openChat(built.request, lifecycle.signal);
|
|
38
|
+
return {
|
|
39
|
+
stream: createOllamaChatStream({
|
|
40
|
+
response,
|
|
41
|
+
warnings: built.warnings,
|
|
42
|
+
includeRawChunks: call.includeRawChunks === true,
|
|
43
|
+
cancel,
|
|
44
|
+
finalize,
|
|
45
|
+
}),
|
|
46
|
+
request: { body: built.request },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
finalize();
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
specificationVersion: "v3",
|
|
56
|
+
provider: "ollama",
|
|
57
|
+
modelId: options.modelId,
|
|
58
|
+
supportedUrls: {},
|
|
59
|
+
doStream,
|
|
60
|
+
doGenerate: async (call) => generateFromOllamaStream((await doStream(call)).stream),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { parseAdapterModel } from "../../core/models";
|
|
3
|
+
import { OllamaCatalogError } from "./errors";
|
|
4
|
+
import { requestOllamaCatalog } from "./http";
|
|
5
|
+
const LOCAL_TAGS_URL = "http://localhost:11434/api/tags";
|
|
6
|
+
const LocalModelSchema = z
|
|
7
|
+
.object({ model: z.string().optional(), name: z.string().optional() })
|
|
8
|
+
.superRefine((value, context) => {
|
|
9
|
+
const model = value.model?.length === 0 ? undefined : value.model;
|
|
10
|
+
const name = value.name?.length === 0 ? undefined : value.name;
|
|
11
|
+
if (model === undefined && name === undefined) {
|
|
12
|
+
context.addIssue({ code: "custom", message: "missing local model ID" });
|
|
13
|
+
}
|
|
14
|
+
if (model !== undefined && name !== undefined && model !== name) {
|
|
15
|
+
context.addIssue({ code: "custom", message: "conflicting local model IDs" });
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
.transform(({ model, name }) => (model?.length === 0 ? undefined : model) ?? name ?? "");
|
|
19
|
+
const LocalTagsSchema = z.object({ models: z.array(LocalModelSchema) }).readonly();
|
|
20
|
+
export async function listLocalOllamaModels(fetch, signal) {
|
|
21
|
+
const text = await requestOllamaCatalog({
|
|
22
|
+
url: LOCAL_TAGS_URL,
|
|
23
|
+
accept: "application/json",
|
|
24
|
+
operation: "local-tags",
|
|
25
|
+
fetch,
|
|
26
|
+
signal,
|
|
27
|
+
});
|
|
28
|
+
try {
|
|
29
|
+
const value = JSON.parse(text);
|
|
30
|
+
return LocalTagsSchema.parse(value).models.map((id) => parseAdapterModel({ id }));
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error instanceof SyntaxError || error instanceof z.ZodError) {
|
|
34
|
+
throw new OllamaCatalogError("local-tags", "invalid-data");
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { OllamaGenerationError } from "./errors";
|
|
2
|
+
const MAX_LINE_BYTES = 1024 * 1024;
|
|
3
|
+
function appendLine(buffered, chunk, operation) {
|
|
4
|
+
if (buffered.byteLength + chunk.byteLength > MAX_LINE_BYTES) {
|
|
5
|
+
throw new OllamaGenerationError(operation);
|
|
6
|
+
}
|
|
7
|
+
const joined = new Uint8Array(buffered.byteLength + chunk.byteLength);
|
|
8
|
+
joined.set(buffered);
|
|
9
|
+
joined.set(chunk, buffered.byteLength);
|
|
10
|
+
return joined;
|
|
11
|
+
}
|
|
12
|
+
export async function* parseOllamaNdjson(response, schema, operation) {
|
|
13
|
+
if (response.body === null)
|
|
14
|
+
throw new OllamaGenerationError(operation);
|
|
15
|
+
const reader = response.body.getReader();
|
|
16
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
17
|
+
let buffered = new Uint8Array();
|
|
18
|
+
try {
|
|
19
|
+
for (;;) {
|
|
20
|
+
const result = await reader.read();
|
|
21
|
+
if (result.done)
|
|
22
|
+
break;
|
|
23
|
+
let start = 0;
|
|
24
|
+
for (let index = 0; index < result.value.byteLength; index += 1) {
|
|
25
|
+
if (result.value[index] !== 0x0a)
|
|
26
|
+
continue;
|
|
27
|
+
const lineBytes = appendLine(buffered, result.value.subarray(start, index), operation);
|
|
28
|
+
buffered = new Uint8Array();
|
|
29
|
+
start = index + 1;
|
|
30
|
+
const line = decoder.decode(lineBytes);
|
|
31
|
+
if (line.trim().length === 0)
|
|
32
|
+
continue;
|
|
33
|
+
yield schema.parse(JSON.parse(line));
|
|
34
|
+
}
|
|
35
|
+
buffered = appendLine(buffered, result.value.subarray(start), operation);
|
|
36
|
+
}
|
|
37
|
+
if (buffered.byteLength > 0) {
|
|
38
|
+
const line = decoder.decode(buffered);
|
|
39
|
+
if (line.trim().length > 0)
|
|
40
|
+
yield schema.parse(JSON.parse(line));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error instanceof OllamaGenerationError)
|
|
45
|
+
throw error;
|
|
46
|
+
throw new OllamaGenerationError(operation);
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
reader.releaseLock();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LanguageModelV3CallOptions, SharedV3Warning } from "@ai-sdk/provider";
|
|
2
|
+
import type { OllamaChatRequest } from "./protocol";
|
|
3
|
+
type BuiltOllamaCall = {
|
|
4
|
+
readonly request: OllamaChatRequest;
|
|
5
|
+
readonly warnings: SharedV3Warning[];
|
|
6
|
+
};
|
|
7
|
+
export declare function buildOllamaCall(modelId: string, call: LanguageModelV3CallOptions): BuiltOllamaCall;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { OllamaGenerationError } from "./errors";
|
|
2
|
+
function unsupported() {
|
|
3
|
+
throw new OllamaGenerationError("prompt");
|
|
4
|
+
}
|
|
5
|
+
function resultText(output) {
|
|
6
|
+
switch (output.type) {
|
|
7
|
+
case "text":
|
|
8
|
+
case "error-text":
|
|
9
|
+
return output.value;
|
|
10
|
+
case "json":
|
|
11
|
+
case "error-json":
|
|
12
|
+
return JSON.stringify(output.value);
|
|
13
|
+
case "execution-denied":
|
|
14
|
+
return output.reason ?? "Tool execution denied";
|
|
15
|
+
case "content":
|
|
16
|
+
return unsupported();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function messagesFromCall(call) {
|
|
20
|
+
const messages = [];
|
|
21
|
+
const pendingCalls = new Map();
|
|
22
|
+
for (const message of call.prompt) {
|
|
23
|
+
if (pendingCalls.size > 0 && message.role !== "tool")
|
|
24
|
+
unsupported();
|
|
25
|
+
switch (message.role) {
|
|
26
|
+
case "system":
|
|
27
|
+
messages.push({ role: "system", content: message.content });
|
|
28
|
+
break;
|
|
29
|
+
case "user":
|
|
30
|
+
messages.push({
|
|
31
|
+
role: "user",
|
|
32
|
+
content: message.content
|
|
33
|
+
.map((part) => (part.type === "text" ? part.text : unsupported()))
|
|
34
|
+
.join(""),
|
|
35
|
+
});
|
|
36
|
+
break;
|
|
37
|
+
case "assistant": {
|
|
38
|
+
const text = [];
|
|
39
|
+
const thinking = [];
|
|
40
|
+
const calls = [];
|
|
41
|
+
for (const part of message.content) {
|
|
42
|
+
switch (part.type) {
|
|
43
|
+
case "text":
|
|
44
|
+
text.push(part.text);
|
|
45
|
+
break;
|
|
46
|
+
case "reasoning":
|
|
47
|
+
thinking.push(part.text);
|
|
48
|
+
break;
|
|
49
|
+
case "tool-call":
|
|
50
|
+
if (part.providerExecuted === true ||
|
|
51
|
+
part.toolCallId.length === 0 ||
|
|
52
|
+
part.toolName.length === 0 ||
|
|
53
|
+
pendingCalls.has(part.toolCallId) ||
|
|
54
|
+
typeof part.input !== "object" ||
|
|
55
|
+
part.input === null ||
|
|
56
|
+
Array.isArray(part.input))
|
|
57
|
+
unsupported();
|
|
58
|
+
calls.push({
|
|
59
|
+
function: {
|
|
60
|
+
name: part.toolName,
|
|
61
|
+
arguments: Object.fromEntries(Object.entries(part.input)),
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
pendingCalls.set(part.toolCallId, part.toolName);
|
|
65
|
+
break;
|
|
66
|
+
case "tool-result":
|
|
67
|
+
return unsupported();
|
|
68
|
+
case "file":
|
|
69
|
+
return unsupported();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
messages.push({
|
|
73
|
+
role: "assistant",
|
|
74
|
+
content: text.join(""),
|
|
75
|
+
...(thinking.length === 0 ? {} : { thinking: thinking.join("") }),
|
|
76
|
+
...(calls.length === 0 ? {} : { tool_calls: calls }),
|
|
77
|
+
});
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case "tool":
|
|
81
|
+
for (const part of message.content) {
|
|
82
|
+
if (part.type !== "tool-result")
|
|
83
|
+
unsupported();
|
|
84
|
+
if (pendingCalls.get(part.toolCallId) !== part.toolName)
|
|
85
|
+
unsupported();
|
|
86
|
+
messages.push({
|
|
87
|
+
role: "tool",
|
|
88
|
+
content: resultText(part.output),
|
|
89
|
+
tool_name: part.toolName,
|
|
90
|
+
});
|
|
91
|
+
pendingCalls.delete(part.toolCallId);
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return messages;
|
|
97
|
+
}
|
|
98
|
+
export function buildOllamaCall(modelId, call) {
|
|
99
|
+
const warnings = [];
|
|
100
|
+
if (call.presencePenalty !== undefined)
|
|
101
|
+
warnings.push({ type: "unsupported", feature: "presencePenalty" });
|
|
102
|
+
if (call.frequencyPenalty !== undefined)
|
|
103
|
+
warnings.push({ type: "unsupported", feature: "frequencyPenalty" });
|
|
104
|
+
if (call.toolChoice !== undefined)
|
|
105
|
+
warnings.push({ type: "unsupported", feature: "toolChoice" });
|
|
106
|
+
if (call.headers !== undefined)
|
|
107
|
+
warnings.push({ type: "unsupported", feature: "headers" });
|
|
108
|
+
const tools = call.tools?.map((tool) => {
|
|
109
|
+
if (tool.type !== "function")
|
|
110
|
+
return unsupported();
|
|
111
|
+
return {
|
|
112
|
+
type: "function",
|
|
113
|
+
function: {
|
|
114
|
+
name: tool.name,
|
|
115
|
+
description: tool.description ?? "",
|
|
116
|
+
parameters: tool.inputSchema,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
const requestOptions = {
|
|
121
|
+
...(call.maxOutputTokens === undefined ? {} : { num_predict: call.maxOutputTokens }),
|
|
122
|
+
...(call.temperature === undefined ? {} : { temperature: call.temperature }),
|
|
123
|
+
...(call.topP === undefined ? {} : { top_p: call.topP }),
|
|
124
|
+
...(call.topK === undefined ? {} : { top_k: call.topK }),
|
|
125
|
+
...(call.seed === undefined ? {} : { seed: call.seed }),
|
|
126
|
+
...(call.stopSequences === undefined ? {} : { stop: call.stopSequences }),
|
|
127
|
+
};
|
|
128
|
+
return {
|
|
129
|
+
request: {
|
|
130
|
+
model: modelId,
|
|
131
|
+
stream: true,
|
|
132
|
+
messages: messagesFromCall(call),
|
|
133
|
+
...(tools === undefined ? {} : { tools }),
|
|
134
|
+
...(call.responseFormat?.type === "json"
|
|
135
|
+
? { format: call.responseFormat.schema ?? "json" }
|
|
136
|
+
: {}),
|
|
137
|
+
...(Object.keys(requestOptions).length === 0 ? {} : { options: requestOptions }),
|
|
138
|
+
},
|
|
139
|
+
warnings,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
type OllamaJson = boolean | null | number | string | readonly OllamaJson[] | {
|
|
3
|
+
readonly [key: string]: OllamaJson;
|
|
4
|
+
};
|
|
5
|
+
export type OllamaPullChunk = {
|
|
6
|
+
readonly status?: string | undefined;
|
|
7
|
+
readonly error?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
export declare const OllamaPullChunkSchema: z.ZodType<OllamaPullChunk>;
|
|
10
|
+
type OllamaToolCall = {
|
|
11
|
+
readonly function: {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly arguments: Record<string, OllamaJson>;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export type OllamaChatChunk = {
|
|
17
|
+
readonly message: {
|
|
18
|
+
readonly role?: string | undefined;
|
|
19
|
+
readonly content: string;
|
|
20
|
+
readonly thinking?: string | undefined;
|
|
21
|
+
readonly tool_calls?: readonly OllamaToolCall[] | undefined;
|
|
22
|
+
};
|
|
23
|
+
readonly done: boolean;
|
|
24
|
+
readonly done_reason?: string | undefined;
|
|
25
|
+
readonly prompt_eval_count?: number | undefined;
|
|
26
|
+
readonly eval_count?: number | undefined;
|
|
27
|
+
};
|
|
28
|
+
export declare const OllamaChatChunkSchema: z.ZodType<OllamaChatChunk>;
|
|
29
|
+
export type OllamaMessage = {
|
|
30
|
+
readonly role: "assistant" | "system" | "tool" | "user";
|
|
31
|
+
readonly content: string;
|
|
32
|
+
readonly thinking?: string;
|
|
33
|
+
readonly tool_name?: string;
|
|
34
|
+
readonly tool_calls?: readonly {
|
|
35
|
+
readonly function: {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly arguments: Readonly<Record<string, unknown>>;
|
|
38
|
+
};
|
|
39
|
+
}[];
|
|
40
|
+
};
|
|
41
|
+
export type OllamaChatRequest = {
|
|
42
|
+
readonly model: string;
|
|
43
|
+
readonly stream: true;
|
|
44
|
+
readonly messages: readonly OllamaMessage[];
|
|
45
|
+
readonly tools?: readonly {
|
|
46
|
+
readonly type: "function";
|
|
47
|
+
readonly function: {
|
|
48
|
+
readonly name: string;
|
|
49
|
+
readonly description: string;
|
|
50
|
+
readonly parameters: object;
|
|
51
|
+
};
|
|
52
|
+
}[];
|
|
53
|
+
readonly format?: object | "json";
|
|
54
|
+
readonly options?: Readonly<Record<string, number | readonly string[]>>;
|
|
55
|
+
};
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const JsonObjectSchema = z.record(z.string(), z.json());
|
|
3
|
+
export const OllamaPullChunkSchema = z
|
|
4
|
+
.object({ status: z.string().optional(), error: z.string().optional() })
|
|
5
|
+
.readonly();
|
|
6
|
+
const OllamaToolCallSchema = z
|
|
7
|
+
.object({
|
|
8
|
+
function: z.object({ name: z.string().min(1), arguments: JsonObjectSchema }),
|
|
9
|
+
})
|
|
10
|
+
.readonly();
|
|
11
|
+
export const OllamaChatChunkSchema = z
|
|
12
|
+
.object({
|
|
13
|
+
message: z
|
|
14
|
+
.object({
|
|
15
|
+
role: z.string().optional(),
|
|
16
|
+
content: z.string().default(""),
|
|
17
|
+
thinking: z.string().optional(),
|
|
18
|
+
tool_calls: z.array(OllamaToolCallSchema).optional(),
|
|
19
|
+
})
|
|
20
|
+
.readonly(),
|
|
21
|
+
done: z.boolean(),
|
|
22
|
+
done_reason: z.string().optional(),
|
|
23
|
+
prompt_eval_count: z.number().int().nonnegative().optional(),
|
|
24
|
+
eval_count: z.number().int().nonnegative().optional(),
|
|
25
|
+
})
|
|
26
|
+
.readonly();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { OllamaCatalogState } from "./catalog-state";
|
|
2
|
+
import { type OllamaFetch } from "./http";
|
|
3
|
+
import { type OllamaChatRequest } from "./protocol";
|
|
4
|
+
export type OllamaRuntimeOptions = {
|
|
5
|
+
readonly catalog: OllamaCatalogState;
|
|
6
|
+
readonly fetch?: OllamaFetch;
|
|
7
|
+
};
|
|
8
|
+
export interface OllamaRuntime {
|
|
9
|
+
openChat(request: OllamaChatRequest, signal: AbortSignal): Promise<Response>;
|
|
10
|
+
}
|
|
11
|
+
export declare function createOllamaRuntime(options: OllamaRuntimeOptions): OllamaRuntime;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { OperationCancelledError } from "../../core/errors";
|
|
2
|
+
import { OllamaGenerationError } from "./errors";
|
|
3
|
+
import { productionOllamaFetch } from "./http";
|
|
4
|
+
import { listLocalOllamaModels } from "./local-catalog";
|
|
5
|
+
import { parseOllamaNdjson } from "./ndjson";
|
|
6
|
+
import { OllamaPullChunkSchema } from "./protocol";
|
|
7
|
+
const PULL_URL = "http://localhost:11434/api/pull";
|
|
8
|
+
const CHAT_URL = "http://localhost:11434/api/chat";
|
|
9
|
+
const JSON_HEADERS = {
|
|
10
|
+
accept: "application/x-ndjson",
|
|
11
|
+
"content-type": "application/json",
|
|
12
|
+
};
|
|
13
|
+
function cancelled(operation) {
|
|
14
|
+
return new OperationCancelledError(`ollama-${operation}`);
|
|
15
|
+
}
|
|
16
|
+
async function post(fetch, url, body, signal, operation) {
|
|
17
|
+
if (signal.aborted)
|
|
18
|
+
throw cancelled(operation);
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(url, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: JSON_HEADERS,
|
|
23
|
+
body: JSON.stringify(body),
|
|
24
|
+
signal,
|
|
25
|
+
credentials: "omit",
|
|
26
|
+
redirect: "error",
|
|
27
|
+
});
|
|
28
|
+
if (signal.aborted)
|
|
29
|
+
throw cancelled(operation);
|
|
30
|
+
if (!response.ok)
|
|
31
|
+
throw new OllamaGenerationError(operation);
|
|
32
|
+
return response;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (signal.aborted)
|
|
36
|
+
throw cancelled(operation);
|
|
37
|
+
if (error instanceof OperationCancelledError)
|
|
38
|
+
throw error;
|
|
39
|
+
if (error instanceof OllamaGenerationError)
|
|
40
|
+
throw error;
|
|
41
|
+
throw new OllamaGenerationError(operation);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function createOllamaRuntime(options) {
|
|
45
|
+
const fetch = options.fetch ?? productionOllamaFetch;
|
|
46
|
+
const pulls = new Map();
|
|
47
|
+
const pull = (modelId) => {
|
|
48
|
+
const existing = pulls.get(modelId);
|
|
49
|
+
if (existing !== undefined)
|
|
50
|
+
return existing;
|
|
51
|
+
const controller = new AbortController();
|
|
52
|
+
const promise = (async () => {
|
|
53
|
+
const response = await post(fetch, PULL_URL, { model: modelId, stream: true }, controller.signal, "pull");
|
|
54
|
+
let succeeded = false;
|
|
55
|
+
for await (const chunk of parseOllamaNdjson(response, OllamaPullChunkSchema, "pull-response")) {
|
|
56
|
+
if (chunk.error !== undefined)
|
|
57
|
+
throw new OllamaGenerationError("pull-response");
|
|
58
|
+
if (chunk.status === "success")
|
|
59
|
+
succeeded = true;
|
|
60
|
+
}
|
|
61
|
+
if (!succeeded)
|
|
62
|
+
throw new OllamaGenerationError("pull-response");
|
|
63
|
+
})();
|
|
64
|
+
const flight = { controller, promise, waiters: 0 };
|
|
65
|
+
pulls.set(modelId, flight);
|
|
66
|
+
const settle = () => {
|
|
67
|
+
if (pulls.get(modelId) === flight)
|
|
68
|
+
pulls.delete(modelId);
|
|
69
|
+
};
|
|
70
|
+
promise.then(settle, settle);
|
|
71
|
+
return flight;
|
|
72
|
+
};
|
|
73
|
+
const waitForPull = (modelId, flight, signal) => {
|
|
74
|
+
flight.waiters += 1;
|
|
75
|
+
const deferred = Promise.withResolvers();
|
|
76
|
+
let settled = false;
|
|
77
|
+
const release = () => {
|
|
78
|
+
if (settled)
|
|
79
|
+
return;
|
|
80
|
+
settled = true;
|
|
81
|
+
signal.removeEventListener("abort", onAbort);
|
|
82
|
+
flight.waiters -= 1;
|
|
83
|
+
if (flight.waiters === 0 && pulls.get(modelId) === flight) {
|
|
84
|
+
pulls.delete(modelId);
|
|
85
|
+
flight.controller.abort(cancelled("pull"));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const onAbort = () => {
|
|
89
|
+
release();
|
|
90
|
+
deferred.reject(cancelled("pull-wait"));
|
|
91
|
+
};
|
|
92
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
93
|
+
if (signal.aborted)
|
|
94
|
+
onAbort();
|
|
95
|
+
flight.promise.then(() => {
|
|
96
|
+
if (settled)
|
|
97
|
+
return;
|
|
98
|
+
release();
|
|
99
|
+
deferred.resolve();
|
|
100
|
+
}, (error) => {
|
|
101
|
+
if (settled)
|
|
102
|
+
return;
|
|
103
|
+
release();
|
|
104
|
+
deferred.reject(error);
|
|
105
|
+
});
|
|
106
|
+
return deferred.promise;
|
|
107
|
+
};
|
|
108
|
+
return {
|
|
109
|
+
openChat: async (request, signal) => {
|
|
110
|
+
let local;
|
|
111
|
+
try {
|
|
112
|
+
local = await listLocalOllamaModels(fetch, signal);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error instanceof OperationCancelledError)
|
|
116
|
+
throw error;
|
|
117
|
+
throw new OllamaGenerationError("tags");
|
|
118
|
+
}
|
|
119
|
+
if (!local.some(({ id }) => id === request.model)) {
|
|
120
|
+
if (!options.catalog.authorizesCloudPull(request.model)) {
|
|
121
|
+
throw new OllamaGenerationError("model-unavailable");
|
|
122
|
+
}
|
|
123
|
+
await waitForPull(request.model, pull(request.model), signal);
|
|
124
|
+
}
|
|
125
|
+
return post(fetch, CHAT_URL, request, signal, "chat");
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LanguageModelV3StreamPart, SharedV3Warning } from "@ai-sdk/provider";
|
|
2
|
+
export declare function createOllamaChatStream(options: {
|
|
3
|
+
readonly response: Response;
|
|
4
|
+
readonly warnings: SharedV3Warning[];
|
|
5
|
+
readonly includeRawChunks: boolean;
|
|
6
|
+
readonly cancel: () => void;
|
|
7
|
+
readonly finalize: () => void;
|
|
8
|
+
}): ReadableStream<LanguageModelV3StreamPart>;
|