dsh-local-ai 0.1.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +201 -0
  3. package/README.es.md +211 -0
  4. package/README.hi.md +211 -0
  5. package/README.md +211 -0
  6. package/README.pt.md +211 -0
  7. package/README.zh.md +211 -0
  8. package/THIRD_PARTY_NOTICES.md +20 -0
  9. package/cordis.patch.yml +44 -0
  10. package/lib/index.js +1334 -0
  11. package/lib/types/adapter.d.ts +39 -0
  12. package/lib/types/adapter.d.ts.map +1 -0
  13. package/lib/types/adapter.js +190 -0
  14. package/lib/types/adapter.js.map +1 -0
  15. package/lib/types/config.d.ts +109 -0
  16. package/lib/types/config.d.ts.map +1 -0
  17. package/lib/types/config.js +161 -0
  18. package/lib/types/config.js.map +1 -0
  19. package/lib/types/health.d.ts +64 -0
  20. package/lib/types/health.d.ts.map +1 -0
  21. package/lib/types/health.js +92 -0
  22. package/lib/types/health.js.map +1 -0
  23. package/lib/types/index.d.ts +43 -0
  24. package/lib/types/index.d.ts.map +1 -0
  25. package/lib/types/index.js +232 -0
  26. package/lib/types/index.js.map +1 -0
  27. package/lib/types/ollama.d.ts +91 -0
  28. package/lib/types/ollama.d.ts.map +1 -0
  29. package/lib/types/ollama.js +184 -0
  30. package/lib/types/ollama.js.map +1 -0
  31. package/lib/types/route.d.ts +52 -0
  32. package/lib/types/route.d.ts.map +1 -0
  33. package/lib/types/route.js +119 -0
  34. package/lib/types/route.js.map +1 -0
  35. package/lib/types/sanitize.d.ts +58 -0
  36. package/lib/types/sanitize.d.ts.map +1 -0
  37. package/lib/types/sanitize.js +110 -0
  38. package/lib/types/sanitize.js.map +1 -0
  39. package/lib/types/serialize.d.ts +65 -0
  40. package/lib/types/serialize.d.ts.map +1 -0
  41. package/lib/types/serialize.js +149 -0
  42. package/lib/types/serialize.js.map +1 -0
  43. package/lib/types/translate.d.ts +57 -0
  44. package/lib/types/translate.d.ts.map +1 -0
  45. package/lib/types/translate.js +169 -0
  46. package/lib/types/translate.js.map +1 -0
  47. package/lib/types/version.d.ts +6 -0
  48. package/lib/types/version.d.ts.map +1 -0
  49. package/lib/types/version.js +6 -0
  50. package/lib/types/version.js.map +1 -0
  51. package/package.json +141 -0
  52. package/src/adapter.ts +158 -0
  53. package/src/config.ts +243 -0
  54. package/src/health.ts +133 -0
  55. package/src/index.ts +279 -0
  56. package/src/ollama.ts +274 -0
  57. package/src/route.ts +127 -0
  58. package/src/sanitize.ts +114 -0
  59. package/src/serialize.ts +178 -0
  60. package/src/translate.ts +205 -0
  61. package/src/version.ts +5 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Health checks for the local Ollama server: API responsiveness over HTTP and
