dsh-subscriptions 0.1.5 → 0.2.2
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 +212 -154
- package/lib/auth/claude-code-creds.js +31 -9
- package/lib/auth/device-flow.js +16 -9
- package/lib/auth/oauth-flow.js +13 -10
- package/lib/auth/rpc.d.ts +73 -2
- package/lib/auth/rpc.js +124 -23
- package/lib/auth/store.js +80 -31
- package/lib/client/CursorCard.d.ts +1 -1
- package/lib/client/CursorCard.js +50 -16
- package/lib/client/ExternalUsageCards.d.ts +1 -1
- package/lib/client/ExternalUsageCards.js +37 -16
- package/lib/client/ImageGallery.d.ts +2 -2
- package/lib/client/ImageGallery.js +92 -33
- package/lib/client/ImageGenerateToolview.js +50 -14
- package/lib/client/OllamaCard.d.ts +13 -0
- package/lib/client/OllamaCard.js +94 -0
- package/lib/client/OllamaSettingsManager.d.ts +24 -0
- package/lib/client/OllamaSettingsManager.js +329 -0
- package/lib/client/ProviderAccountManager.d.ts +1 -1
- package/lib/client/ProviderAccountManager.js +164 -49
- package/lib/client/ProviderModelEditor.js +109 -26
- package/lib/client/SpeedSelect.d.ts +62 -14
- package/lib/client/SpeedSelect.js +257 -46
- package/lib/client/SubscriptionUsageBadge.d.ts +5 -11
- package/lib/client/SubscriptionUsageBadge.js +301 -112
- package/lib/client/SubscriptionsSection.d.ts +2 -0
- package/lib/client/SubscriptionsSection.js +259 -85
- package/lib/client/UsageBadgeDisplaySetting.js +35 -12
- package/lib/client/UsageMeter.d.ts +1 -1
- package/lib/client/UsageMeter.js +69 -27
- package/lib/client/VideoGenerateToolview.js +69 -17
- package/lib/client/account-preferences.d.ts +8 -0
- package/lib/client/account-preferences.js +20 -5
- package/lib/client/host-contract.d.ts +11 -2
- package/lib/client/host-contract.js +20 -3
- package/lib/client/index.d.ts +5 -5
- package/lib/client/index.js +34 -12
- package/lib/client/locales.d.ts +78 -0
- package/lib/client/locales.js +121 -34
- package/lib/client/ollama-draft.d.ts +229 -0
- package/lib/client/ollama-draft.js +255 -0
- package/lib/client/reset-action.js +6 -4
- package/lib/client/reset-credits-view.d.ts +1 -1
- package/lib/client/reset-credits-view.js +66 -17
- package/lib/client/subscription-card-styles.js +94 -24
- package/lib/client/usage-color-preferences.js +4 -2
- package/lib/client/usage-pace.d.ts +7 -0
- package/lib/client/usage-pace.js +43 -10
- package/lib/client.js +1647 -266
- package/lib/client.js.map +1 -1
- package/lib/http.js +1 -1
- package/lib/index.d.ts +28 -3
- package/lib/index.js +9329 -8217
- package/lib/model-defaults.js +4 -2
- package/lib/provider-settings.d.ts +14 -1
- package/lib/provider-settings.js +64 -20
- package/lib/providers/account-preferences.js +51 -22
- package/lib/providers/accounts.js +15 -9
- package/lib/providers/antigravity-oauth-client.js +2 -2
- package/lib/providers/antigravity.js +141 -68
- package/lib/providers/catalog-store.js +120 -41
- package/lib/providers/claude-cli-version.js +3 -3
- package/lib/providers/claude.d.ts +23 -3
- package/lib/providers/claude.js +167 -92
- package/lib/providers/codex-client-version.js +3 -3
- package/lib/providers/codex-search.js +40 -13
- package/lib/providers/codex.js +196 -112
- package/lib/providers/common.d.ts +14 -0
- package/lib/providers/common.js +118 -38
- package/lib/providers/copilot.js +143 -82
- package/lib/providers/cursor-adapter.js +42 -18
- package/lib/providers/cursor-auth.d.ts +1 -1
- package/lib/providers/cursor-auth.js +69 -24
- package/lib/providers/cursor-model-settings.js +14 -5
- package/lib/providers/cursor-usage.js +27 -13
- package/lib/providers/external-usage-controller.d.ts +9 -2
- package/lib/providers/external-usage-controller.js +30 -7
- package/lib/providers/external-usage.d.ts +8 -0
- package/lib/providers/external-usage.js +140 -20
- package/lib/providers/grok.js +152 -89
- package/lib/providers/image-pool.js +29 -11
- package/lib/providers/minimax-usage.js +31 -11
- package/lib/providers/npm-cli-version.js +10 -3
- package/lib/providers/ollama-settings.d.ts +90 -0
- package/lib/providers/ollama-settings.js +213 -0
- package/lib/providers/ollama-web.d.ts +46 -0
- package/lib/providers/ollama-web.js +231 -0
- package/lib/providers/ollama.d.ts +107 -0
- package/lib/providers/ollama.js +608 -0
- package/lib/providers/pool-family.js +11 -3
- package/lib/providers/pool-health.js +28 -8
- package/lib/providers/pool-usage.js +16 -9
- package/lib/providers/pool.d.ts +8 -0
- package/lib/providers/pool.js +81 -42
- package/lib/providers/rate-limit.js +8 -2
- package/lib/providers/replay.js +40 -17
- package/lib/providers/reset-redemption.js +18 -6
- package/lib/tools/image-generate.js +123 -65
- package/lib/tools/registration.js +5 -2
- package/lib/tools/video-generate.js +51 -31
- package/lib/tools/x-search.js +50 -22
- package/lib/translate/anthropic.js +85 -37
- package/lib/translate/antigravity-schema.js +71 -28
- package/lib/translate/antigravity-thinking.js +22 -9
- package/lib/translate/antigravity.js +141 -50
- package/lib/translate/chat-completions.js +67 -23
- package/lib/translate/resolved.js +55 -21
- package/lib/translate/responses.js +69 -29
- package/lib/translate/sse.js +4 -1
- package/package.json +26 -4
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama-native web capabilities: search and fetch ride the Cloud
|
|
3
|
+
* `/api/web_search` + `/api/web_fetch` endpoints independently of the
|
|
4
|
+
* selected chat model. Both providers share the `ollama-cloud` id because
|
|
5
|
+
* the seam addresses each capability kind separately.
|
|
6
|
+
*/
|
|
7
|
+
import { attributionHeaders } from '@deepseek-ai/dsh-llm';
|
|
8
|
+
import { WebError } from '@deepseek-ai/dsh-web';
|
|
9
|
+
import { readBoundedJson } from './common.js';
|
|
10
|
+
import { hostFetch } from '../http.js';
|
|
11
|
+
/** Shared provider id for both web capabilities. */
|
|
12
|
+
export const OLLAMA_WEB_PROVIDER_ID = 'ollama-cloud';
|
|
13
|
+
/** Per-attempt budget; the seam owns overall cancellation. */
|
|
14
|
+
export const OLLAMA_WEB_TIMEOUT_MS = 15_000;
|
|
15
|
+
/** Search result cap applied at the request layer. */
|
|
16
|
+
export const OLLAMA_WEB_MAX_RESULTS = 10;
|
|
17
|
+
/** Response body bound for web payloads. */
|
|
18
|
+
export const OLLAMA_WEB_MAX_BYTES = 2 * 1024 * 1024;
|
|
19
|
+
/** The effective base URL; both forms are read fresh so saves apply live. */
|
|
20
|
+
function baseURLOf(options) {
|
|
21
|
+
return typeof options.baseURL === 'function'
|
|
22
|
+
? options.baseURL()
|
|
23
|
+
: options.baseURL;
|
|
24
|
+
}
|
|
25
|
+
function throwIfAborted(signal) {
|
|
26
|
+
signal?.throwIfAborted();
|
|
27
|
+
}
|
|
28
|
+
function isRedirectFailure(error) {
|
|
29
|
+
// Real fetch failures nest: undici reports `fetch failed` on top with the
|
|
30
|
+
// redirect rejection in `cause`. Walk the chain instead of reading only
|
|
31
|
+
// the outer message.
|
|
32
|
+
for (let current = error; current instanceof Error; current = current.cause) {
|
|
33
|
+
if (/redirect/i.test(current.message))
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
async function postJson(url, apiKey, payload, options, signal) {
|
|
39
|
+
const fetchFn = options.fetchFn ?? hostFetch;
|
|
40
|
+
const timeoutMs = options.requestTimeoutMs ?? OLLAMA_WEB_TIMEOUT_MS;
|
|
41
|
+
// Exactly two attempts; only a timeout or a pre-response transport
|
|
42
|
+
// failure retries. HTTP errors, malformed replies, missing credentials,
|
|
43
|
+
// redirects, and caller cancellation never retry.
|
|
44
|
+
for (let attempt = 1; attempt <= 2; attempt += 1) {
|
|
45
|
+
throwIfAborted(signal);
|
|
46
|
+
const controller = new AbortController();
|
|
47
|
+
let timedOut = false;
|
|
48
|
+
const timer = setTimeout(() => {
|
|
49
|
+
timedOut = true;
|
|
50
|
+
controller.abort(new Error('ollama web request timed out'));
|
|
51
|
+
}, timeoutMs);
|
|
52
|
+
if (typeof timer.unref === 'function') {
|
|
53
|
+
;
|
|
54
|
+
timer.unref();
|
|
55
|
+
}
|
|
56
|
+
const onCallerAbort = () => controller.abort(signal?.reason);
|
|
57
|
+
signal?.addEventListener('abort', onCallerAbort, { once: true });
|
|
58
|
+
try {
|
|
59
|
+
const response = await fetchFn(url, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: {
|
|
62
|
+
'content-type': 'application/json',
|
|
63
|
+
accept: 'application/json',
|
|
64
|
+
authorization: `Bearer ${apiKey}`,
|
|
65
|
+
...attributionHeaders(),
|
|
66
|
+
},
|
|
67
|
+
body: JSON.stringify(payload),
|
|
68
|
+
redirect: 'error',
|
|
69
|
+
signal: controller.signal,
|
|
70
|
+
});
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
throw new WebError(`ollama web request failed (HTTP ${String(response.status)})`, 'OLLAMA_WEB_BAD_RESPONSE');
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
return (await readBoundedJson(response, 'ollama web request', OLLAMA_WEB_MAX_BYTES));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (signal?.aborted)
|
|
79
|
+
throw error;
|
|
80
|
+
// A timeout can also land mid-body: same retry treatment as a
|
|
81
|
+
// connect timeout, under the same code.
|
|
82
|
+
if (timedOut) {
|
|
83
|
+
if (attempt >= 2)
|
|
84
|
+
throw new WebError('ollama web request timed out', 'OLLAMA_WEB_TIMEOUT');
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
// The SyntaxError cause is dropped on purpose: V8 quotes the
|
|
88
|
+
// offending body bytes, which would carry provider text into
|
|
89
|
+
// logs through the chained message. An oversized body lands
|
|
90
|
+
// here too: loud and unretried.
|
|
91
|
+
throw new WebError('ollama web request returned a malformed reply', 'OLLAMA_WEB_BAD_REPLY');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (signal?.aborted)
|
|
96
|
+
throw error;
|
|
97
|
+
// Classified failures carry their own code and never retry.
|
|
98
|
+
if (error instanceof WebError)
|
|
99
|
+
throw error;
|
|
100
|
+
if (isRedirectFailure(error)) {
|
|
101
|
+
throw new WebError('ollama web request redirected; redirects are not followed', 'OLLAMA_WEB_REDIRECT');
|
|
102
|
+
}
|
|
103
|
+
if (timedOut) {
|
|
104
|
+
if (attempt >= 2)
|
|
105
|
+
throw new WebError('ollama web request timed out', 'OLLAMA_WEB_TIMEOUT', { cause: error });
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (attempt >= 2) {
|
|
109
|
+
throw new WebError('ollama web request transport failed', 'OLLAMA_WEB_TRANSPORT', { cause: error });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
clearTimeout(timer);
|
|
114
|
+
signal?.removeEventListener('abort', onCallerAbort);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
throw new WebError('ollama web request failed', 'OLLAMA_WEB_TRANSPORT');
|
|
118
|
+
}
|
|
119
|
+
function recordOf(value) {
|
|
120
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
121
|
+
? value
|
|
122
|
+
: undefined;
|
|
123
|
+
}
|
|
124
|
+
async function resolveWebKey(options, signal) {
|
|
125
|
+
throwIfAborted(signal);
|
|
126
|
+
const apiKey = await options.apiKey();
|
|
127
|
+
if (apiKey === undefined) {
|
|
128
|
+
throw new WebError('Ollama web search requires an Ollama Cloud API key; configure OLLAMA_API_KEY', 'OLLAMA_WEB_MISSING_CREDENTIAL');
|
|
129
|
+
}
|
|
130
|
+
return apiKey;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Refuse a call while the Settings switch is off. The host normally selects
|
|
134
|
+
* only available providers, but a pinned `searchProvider`/`fetchProvider`
|
|
135
|
+
* would otherwise keep routing through a provider the user turned off.
|
|
136
|
+
*/
|
|
137
|
+
function assertEnabled(options) {
|
|
138
|
+
if (options.enabled?.() === false) {
|
|
139
|
+
throw new WebError('Ollama web search/fetch is disabled in Settings', 'OLLAMA_WEB_DISABLED');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Search provider behind DSH's stock web_search tool. */
|
|
143
|
+
export class OllamaWebSearchProvider {
|
|
144
|
+
options;
|
|
145
|
+
id = OLLAMA_WEB_PROVIDER_ID;
|
|
146
|
+
constructor(options) {
|
|
147
|
+
this.options = options;
|
|
148
|
+
}
|
|
149
|
+
available() {
|
|
150
|
+
try {
|
|
151
|
+
new URL(baseURLOf(this.options));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
return this.options.enabled?.() ?? true;
|
|
157
|
+
}
|
|
158
|
+
async search(request, signal) {
|
|
159
|
+
assertEnabled(this.options);
|
|
160
|
+
const apiKey = await resolveWebKey(this.options, signal);
|
|
161
|
+
const base = baseURLOf(this.options).replace(/\/+$/, '');
|
|
162
|
+
const payload = await postJson(`${base}/web_search`, apiKey, {
|
|
163
|
+
query: request.query,
|
|
164
|
+
...(request.maxResults === undefined
|
|
165
|
+
? {}
|
|
166
|
+
: {
|
|
167
|
+
max_results: Math.min(request.maxResults, OLLAMA_WEB_MAX_RESULTS),
|
|
168
|
+
}),
|
|
169
|
+
}, this.options, signal);
|
|
170
|
+
const results = recordOf(payload)?.['results'];
|
|
171
|
+
if (!Array.isArray(results))
|
|
172
|
+
throw new WebError('ollama web search returned no results array', 'OLLAMA_WEB_BAD_REPLY');
|
|
173
|
+
// Official shape per docs: {title, url, content}. The snippet rides
|
|
174
|
+
// `content`, not `snippet`.
|
|
175
|
+
const sources = results.flatMap((entry) => {
|
|
176
|
+
const record = recordOf(entry);
|
|
177
|
+
const url = record?.['url'];
|
|
178
|
+
if (typeof url !== 'string' || url.length === 0)
|
|
179
|
+
return [];
|
|
180
|
+
return [
|
|
181
|
+
{
|
|
182
|
+
url,
|
|
183
|
+
...(typeof record?.['title'] === 'string'
|
|
184
|
+
? { title: record?.['title'] }
|
|
185
|
+
: {}),
|
|
186
|
+
...(typeof record?.['content'] === 'string'
|
|
187
|
+
? { snippet: record?.['content'] }
|
|
188
|
+
: {}),
|
|
189
|
+
},
|
|
190
|
+
];
|
|
191
|
+
});
|
|
192
|
+
return { sources, truncated: false };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/** Fetch provider behind DSH's stock web_fetch tool. */
|
|
196
|
+
export class OllamaWebFetchProvider {
|
|
197
|
+
options;
|
|
198
|
+
id = OLLAMA_WEB_PROVIDER_ID;
|
|
199
|
+
constructor(options) {
|
|
200
|
+
this.options = options;
|
|
201
|
+
}
|
|
202
|
+
available() {
|
|
203
|
+
try {
|
|
204
|
+
new URL(baseURLOf(this.options));
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
return this.options.enabled?.() ?? true;
|
|
210
|
+
}
|
|
211
|
+
async fetch(request, signal) {
|
|
212
|
+
assertEnabled(this.options);
|
|
213
|
+
const apiKey = await resolveWebKey(this.options, signal);
|
|
214
|
+
const base = baseURLOf(this.options).replace(/\/+$/, '');
|
|
215
|
+
const payload = await postJson(`${base}/web_fetch`, apiKey, { url: request.url }, this.options, signal);
|
|
216
|
+
// Official shape per docs: {title, content, links}. The endpoint
|
|
217
|
+
// answers the retrieval itself, so the request URL is the result URL
|
|
218
|
+
// and a decoded body means success.
|
|
219
|
+
const record = recordOf(payload);
|
|
220
|
+
const content = record?.['content'];
|
|
221
|
+
if (typeof content !== 'string') {
|
|
222
|
+
throw new WebError('ollama web fetch returned a malformed reply', 'OLLAMA_WEB_BAD_REPLY');
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
url: request.url,
|
|
226
|
+
statusCode: 200,
|
|
227
|
+
body: { kind: 'text', content },
|
|
228
|
+
truncated: false,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud provider: a key-based OpenAI-completions route with no OAuth
|
|
3
|
+
* session. The credential arrives per request as a bearer key; chat posts to
|
|
4
|
+
* the configured native baseURL's `/v1` sibling. The route ships no catalog:
|
|
5
|
+
* only models the user stored on the Settings card are served, so an empty
|
|
6
|
+
* store hides the picker entry and rejects every chat model.
|
|
7
|
+
*/
|
|
8
|
+
import { LlmAdapter } from '@deepseek-ai/dsh-llm';
|
|
9
|
+
import type { GenerateOptions, LlmModelInfo, LlmProviderInfo, LlmResolvedModelInfo, StreamChunk } from '@deepseek-ai/dsh-llm';
|
|
10
|
+
import type { DiscoveredModel, FetchFn } from './common.js';
|
|
11
|
+
import type { OllamaModelSetting } from './ollama-settings.js';
|
|
12
|
+
import type { AttachmentStore } from '@deepseek-ai/dsh-attachment';
|
|
13
|
+
/** Route id owned by this adapter. Not a member of the OAuth `PROVIDER_IDS`. */
|
|
14
|
+
export declare const OLLAMA_CLOUD_ROUTE = "ollama-cloud";
|
|
15
|
+
/** Default credential reference naming the Ollama Cloud API key. */
|
|
16
|
+
export declare const DEFAULT_OLLAMA_API_KEY_REF = "OLLAMA_API_KEY";
|
|
17
|
+
/** Default native base URL; chat maps it to its `/v1` sibling. */
|
|
18
|
+
export declare const DEFAULT_OLLAMA_BASE_URL = "https://ollama.com/api";
|
|
19
|
+
/** Fallback per-request output cap; Ollama publishes no per-model limit. */
|
|
20
|
+
export declare const OLLAMA_DEFAULT_MAX_TOKENS = 32768;
|
|
21
|
+
/** Fallback context window for a row the endpoint never described. */
|
|
22
|
+
export declare const OLLAMA_DEFAULT_CONTEXT_WINDOW = 262144;
|
|
23
|
+
/**
|
|
24
|
+
* Budget for the Settings card's explicit cloud listing. Longer than the
|
|
25
|
+
* picker's discovery bound because a user waits on this one and `/api/show`
|
|
26
|
+
* runs once per model.
|
|
27
|
+
*/
|
|
28
|
+
export declare const OLLAMA_PULL_TIMEOUT_MS = 20000;
|
|
29
|
+
/**
|
|
30
|
+
* The window the session plans against: the user's override, capped at what
|
|
31
|
+
* the endpoint advertises (or, without discovery, the stored snapshot). The
|
|
32
|
+
* cap keeps a stale or mistyped override from planning past the model.
|
|
33
|
+
*/
|
|
34
|
+
export declare function effectiveContextWindow(row: {
|
|
35
|
+
contextWindow: number;
|
|
36
|
+
contextOverride: number | undefined;
|
|
37
|
+
}, discovered: number | undefined): number;
|
|
38
|
+
export interface OllamaAdapterOptions {
|
|
39
|
+
/** Resolve the API key per request; `undefined` means unconfigured. */
|
|
40
|
+
apiKey: () => Promise<string | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Live native base URL (`https://ollama.com/api`); chat maps it to `/v1`.
|
|
43
|
+
* Read per request so a Settings save takes effect without a restart.
|
|
44
|
+
*/
|
|
45
|
+
baseURL: () => string;
|
|
46
|
+
/**
|
|
47
|
+
* Live catalog snapshot, in picker order. The Settings store (or a
|
|
48
|
+
* non-empty config override) is the only source; an empty list means the
|
|
49
|
+
* route serves no model.
|
|
50
|
+
*/
|
|
51
|
+
catalog: () => readonly OllamaModelSetting[];
|
|
52
|
+
/** Per-model default-effort override, winning over the stored row. */
|
|
53
|
+
defaultEffortOf?: (model: string) => string | undefined;
|
|
54
|
+
/** Live discovery via `/api/tags` + `/api/show` (default true). */
|
|
55
|
+
discovery?: boolean;
|
|
56
|
+
fetchFn?: FetchFn;
|
|
57
|
+
resolveAttachments?: () => AttachmentStore | undefined;
|
|
58
|
+
streamIdleTimeoutMs?: number;
|
|
59
|
+
onWarn?: (message: string) => void;
|
|
60
|
+
}
|
|
61
|
+
/** Map a native base URL to its OpenAI-compatible chat sibling. */
|
|
62
|
+
export declare function ollamaChatBaseURL(baseURL: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Normalize one listing id to the wire id the chat endpoint accepts. The
|
|
65
|
+
* Cloud listing advertises bare names (`glm-5.3`) while its chat wire wants
|
|
66
|
+
* the `:cloud` tag; a local daemon reached through a custom base URL takes
|
|
67
|
+
* the bare name, so only the official host gets the tag. An id that already
|
|
68
|
+
* carries a tag is returned unchanged.
|
|
69
|
+
* @param id - the id as listed by `/api/tags`.
|
|
70
|
+
* @param baseURL - the native base URL the listing came from.
|
|
71
|
+
* @returns the id to store and send on the chat wire.
|
|
72
|
+
*/
|
|
73
|
+
export declare function normalizeOllamaModelId(id: string, baseURL: string): string;
|
|
74
|
+
export interface OllamaDiscoveryOptions {
|
|
75
|
+
baseURL: string;
|
|
76
|
+
apiKey: string | undefined;
|
|
77
|
+
fetchFn?: FetchFn | undefined;
|
|
78
|
+
signal?: AbortSignal | undefined;
|
|
79
|
+
}
|
|
80
|
+
/** One discovered Cloud model, with the capability flags the card badges. */
|
|
81
|
+
export interface OllamaDiscoveredModel extends DiscoveredModel {
|
|
82
|
+
/** The id exactly as `/api/tags` published it, before wire normalization. */
|
|
83
|
+
rawId: string;
|
|
84
|
+
/** The endpoint advertised the `thinking` capability. */
|
|
85
|
+
thinking: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* List Cloud models via `/api/tags`, enriching through `/api/show`. A failed
|
|
89
|
+
* enrichment degrades to an id-only row; a failed listing fails. Listing ids
|
|
90
|
+
* are normalized to their wire form ({@link normalizeOllamaModelId}) while
|
|
91
|
+
* `/api/show` still receives the id the endpoint published.
|
|
92
|
+
*/
|
|
93
|
+
export declare function fetchOllamaModels(options: OllamaDiscoveryOptions): Promise<OllamaDiscoveredModel[]>;
|
|
94
|
+
export declare function ollamaChatRequestBody(options: GenerateOptions, messages: Record<string, unknown>[], maxTokens: number | undefined): Record<string, unknown>;
|
|
95
|
+
export declare class OllamaAdapter extends LlmAdapter {
|
|
96
|
+
private readonly options;
|
|
97
|
+
private readonly catalogCache;
|
|
98
|
+
constructor(options: OllamaAdapterOptions);
|
|
99
|
+
/** Drop the discovery snapshot so the next picker pass re-reads the endpoint. */
|
|
100
|
+
invalidateModels(): void;
|
|
101
|
+
private rows;
|
|
102
|
+
providerInfo(provider: string): LlmProviderInfo;
|
|
103
|
+
listModels(provider: string): Promise<readonly LlmModelInfo[]>;
|
|
104
|
+
private staticList;
|
|
105
|
+
resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo>;
|
|
106
|
+
stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
|
|
107
|
+
}
|