3
+ * process liveness through the real subprocess seam (the `ollama` CLI's own
4
+ * channel). Both signals are independent — a server that answers HTTP but has
5
+ * no reachable CLI, or vice versa, is reported as two facts, never conflated.
6
+ * @module dsh-local-ai/health
7
+ */
8
+ import { apiVersion } from "./ollama.js";
9
+ import { sanitizeText } from "./sanitize.js";
10
+ import { tmpdir } from 'node:os';
11
+ /** The default probe: `ollama list` reaches the server through the CLI's own channel. */
12
+ export const OLLAMA_PROCESS_PROBE = { command: 'ollama', args: ['list'] };
13
+ /**
14
+ * Check whether the Ollama HTTP API responds to `/api/version` within a
15
+ * deadline. A timeout, transport failure, or non-2xx response is `ok: false`
16
+ * with a sanitized error.
17
+ * @param baseURL - the Ollama base URL.
18
+ * @param fetchImpl - the fetch implementation.
19
+ * @param timeoutMs - deadline in milliseconds.
20
+ * @returns the API health result.
21
+ */
22
+ export async function checkApiHealth(baseURL, fetchImpl, timeoutMs) {
23
+ const controller = new AbortController();
24
+ const timer = setTimeout(() => controller.abort(new Error('timeout')), timeoutMs);
25
+ try {
26
+ const version = await apiVersion(baseURL, fetchImpl, controller.signal);
27
+ return { ok: true, version: sanitizeText(version, 64) };
28
+ }
29
+ catch (error) {
30
+ return { ok: false, error: sanitizeText(error instanceof Error ? error.message : String(error), 500) };
31
+ }
32
+ finally {
33
+ clearTimeout(timer);
34
+ }
35
+ }
36
+ /**
37
+ * Check process liveness through the subprocess seam by spawning the probe
38
+ * command in collect mode. Exit code 0 means the CLI (and, for the default
39
+ * `ollama list` probe, the server it talks to) is alive; a missing executable
40
+ * or non-zero exit is `present: false` with a sanitized error.
41
+ * @param subprocess - the real subprocess runtime.
42
+ * @param graceMs - terminate grace for the spawned probe.
43
+ * @param probe - the command to probe with (defaults to `ollama list`).
44
+ * @returns the process health result.
45
+ */
46
+ export async function checkProcessHealth(subprocess, graceMs, probe = OLLAMA_PROCESS_PROBE) {
47
+ let executable;
48
+ try {
49
+ executable = await subprocess.resolveExecutable(probe.command);
50
+ }
51
+ catch (error) {
52
+ return {
53
+ present: false,
54
+ error: sanitizeText(`"${probe.command}" not found: ${error instanceof Error ? error.message : String(error)}`, 500),
55
+ };
56
+ }
57
+ const handle = subprocess.spawn({
58
+ argv: [executable, ...probe.args],
59
+ cwd: tmpdir(),
60
+ stdio: {
61
+ stdin: 'ignore',
62
+ stdout: { maxBytes: 4096 },
63
+ stderr: { maxBytes: 4096 },
64
+ },
65
+ graceMs,
66
+ });
67
+ const outcome = await handle.done;
68
+ if (outcome.exitCode === 0)
69
+ return { present: true };
70
+ const stderr = handle.collected.stderr?.readFrom(0).text ?? '';
71
+ return {
72
+ present: false,
73
+ error: sanitizeText(stderr.trim().length > 0 ? stderr : `exit code ${String(outcome.exitCode)}`, 500),
74
+ };
75
+ }
76
+ /**
77
+ * Check both health signals.
78
+ * @param baseURL - the Ollama base URL.
79
+ * @param fetchImpl - the fetch implementation.
80
+ * @param subprocess - the real subprocess runtime.
81
+ * @param requestTimeoutMs - HTTP deadline in milliseconds.
82
+ * @param graceMs - subprocess terminate grace in milliseconds.
83
+ * @returns the combined health result.
84
+ */
85
+ export async function checkHealth(baseURL, fetchImpl, subprocess, requestTimeoutMs, graceMs) {
86
+ const [api, process] = await Promise.all([
87
+ checkApiHealth(baseURL, fetchImpl, requestTimeoutMs),
88
+ checkProcessHealth(subprocess, graceMs),
89
+ ]);
90
+ return { api, process };
91
+ }
92
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * `dsh-local-ai` — local-model (Ollama) integration for DeepSeek Harness.
3
+ * Registers the `ollama` `LlmAdapter` route, exposes discovery/management
4
+ * tools (`ollama_list`, `ollama_show`, `ollama_pull`, `ollama_remove`) plus a
5
+ * health check, routes requests to local models by task type or keyword with
6
+ * automatic fallback to the cloud, and provides the `/ollama` one-shot status
7
+ * command. Zero runtime dependencies beyond the harness peers: everything
8
+ * talks to Ollama over its HTTP API (or, for process liveness, the CLI).
9
+ *
10
+ * Function plugin — no default export (the Loader unwraps
11
+ * `exports.default ?? exports`, and a stray default would discard
12
+ * `name`/`inject`/`Config`/`apply`).
13
+ * @module dsh-local-ai
14
+ */
15
+ import type { Context } from '@deepseek-ai/cordis';
16
+ import type { JsonValue } from '@deepseek-ai/dsh-tools';
17
+ import { Config } from './config.ts';
18
+ export declare const name = "local-ai";
19
+ export declare const inject: string[];
20
+ export { Config, resolveConfig } from './config.ts';
21
+ export type { Config as LocalAiConfig, ModelMapping, ResolvedConfig, ResolvedModelMapping, ResolvedRouteRule, RouteRule } from './config.ts';
22
+ export { VERSION } from './version.ts';
23
+ export { REDACTED, redactSecrets, sanitizeEndpoint, sanitizePath, sanitizeText, truncate } from './sanitize.ts';
24
+ /** Format a byte count into a compact human-readable string. */
25
+ export declare function formatBytes(bytes: number): string;
26
+ /** Render the `ollama_list` canonical value as model-visible text. */
27
+ export declare function renderList(value: JsonValue): string;
28
+ /** Render the `ollama_show` canonical value as model-visible text. */
29
+ export declare function renderShow(value: JsonValue): string;
30
+ /** Render a health canonical value as model-visible text. */
31
+ export declare function renderHealth(value: JsonValue): string;
32
+ /** Render a pull/remove canonical value as model-visible text. */
33
+ export declare function renderOperation(value: JsonValue): string;
34
+ /**
35
+ * Mount the plugin: resolve config (fail loud), register the Ollama adapter,
36
+ * the `llm/stream` routing waterfall, the five management tools, and the
37
+ * `/ollama` command. Every contribution goes through its registry's effect
38
+ * (register/on), so stop and hot-reload withdraw all of it.
39
+ * @param ctx - the plugin context (host).
40
+ * @param config - raw plugin config.
41
+ */
42
+ export declare function apply(ctx: Context, config?: Config): void;
43
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAGvD,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAA;AAOnD,eAAO,MAAM,IAAI,aAAa,CAAA;AAC9B,eAAO,MAAM,MAAM,UAA6C,CAAA;AAEhE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACnD,YAAY,EAAE,MAAM,IAAI,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5I,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE/G,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWjD;AA6BD,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAYnD;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAMnD;AAED,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CASrD;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAIxD;AAED;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI,CAuJ7D"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * `dsh-local-ai` — local-model (Ollama) integration for DeepSeek Harness.
3
+ * Registers the `ollama` `LlmAdapter` route, exposes discovery/management
4
+ * tools (`ollama_list`, `ollama_show`, `ollama_pull`, `ollama_remove`) plus a
5
+ * health check, routes requests to local models by task type or keyword with
6
+ * automatic fallback to the cloud, and provides the `/ollama` one-shot status
7
+ * command. Zero runtime dependencies beyond the harness peers: everything
8
+ * talks to Ollama over its HTTP API (or, for process liveness, the CLI).
9
+ *
10
+ * Function plugin — no default export (the Loader unwraps
11
+ * `exports.default ?? exports`, and a stray default would discard
12
+ * `name`/`inject`/`Config`/`apply`).
13
+ * @module dsh-local-ai
14
+ */
15
+ import { defineTool } from '@deepseek-ai/dsh-tools';
16
+ import { resolveConfig } from "./config.js";
17
+ import { OllamaAdapter, OLLAMA_PROVIDER } from "./adapter.js";
18
+ import { decideRoute, routeLocal } from "./route.js";
19
+ import { checkHealth } from "./health.js";
20
+ import { contextLengthOf, listModels, listRunning, pullModel, removeModel, showModel } from "./ollama.js";
21
+ export const name = 'local-ai';
22
+ export const inject = ['llm', 'tools', 'subprocess', 'commands'];
23
+ export { Config, resolveConfig } from "./config.js";
24
+ export { VERSION } from "./version.js";
25
+ export { REDACTED, redactSecrets, sanitizeEndpoint, sanitizePath, sanitizeText, truncate } from "./sanitize.js";
26
+ /** Format a byte count into a compact human-readable string. */
27
+ export function formatBytes(bytes) {
28
+ if (!Number.isFinite(bytes) || bytes < 0)
29
+ return '0 B';
30
+ const units = ['B', 'KB', 'MB', 'GB', 'TB'];
31
+ let value = bytes;
32
+ let unit = 0;
33
+ while (value >= 1024 && unit < units.length - 1) {
34
+ value /= 1024;
35
+ unit += 1;
36
+ }
37
+ const rounded = unit === 0 ? String(Math.round(value)) : value.toFixed(1);
38
+ return `${rounded} ${units[unit]}`;
39
+ }
40
+ /** Render the `ollama_list` canonical value as model-visible text. */
41
+ export function renderList(value) {
42
+ const list = value;
43
+ const models = list.models ?? [];
44
+ const lines = [`${models.length} local model(s), ${formatBytes(list.totalBytes ?? 0)} on disk`];
45
+ for (const model of models) {
46
+ const detail = [model.parameterSize, model.quantization].filter(part => part !== undefined).join(' ');
47
+ lines.push(`- ${model.name}${detail.length > 0 ? ` (${detail})` : ''} — ${formatBytes(model.size)}${model.running ? ' [running]' : ''}`);
48
+ }
49
+ if (list.running !== undefined && list.running.length > 0) {
50
+ lines.push(`running: ${list.running.join(', ')}`);
51
+ }
52
+ return lines.join('\n');
53
+ }
54
+ /** Render the `ollama_show` canonical value as model-visible text. */
55
+ export function renderShow(value) {
56
+ const show = value;
57
+ const detail = [show.parameterSize, show.quantization].filter(part => part !== undefined).join(' ');
58
+ const context = show.contextLength !== undefined ? `context ${show.contextLength}` : undefined;
59
+ const parts = [detail, context, show.family, show.format].filter(part => part !== undefined && part.length > 0);
60
+ return `${show.name}${parts.length > 0 ? ` — ${parts.join(', ')}` : ''}`;
61
+ }
62
+ /** Render a health canonical value as model-visible text. */
63
+ export function renderHealth(value) {
64
+ const health = value;
65
+ return [
66
+ `API: ${health.api.ok ? `ok${health.api.version !== undefined ? ` (v${health.api.version})` : ''}` : 'down'}`,
67
+ `process: ${health.process.present ? 'alive' : 'not detected'}`,
68
+ ].join('\n');
69
+ }
70
+ /** Render a pull/remove canonical value as model-visible text. */
71
+ export function renderOperation(value) {
72
+ const op = value;
73
+ if (op.removed === true)
74
+ return `removed ${op.name}`;
75
+ return `${op.name}: ${op.status ?? 'done'}`;
76
+ }
77
+ /**
78
+ * Mount the plugin: resolve config (fail loud), register the Ollama adapter,
79
+ * the `llm/stream` routing waterfall, the five management tools, and the
80
+ * `/ollama` command. Every contribution goes through its registry's effect
81
+ * (register/on), so stop and hot-reload withdraw all of it.
82
+ * @param ctx - the plugin context (host).
83
+ * @param config - raw plugin config.
84
+ */
85
+ export function apply(ctx, config = {}) {
86
+ const resolved = resolveConfig(config);
87
+ const logger = ctx.logger('local-ai');
88
+ // Lazily-bound so tests can stub `globalThis.fetch` before a call.
89
+ const fetchImpl = (input, init) => globalThis.fetch(input, init);
90
+ const adapter = new OllamaAdapter({ config: () => resolved, fetchImpl });
91
+ ctx.llm.registerAdapter([OLLAMA_PROVIDER], adapter);
92
+ // Routing waterfall: passthrough by default; a matched rule re-routes to the
93
+ // local model and falls back to `next()` (the cloud) when local fails first.
94
+ ctx.on('llm/stream', (options, next) => {
95
+ const decision = decideRoute(options, resolved);
96
+ if (decision === undefined)
97
+ return next();
98
+ return routeLocal((reRouted) => ctx.llm.stream(reRouted), options, decision, next);
99
+ });
100
+ ctx.tools.register(defineTool({
101
+ name: 'ollama_list',
102
+ description: 'List local Ollama models with disk usage and which are currently loaded (running).',
103
+ parameters: {},
104
+ output: {
105
+ schema: { type: 'json' },
106
+ render: (_args, value) => [{ type: 'text', text: renderList(value) }],
107
+ },
108
+ async execute(_args, exec) {
109
+ const [models, running] = await Promise.all([
110
+ listModels(resolved.baseURL, fetchImpl, exec.signal),
111
+ listRunning(resolved.baseURL, fetchImpl, exec.signal).catch(() => []),
112
+ ]);
113
+ const runningNames = new Set(running.map(model => model.name));
114
+ const value = {
115
+ models: models.map(model => ({
116
+ name: model.name,
117
+ size: model.size,
118
+ ...model.details?.parameter_size === undefined ? {} : { parameterSize: model.details.parameter_size },
119
+ ...model.details?.quantization_level === undefined ? {} : { quantization: model.details.quantization_level },
120
+ running: runningNames.has(model.name),
121
+ })),
122
+ running: running.map(model => model.name),
123
+ count: models.length,
124
+ totalBytes: models.reduce((sum, model) => sum + model.size, 0),
125
+ };
126
+ return value;
127
+ },
128
+ }));
129
+ ctx.tools.register(defineTool({
130
+ name: 'ollama_show',
131
+ description: 'Show details for one local Ollama model: parameter size, quantization, and context length.',
132
+ parameters: {
133
+ name: { type: 'string', required: true, description: 'The Ollama model name to inspect.' },
134
+ },
135
+ output: {
136
+ schema: { type: 'json' },
137
+ render: (_args, value) => [{ type: 'text', text: renderShow(value) }],
138
+ },
139
+ async execute(args, exec) {
140
+ const name = args.name;
141
+ const show = await showModel(resolved.baseURL, name, fetchImpl, exec.signal);
142
+ const value = {
143
+ name,
144
+ ...show.details?.parameter_size === undefined ? {} : { parameterSize: show.details.parameter_size },
145
+ ...show.details?.quantization_level === undefined ? {} : { quantization: show.details.quantization_level },
146
+ ...show.details?.family === undefined ? {} : { family: show.details.family },
147
+ ...show.details?.format === undefined ? {} : { format: show.details.format },
148
+ ...(() => {
149
+ const contextLength = contextLengthOf(show);
150
+ return contextLength === undefined ? {} : { contextLength };
151
+ })(),
152
+ };
153
+ return value;
154
+ },
155
+ }));
156
+ ctx.tools.register(defineTool({
157
+ name: 'ollama_pull',
158
+ description: 'Pull (download) a model into the local Ollama server.',
159
+ parameters: {
160
+ name: { type: 'string', required: true, description: 'The Ollama model name to pull (e.g. llama3.2).' },
161
+ },
162
+ output: {
163
+ schema: { type: 'json' },
164
+ render: (_args, value) => [{ type: 'text', text: renderOperation(value) }],
165
+ },
166
+ async execute(args, exec) {
167
+ const name = args.name;
168
+ const result = await pullModel(resolved.baseURL, name, fetchImpl, exec.signal);
169
+ return { name, status: result.status };
170
+ },
171
+ }));
172
+ ctx.tools.register(defineTool({
173
+ name: 'ollama_remove',
174
+ description: 'Remove (delete) a model from the local Ollama server.',
175
+ parameters: {
176
+ name: { type: 'string', required: true, description: 'The Ollama model name to remove.' },
177
+ },
178
+ output: {
179
+ schema: { type: 'json' },
180
+ render: (_args, value) => [{ type: 'text', text: renderOperation(value) }],
181
+ },
182
+ async execute(args, exec) {
183
+ const name = args.name;
184
+ await removeModel(resolved.baseURL, name, fetchImpl, exec.signal);
185
+ return { name, removed: true };
186
+ },
187
+ }));
188
+ ctx.tools.register(defineTool({
189
+ name: 'ollama_health',
190
+ description: 'Check the local Ollama server: whether the process is alive and whether the API responds.',
191
+ parameters: {},
192
+ output: {
193
+ schema: { type: 'json' },
194
+ render: (_args, value) => [{ type: 'text', text: renderHealth(value) }],
195
+ },
196
+ async execute(_args, exec) {
197
+ const health = await checkHealth(resolved.baseURL, fetchImpl, ctx.subprocess, resolved.requestTimeoutMs, resolved.graceMs);
198
+ void exec;
199
+ return health;
200
+ },
201
+ }));
202
+ ctx.commands.register({
203
+ name: 'ollama',
204
+ description: 'One-shot status overview: local models, disk usage, health, and routing suggestions.',
205
+ async handler() {
206
+ const health = await checkHealth(resolved.baseURL, fetchImpl, ctx.subprocess, resolved.requestTimeoutMs, resolved.graceMs);
207
+ const lines = ['Ollama status:'];
208
+ lines.push(`- API: ${health.api.ok ? `ok${health.api.version !== undefined ? ` (v${health.api.version})` : ''}` : 'down'}`);
209
+ lines.push(`- process: ${health.process.present ? 'alive' : 'not detected'}`);
210
+ let models = [];
211
+ try {
212
+ models = await listModels(resolved.baseURL, fetchImpl);
213
+ }
214
+ catch {
215
+ // Model listing is best-effort in the overview; health already reported the failure.
216
+ }
217
+ const totalBytes = models.reduce((sum, model) => sum + model.size, 0);
218
+ lines.push(`- models: ${models.length} installed (${formatBytes(totalBytes)})`);
219
+ for (const model of models)
220
+ lines.push(` - ${model.name} (${formatBytes(model.size)})`);
221
+ if (!health.api.ok && !health.process.present) {
222
+ lines.push('suggestion: start the Ollama server (e.g. `ollama serve`)');
223
+ }
224
+ else if (resolved.route.length === 0) {
225
+ lines.push('suggestion: configure `route` rules to route requests to local models');
226
+ }
227
+ return { kind: 'success', text: lines.join('\n') };
228
+ },
229
+ });
230
+ logger.info(`ollama adapter registered at ${resolved.baseURL} (${resolved.models.length} mapping(s), ${resolved.route.length} route rule(s))`);
231
+ }
232
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Ollama HTTP API client (zero runtime dependencies — plain `fetch`). The
3
+ * harness `LlmAdapter` streams through `/api/chat`; discovery and management
4
+ * tools call `/api/tags`, `/api/show`, `/api/pull`, `/api/delete`, and
5
+ * `/api/version`. Every request carries the harness attribution headers and
6
+ * honors the caller's abort signal; non-2xx responses fail with a normalized
7
+ * `LlmError`. The fetch implementation is injectable for tests.
8
+ * @module dsh-local-ai/ollama
9
+ */
10
+ /** A `fetch`-compatible function, injectable for tests. */
11
+ export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
12
+ /** One installed model as reported by `/api/tags`. */
13
+ export interface OllamaModel {
14
+ name: string;
15
+ model: string;
16
+ size: number;
17
+ digest: string;
18
+ modified_at?: string;
19
+ details?: OllamaModelDetails;
20
+ }
21
+ /** Structured model details reported by `/api/show` and `/api/tags`. */
22
+ export interface OllamaModelDetails {
23
+ family?: string;
24
+ parameter_size?: string;
25
+ quantization_level?: string;
26
+ format?: string;
27
+ parent_model?: string;
28
+ }
29
+ /** The `/api/show` response body. */
30
+ export interface OllamaShowResult {
31
+ license?: string;
32
+ modelfile?: string;
33
+ parameters?: string;
34
+ template?: string;
35
+ details?: OllamaModelDetails;
36
+ model_info?: Record<string, unknown>;
37
+ }
38
+ /** The `/api/version` response body. */
39
+ export interface OllamaVersionResult {
40
+ version: string;
41
+ }
42
+ /** The `/api/pull` final success status. */
43
+ export interface OllamaPullResult {
44
+ status: string;
45
+ }
46
+ /** Build an absolute API URL from a normalized base URL. */
47
+ export declare function endpointUrl(baseURL: string, path: string): string;
48
+ /** Map an HTTP status to a stable LlmError code. */
49
+ export declare function httpErrorCode(status: number): string;
50
+ /** Send a GET request and parse the JSON response. */
51
+ export declare function requestJson<T>(baseURL: string, path: string, fetchImpl: FetchLike, signal?: AbortSignal): Promise<T>;
52
+ /** Send a POST request and parse the JSON response. */
53
+ export declare function postJson<T>(baseURL: string, path: string, body: unknown, fetchImpl: FetchLike, signal?: AbortSignal): Promise<T>;
54
+ /** Send a DELETE request and parse the JSON response. */
55
+ export declare function deleteJson<T>(baseURL: string, path: string, body: unknown, fetchImpl: FetchLike, signal?: AbortSignal): Promise<T>;
56
+ /**
57
+ * Send a POST and return the raw `Response` after validating 2xx. Used by the
58
+ * streaming adapter, which owns body decoding and the idle watchdog.
59
+ */
60
+ export declare function postStream(baseURL: string, path: string, body: unknown, fetchImpl: FetchLike, signal?: AbortSignal): Promise<Response>;
61
+ /** List installed models from `/api/tags`. */
62
+ export declare function listModels(baseURL: string, fetchImpl: FetchLike, signal?: AbortSignal): Promise<OllamaModel[]>;
63
+ /** List currently-loaded (running) models from `/api/ps`. */
64
+ export declare function listRunning(baseURL: string, fetchImpl: FetchLike, signal?: AbortSignal): Promise<OllamaModel[]>;
65
+ /** Inspect one model via `/api/show`. */
66
+ export declare function showModel(baseURL: string, name: string, fetchImpl: FetchLike, signal?: AbortSignal): Promise<OllamaShowResult>;
67
+ /** Remove one model via `/api/delete`. */
68
+ export declare function removeModel(baseURL: string, name: string, fetchImpl: FetchLike, signal?: AbortSignal): Promise<void>;
69
+ /** Query the Ollama server version via `/api/version`. */
70
+ export declare function apiVersion(baseURL: string, fetchImpl: FetchLike, signal?: AbortSignal): Promise<string>;
71
+ /**
72
+ * Pull a model via `/api/pull`, consuming the progress stream and returning the
73
+ * final status. An intermediate error status or a non-2xx response fails loud.
74
+ */
75
+ export declare function pullModel(baseURL: string, name: string, fetchImpl: FetchLike, signal?: AbortSignal): Promise<OllamaPullResult>;
76
+ /**
77
+ * Decode a `ReadableStream<Uint8Array>` into newline-delimited text lines.
78
+ * The final line is yielded even without a trailing newline; a missing body
79
+ * yields nothing.
80
+ * @param body - the response body stream.
81
+ * @returns text lines in delivery order.
82
+ */
83
+ export declare function readNdjsonLines(body: ReadableStream<Uint8Array>): AsyncGenerator<string>;
84
+ /**
85
+ * Extract the context length from an `/api/show` result by scanning
86
+ * `model_info` for a `*.context_length` or bare `context_length` entry.
87
+ * @param show - the `/api/show` result.
88
+ * @returns the context length, or `undefined` when not reported.
89
+ */
90
+ export declare function contextLengthOf(show: OllamaShowResult): number | undefined;
91
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../src/ollama.ts"],"names":[],"mappings":"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"}