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.
- package/CHANGELOG.md +17 -0
- package/LICENSE +201 -0
- package/README.es.md +211 -0
- package/README.hi.md +211 -0
- package/README.md +211 -0
- package/README.pt.md +211 -0
- package/README.zh.md +211 -0
- package/THIRD_PARTY_NOTICES.md +20 -0
- package/cordis.patch.yml +44 -0
- package/lib/index.js +1334 -0
- package/lib/types/adapter.d.ts +39 -0
- package/lib/types/adapter.d.ts.map +1 -0
- package/lib/types/adapter.js +190 -0
- package/lib/types/adapter.js.map +1 -0
- package/lib/types/config.d.ts +109 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/config.js +161 -0
- package/lib/types/config.js.map +1 -0
- package/lib/types/health.d.ts +64 -0
- package/lib/types/health.d.ts.map +1 -0
- package/lib/types/health.js +92 -0
- package/lib/types/health.js.map +1 -0
- package/lib/types/index.d.ts +43 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +232 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/ollama.d.ts +91 -0
- package/lib/types/ollama.d.ts.map +1 -0
- package/lib/types/ollama.js +184 -0
- package/lib/types/ollama.js.map +1 -0
- package/lib/types/route.d.ts +52 -0
- package/lib/types/route.d.ts.map +1 -0
- package/lib/types/route.js +119 -0
- package/lib/types/route.js.map +1 -0
- package/lib/types/sanitize.d.ts +58 -0
- package/lib/types/sanitize.d.ts.map +1 -0
- package/lib/types/sanitize.js +110 -0
- package/lib/types/sanitize.js.map +1 -0
- package/lib/types/serialize.d.ts +65 -0
- package/lib/types/serialize.d.ts.map +1 -0
- package/lib/types/serialize.js +149 -0
- package/lib/types/serialize.js.map +1 -0
- package/lib/types/translate.d.ts +57 -0
- package/lib/types/translate.d.ts.map +1 -0
- package/lib/types/translate.js +169 -0
- package/lib/types/translate.js.map +1 -0
- package/lib/types/version.d.ts +6 -0
- package/lib/types/version.d.ts.map +1 -0
- package/lib/types/version.js +6 -0
- package/lib/types/version.js.map +1 -0
- package/package.json +141 -0
- package/src/adapter.ts +158 -0
- package/src/config.ts +243 -0
- package/src/health.ts +133 -0
- package/src/index.ts +279 -0
- package/src/ollama.ts +274 -0
- package/src/route.ts +127 -0
- package/src/sanitize.ts +114 -0
- package/src/serialize.ts +178 -0
- package/src/translate.ts +205 -0
- package/src/version.ts +5 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize harness messages and requests into the Ollama `/api/chat` wire
|
|
3
|
+
* vocabulary. User text is joined; assistant text becomes `content` and tool
|
|
4
|
+
* calls become `tool_calls` (with arguments parsed from the raw JSON string to
|
|
5
|
+
* the object Ollama expects); tool results become separate `tool` messages.
|
|
6
|
+
* Core image blocks are rejected explicitly because this route is text-only;
|
|
7
|
+
* unknown declaration-merged block types retain the documented extension
|
|
8
|
+
* fallback (ignored for content, retained as text where text is expected).
|
|
9
|
+
* @module dsh-local-ai/serialize
|
|
10
|
+
*/
|
|
11
|
+
import { contentHasImage, LlmError } from '@deepseek-ai/dsh-llm';
|
|
12
|
+
/** Join the text blocks of a message (used for user/tool-result content). */
|
|
13
|
+
function flattenText(blocks) {
|
|
14
|
+
return blocks
|
|
15
|
+
.filter(block => block.type === 'text')
|
|
16
|
+
.map(block => block.text)
|
|
17
|
+
.join('');
|
|
18
|
+
}
|
|
19
|
+
/** Reject core image content before any text-flattening path can silently erase it. */
|
|
20
|
+
function assertTextOnly(blocks) {
|
|
21
|
+
if (contentHasImage(blocks)) {
|
|
22
|
+
throw new LlmError('The Ollama adapter does not support image content.', 'UNSUPPORTED_CONTENT');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parse a tool-call argument string into the object Ollama expects. The raw
|
|
27
|
+
* string is guaranteed by the harness contract to be JSON; a malformed value
|
|
28
|
+
* from a hand-built call degrades to a single `value` field rather than
|
|
29
|
+
* bricking the whole session.
|
|
30
|
+
* @param raw - the raw JSON string produced by the model.
|
|
31
|
+
* @returns the parsed object, or a `{ value }` fallback.
|
|
32
|
+
*/
|
|
33
|
+
export function parseToolArguments(raw) {
|
|
34
|
+
try {
|
|
35
|
+
const parsed = JSON.parse(raw);
|
|
36
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
37
|
+
return parsed;
|
|
38
|
+
}
|
|
39
|
+
return { value: raw };
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return { value: raw };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Serialize one assistant message (text + tool calls). */
|
|
46
|
+
function serializeAssistant(message) {
|
|
47
|
+
const text = flattenText(message.content);
|
|
48
|
+
const toolCalls = message.content
|
|
49
|
+
.filter(block => block.type === 'tool-call')
|
|
50
|
+
.map(block => ({
|
|
51
|
+
function: { name: block.name, arguments: parseToolArguments(block.arguments) },
|
|
52
|
+
}));
|
|
53
|
+
return {
|
|
54
|
+
role: 'assistant',
|
|
55
|
+
content: text,
|
|
56
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Resolve a tool-result block's name from the assistant tool calls that precede it. */
|
|
60
|
+
function toolNameOf(callId, namesByCallId) {
|
|
61
|
+
return namesByCallId.get(callId);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Serialize the conversation. `tool-result` blocks become standalone
|
|
65
|
+
* `{role: 'tool'}` messages; the harness puts each tool result in its own
|
|
66
|
+
* user-role message, so a mixed user message contributes its text first and
|
|
67
|
+
* its tool results as separate wire messages after. Assistant tool calls are
|
|
68
|
+
* indexed first so their results can carry the tool name Ollama needs.
|
|
69
|
+
* @param messages - the harness conversation, in order.
|
|
70
|
+
* @returns the wire messages; order preserved, each tool result expanded into its own entry.
|
|
71
|
+
*/
|
|
72
|
+
export function serializeMessages(messages) {
|
|
73
|
+
const namesByCallId = new Map();
|
|
74
|
+
for (const message of messages) {
|
|
75
|
+
if (message.role !== 'assistant')
|
|
76
|
+
continue;
|
|
77
|
+
for (const block of message.content) {
|
|
78
|
+
if (block.type === 'tool-call')
|
|
79
|
+
namesByCallId.set(String(block.id), block.name);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const wire = [];
|
|
83
|
+
for (const message of messages) {
|
|
84
|
+
assertTextOnly(message.content);
|
|
85
|
+
if (message.role === 'system') {
|
|
86
|
+
wire.push({ role: 'system', content: flattenText(message.content) });
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (message.role === 'assistant') {
|
|
90
|
+
wire.push(serializeAssistant(message));
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
// user role: tool results ride in user messages in the harness
|
|
94
|
+
// vocabulary, but Ollama wants them as role:'tool' messages.
|
|
95
|
+
const toolResults = message.content.filter(block => block.type === 'tool-result');
|
|
96
|
+
const text = flattenText(message.content);
|
|
97
|
+
if (text.length > 0 || toolResults.length === 0) {
|
|
98
|
+
wire.push({ role: 'user', content: text });
|
|
99
|
+
}
|
|
100
|
+
for (const result of toolResults) {
|
|
101
|
+
const name = toolNameOf(String(result.toolCallId), namesByCallId);
|
|
102
|
+
wire.push({
|
|
103
|
+
role: 'tool',
|
|
104
|
+
// Empty tool output still needs SOME content on the wire.
|
|
105
|
+
content: flattenText(result.content) || '(no output)',
|
|
106
|
+
...name === undefined ? {} : { tool_name: name },
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return wire;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Build the full wire request. Always streaming (`stream: true`); optional
|
|
114
|
+
* fields are omitted rather than sent as null, so Ollama defaults apply.
|
|
115
|
+
* `temperature` resolves request → model mapping → plugin default; `num_predict`
|
|
116
|
+
* is the harness-materialized `maxTokens`.
|
|
117
|
+
* @param options - the harness request (model, history, system, tools, sampling).
|
|
118
|
+
* @param resolved - the resolved plugin config.
|
|
119
|
+
* @returns the `/api/chat` request body.
|
|
120
|
+
*/
|
|
121
|
+
export function serializeRequest(options, resolved) {
|
|
122
|
+
const mapping = resolved.models.find(entry => entry.name === options.model);
|
|
123
|
+
const model = mapping?.model ?? options.model;
|
|
124
|
+
const messages = [];
|
|
125
|
+
if (options.system !== undefined) {
|
|
126
|
+
messages.push({ role: 'system', content: options.system });
|
|
127
|
+
}
|
|
128
|
+
messages.push(...serializeMessages(options.messages));
|
|
129
|
+
const temperature = options.temperature ?? mapping?.temperature ?? resolved.temperature;
|
|
130
|
+
const ollamaOptions = {};
|
|
131
|
+
if (temperature !== undefined)
|
|
132
|
+
ollamaOptions.temperature = temperature;
|
|
133
|
+
if (options.maxTokens !== undefined)
|
|
134
|
+
ollamaOptions.num_predict = options.maxTokens;
|
|
135
|
+
if (options.stop !== undefined && options.stop.length > 0)
|
|
136
|
+
ollamaOptions.stop = options.stop;
|
|
137
|
+
const tools = options.tools?.map(tool => ({
|
|
138
|
+
type: 'function',
|
|
139
|
+
function: tool,
|
|
140
|
+
}));
|
|
141
|
+
return {
|
|
142
|
+
model,
|
|
143
|
+
messages,
|
|
144
|
+
stream: true,
|
|
145
|
+
...Object.keys(ollamaOptions).length > 0 ? { options: ollamaOptions } : {},
|
|
146
|
+
...tools !== undefined && tools.length > 0 ? { tools } : {},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=serialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../src/serialize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate Ollama NDJSON chat chunks into the harness `StreamChunk` protocol.
|
|
3
|
+
* Ollama streams one JSON object per line: `message.content` and
|
|
4
|
+
* `message.thinking` are incremental deltas, while `message.tool_calls`
|
|
5
|
+
* carries the CUMULATIVE arguments object, so tool-call deltas are computed by
|
|
6
|
+
* longest-common-prefix diffing. Usage and the finish reason are deferred to
|
|
7
|
+
* the `done: true` chunk, guaranteeing no chunk follows `finish`.
|
|
8
|
+
* @module dsh-local-ai/translate
|
|
9
|
+
*/
|
|
10
|
+
import type { FinishReason, StreamChunk } from '@deepseek-ai/dsh-llm';
|
|
11
|
+
/** One Ollama streaming chat chunk on the wire. */
|
|
12
|
+
export interface OllamaWireChunk {
|
|
13
|
+
model?: string;
|
|
14
|
+
message?: {
|
|
15
|
+
role?: string;
|
|
16
|
+
content?: string;
|
|
17
|
+
thinking?: string;
|
|
18
|
+
tool_calls?: Array<{
|
|
19
|
+
function?: {
|
|
20
|
+
name?: string;
|
|
21
|
+
arguments?: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
24
|
+
};
|
|
25
|
+
done?: boolean;
|
|
26
|
+
done_reason?: string;
|
|
27
|
+
prompt_eval_count?: number;
|
|
28
|
+
eval_count?: number;
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Map the Ollama `done_reason` vocabulary to the harness FinishReason.
|
|
33
|
+
* @param reason - the wire `done_reason` string.
|
|
34
|
+
* @returns the mapped reason; unrecognized values become `{kind: 'error'}`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function mapFinishReason(reason: string): FinishReason;
|
|
37
|
+
/**
|
|
38
|
+
* Compute the append delta from a cumulative JSON string, so the harness's
|
|
39
|
+
* delta-concatenating assembler reconstructs the full arguments. Ollama grows
|
|
40
|
+
* the arguments object monotonically, so the delta is everything past the
|
|
41
|
+
* longest common prefix with the previously seen string.
|
|
42
|
+
* @param previous - the previously seen cumulative JSON (or `''`).
|
|
43
|
+
* @param next - the new cumulative JSON.
|
|
44
|
+
* @returns the fragment to append.
|
|
45
|
+
*/
|
|
46
|
+
export declare function argumentsDelta(previous: string, next: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Consume Ollama NDJSON lines and yield StreamChunks. Text and reasoning deltas
|
|
49
|
+
* stream as they arrive; tool-call deltas are diffed from the cumulative wire
|
|
50
|
+
* arguments; `block-end`, `usage`, and `finish` are deferred to the `done`
|
|
51
|
+
* chunk. A `stop` finish with no opened blocks maps to an `EMPTY_RESPONSE`
|
|
52
|
+
* error finish.
|
|
53
|
+
* @param lines - newline-delimited Ollama chat payloads.
|
|
54
|
+
* @returns deltas as they arrive; `block-end`s, `usage`, and `finish` deferred to `done`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function translate(lines: AsyncIterable<string>): AsyncGenerator<StreamChunk>;
|
|
57
|
+
//# sourceMappingURL=translate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/translate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAgB,YAAY,EAAE,WAAW,EAAc,MAAM,sBAAsB,CAAA;AAE/F,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,KAAK,CAAC;YAAE,QAAQ,CAAC,EAAE;gBAAE,IAAI,CAAC,EAAE,MAAM,CAAC;gBAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;aAAE,CAAA;SAAE,CAAC,CAAA;KAC1F,CAAA;IACD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAYD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAW5D;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrE;AAED;;;;;;;;GAQG;AACH,wBAAuB,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,cAAc,CAAC,WAAW,CAAC,CA4G1F"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate Ollama NDJSON chat chunks into the harness `StreamChunk` protocol.
|
|
3
|
+
* Ollama streams one JSON object per line: `message.content` and
|
|
4
|
+
* `message.thinking` are incremental deltas, while `message.tool_calls`
|
|
5
|
+
* carries the CUMULATIVE arguments object, so tool-call deltas are computed by
|
|
6
|
+
* longest-common-prefix diffing. Usage and the finish reason are deferred to
|
|
7
|
+
* the `done: true` chunk, guaranteeing no chunk follows `finish`.
|
|
8
|
+
* @module dsh-local-ai/translate
|
|
9
|
+
*/
|
|
10
|
+
import { CallId, EMPTY_RESPONSE_CODE, LlmError } from '@deepseek-ai/dsh-llm';
|
|
11
|
+
/**
|
|
12
|
+
* Map the Ollama `done_reason` vocabulary to the harness FinishReason.
|
|
13
|
+
* @param reason - the wire `done_reason` string.
|
|
14
|
+
* @returns the mapped reason; unrecognized values become `{kind: 'error'}`.
|
|
15
|
+
*/
|
|
16
|
+
export function mapFinishReason(reason) {
|
|
17
|
+
switch (reason) {
|
|
18
|
+
case 'stop': return { kind: 'stop' };
|
|
19
|
+
case 'tool_calls': return { kind: 'tool-calls' };
|
|
20
|
+
case 'length': return { kind: 'max-tokens' };
|
|
21
|
+
default:
|
|
22
|
+
return {
|
|
23
|
+
kind: 'error',
|
|
24
|
+
failure: { message: `model stopped: ${reason}`, code: reason.toUpperCase() },
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Assemble the final ContentBlock for one open block. */
|
|
29
|
+
function closeBlock(block) {
|
|
30
|
+
switch (block.kind) {
|
|
31
|
+
case 'text': return { type: 'text', text: block.text };
|
|
32
|
+
case 'reasoning': return { type: 'reasoning', text: block.text };
|
|
33
|
+
case 'tool-call': return {
|
|
34
|
+
type: 'tool-call',
|
|
35
|
+
id: CallId(block.callId ?? ''),
|
|
36
|
+
name: block.name ?? '',
|
|
37
|
+
arguments: block.text,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Compute the append delta from a cumulative JSON string, so the harness's
|
|
43
|
+
* delta-concatenating assembler reconstructs the full arguments. Ollama grows
|
|
44
|
+
* the arguments object monotonically, so the delta is everything past the
|
|
45
|
+
* longest common prefix with the previously seen string.
|
|
46
|
+
* @param previous - the previously seen cumulative JSON (or `''`).
|
|
47
|
+
* @param next - the new cumulative JSON.
|
|
48
|
+
* @returns the fragment to append.
|
|
49
|
+
*/
|
|
50
|
+
export function argumentsDelta(previous, next) {
|
|
51
|
+
if (next.startsWith(previous))
|
|
52
|
+
return next.slice(previous.length);
|
|
53
|
+
let index = 0;
|
|
54
|
+
while (index < previous.length && index < next.length && previous[index] === next[index])
|
|
55
|
+
index += 1;
|
|
56
|
+
return next.slice(index);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Consume Ollama NDJSON lines and yield StreamChunks. Text and reasoning deltas
|
|
60
|
+
* stream as they arrive; tool-call deltas are diffed from the cumulative wire
|
|
61
|
+
* arguments; `block-end`, `usage`, and `finish` are deferred to the `done`
|
|
62
|
+
* chunk. A `stop` finish with no opened blocks maps to an `EMPTY_RESPONSE`
|
|
63
|
+
* error finish.
|
|
64
|
+
* @param lines - newline-delimited Ollama chat payloads.
|
|
65
|
+
* @returns deltas as they arrive; `block-end`s, `usage`, and `finish` deferred to `done`.
|
|
66
|
+
*/
|
|
67
|
+
export async function* translate(lines) {
|
|
68
|
+
let nextIndex = 0;
|
|
69
|
+
let textBlock;
|
|
70
|
+
let reasoningBlock;
|
|
71
|
+
const toolBlocks = new Map();
|
|
72
|
+
const toolArguments = new Map();
|
|
73
|
+
const order = [];
|
|
74
|
+
function open(kind) {
|
|
75
|
+
const block = { index: nextIndex++, kind, text: '' };
|
|
76
|
+
order.push(block);
|
|
77
|
+
return block;
|
|
78
|
+
}
|
|
79
|
+
for await (const line of lines) {
|
|
80
|
+
if (line.length === 0)
|
|
81
|
+
continue;
|
|
82
|
+
let chunk;
|
|
83
|
+
try {
|
|
84
|
+
chunk = JSON.parse(line);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
throw new LlmError(`malformed Ollama NDJSON payload: ${line.slice(0, 120)}`, 'MALFORMED_RESPONSE');
|
|
88
|
+
}
|
|
89
|
+
if (typeof chunk.error === 'string' && chunk.error.length > 0) {
|
|
90
|
+
throw new LlmError(chunk.error, 'PROVIDER');
|
|
91
|
+
}
|
|
92
|
+
const message = chunk.message;
|
|
93
|
+
if (message !== undefined) {
|
|
94
|
+
const reasoning = message.thinking;
|
|
95
|
+
if (typeof reasoning === 'string' && reasoning.length > 0) {
|
|
96
|
+
if (!reasoningBlock) {
|
|
97
|
+
reasoningBlock = open('reasoning');
|
|
98
|
+
yield { type: 'block-start', index: reasoningBlock.index, blockType: 'reasoning' };
|
|
99
|
+
}
|
|
100
|
+
reasoningBlock.text += reasoning;
|
|
101
|
+
yield { type: 'reasoning-delta', index: reasoningBlock.index, text: reasoning };
|
|
102
|
+
}
|
|
103
|
+
const content = message.content;
|
|
104
|
+
if (typeof content === 'string' && content.length > 0) {
|
|
105
|
+
if (!textBlock) {
|
|
106
|
+
textBlock = open('text');
|
|
107
|
+
yield { type: 'block-start', index: textBlock.index, blockType: 'text' };
|
|
108
|
+
}
|
|
109
|
+
textBlock.text += content;
|
|
110
|
+
yield { type: 'text-delta', index: textBlock.index, text: content };
|
|
111
|
+
}
|
|
112
|
+
const toolCalls = message.tool_calls ?? [];
|
|
113
|
+
for (let callIndex = 0; callIndex < toolCalls.length; callIndex++) {
|
|
114
|
+
const call = toolCalls[callIndex];
|
|
115
|
+
let block = toolBlocks.get(callIndex);
|
|
116
|
+
if (!block) {
|
|
117
|
+
block = open('tool-call');
|
|
118
|
+
toolBlocks.set(callIndex, block);
|
|
119
|
+
toolArguments.set(callIndex, '');
|
|
120
|
+
yield { type: 'block-start', index: block.index, blockType: 'tool-call' };
|
|
121
|
+
}
|
|
122
|
+
if (call?.function?.name !== undefined && block.name === undefined) {
|
|
123
|
+
block.name = call.function.name;
|
|
124
|
+
}
|
|
125
|
+
const cumulative = JSON.stringify(call?.function?.arguments ?? {});
|
|
126
|
+
const previous = toolArguments.get(callIndex) ?? '';
|
|
127
|
+
if (cumulative !== previous) {
|
|
128
|
+
const fragment = argumentsDelta(previous, cumulative);
|
|
129
|
+
toolArguments.set(callIndex, cumulative);
|
|
130
|
+
block.text += fragment;
|
|
131
|
+
yield {
|
|
132
|
+
type: 'tool-call-delta',
|
|
133
|
+
index: block.index,
|
|
134
|
+
id: CallId(block.callId ?? ''),
|
|
135
|
+
...block.name !== undefined ? { name: block.name } : {},
|
|
136
|
+
argumentsDelta: fragment,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (chunk.done === true) {
|
|
142
|
+
for (const block of order) {
|
|
143
|
+
yield { type: 'block-end', index: block.index, block: closeBlock(block) };
|
|
144
|
+
}
|
|
145
|
+
const promptCount = chunk.prompt_eval_count;
|
|
146
|
+
const evalCount = chunk.eval_count;
|
|
147
|
+
if (promptCount !== undefined || evalCount !== undefined) {
|
|
148
|
+
const usage = {
|
|
149
|
+
inputTokens: promptCount ?? 0,
|
|
150
|
+
outputTokens: evalCount ?? 0,
|
|
151
|
+
};
|
|
152
|
+
yield { type: 'usage', usage };
|
|
153
|
+
}
|
|
154
|
+
const reason = mapFinishReason(chunk.done_reason ?? 'stop');
|
|
155
|
+
yield {
|
|
156
|
+
type: 'finish',
|
|
157
|
+
reason: reason.kind === 'stop' && order.length === 0
|
|
158
|
+
? {
|
|
159
|
+
kind: 'error',
|
|
160
|
+
failure: { message: 'model returned a completed response with no content', code: EMPTY_RESPONSE_CODE },
|
|
161
|
+
}
|
|
162
|
+
: reason,
|
|
163
|
+
};
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
throw new LlmError('Ollama NDJSON stream ended without a done chunk', 'STREAM_CLOSED');
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=translate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/translate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,OAAO,UAAU,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-local-ai",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Local-model (Ollama) integration for DeepSeek Harness: discover, pull, remove, and inspect local models, route requests to them by task type or keyword with automatic fallback to the cloud, and get a one-shot status overview via /ollama.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/PerryLink/dsh-local-ai.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/PerryLink/dsh-local-ai#readme",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/PerryLink/dsh-local-ai/issues"
|
|
12
|
+
},
|
|
13
|
+
"author": "PerryLink",
|
|
14
|
+
"private": false,
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./lib/index.js",
|
|
17
|
+
"types": "./lib/types/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./lib/types/index.d.ts",
|
|
21
|
+
"default": "./lib/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"lib",
|
|
27
|
+
"src",
|
|
28
|
+
"cordis.patch.yml",
|
|
29
|
+
"CHANGELOG.md",
|
|
30
|
+
"THIRD_PARTY_NOTICES.md",
|
|
31
|
+
"README.md",
|
|
32
|
+
"README.zh.md",
|
|
33
|
+
"README.es.md",
|
|
34
|
+
"README.pt.md",
|
|
35
|
+
"README.hi.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"sideEffects": false,
|
|
39
|
+
"dsh": {
|
|
40
|
+
"bundle": {
|
|
41
|
+
"patch": "./cordis.patch.yml"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"dshWorkshop": {
|
|
45
|
+
"schema": "omdsh-workshop-package/v1",
|
|
46
|
+
"type": "plugin",
|
|
47
|
+
"integration": {
|
|
48
|
+
"protocol": "harness-profile",
|
|
49
|
+
"artifact": "cordis.patch.yml"
|
|
50
|
+
},
|
|
51
|
+
"install": {
|
|
52
|
+
"mode": "transactional",
|
|
53
|
+
"adapter": "profile-bundle",
|
|
54
|
+
"failurePolicy": "generation-rollback",
|
|
55
|
+
"touchesCurrentBeforeActivation": false
|
|
56
|
+
},
|
|
57
|
+
"lifecycle": {
|
|
58
|
+
"activation": "restart-profile",
|
|
59
|
+
"dispose": "supported"
|
|
60
|
+
},
|
|
61
|
+
"permissions": [
|
|
62
|
+
"network:outbound",
|
|
63
|
+
"native-code:none"
|
|
64
|
+
],
|
|
65
|
+
"compatibility": {
|
|
66
|
+
"dshVersions": [
|
|
67
|
+
"0.1.0-rc.6"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"capability": {
|
|
71
|
+
"id": "local-ai",
|
|
72
|
+
"kind": "service",
|
|
73
|
+
"invocation": "mount the dsh-local-ai bundle row",
|
|
74
|
+
"expected": "registers the Ollama LlmAdapter route, exposes ollama_list/pull/remove/show tools plus a health check, routes requests to local models by rule, and provides the /ollama command"
|
|
75
|
+
},
|
|
76
|
+
"evidence": {
|
|
77
|
+
"install": null,
|
|
78
|
+
"failureIsolation": null,
|
|
79
|
+
"hotReload": null,
|
|
80
|
+
"remove": null
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"keywords": [
|
|
84
|
+
"dsh",
|
|
85
|
+
"dsh-plugin",
|
|
86
|
+
"deepseek-harness",
|
|
87
|
+
"deepseek",
|
|
88
|
+
"cordis",
|
|
89
|
+
"ollama",
|
|
90
|
+
"local-llm",
|
|
91
|
+
"local-models",
|
|
92
|
+
"offline",
|
|
93
|
+
"privacy",
|
|
94
|
+
"model-routing"
|
|
95
|
+
],
|
|
96
|
+
"engines": {
|
|
97
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
98
|
+
},
|
|
99
|
+
"packageManager": "pnpm@11.7.0",
|
|
100
|
+
"peerDependencies": {
|
|
101
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
102
|
+
"@deepseek-ai/schemastery": "^3.18.0",
|
|
103
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.6",
|
|
104
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.6",
|
|
105
|
+
"@deepseek-ai/dsh-subprocess": "0.1.0-rc.6",
|
|
106
|
+
"@deepseek-ai/dsh-commands": "0.1.0-rc.6",
|
|
107
|
+
"@deepseek-ai/dsh-timeout": "0.1.0-rc.6"
|
|
108
|
+
},
|
|
109
|
+
"dependencies": {
|
|
110
|
+
"tsdown": "^0.22.14",
|
|
111
|
+
"typescript": "^5.9.0"
|
|
112
|
+
},
|
|
113
|
+
"devDependencies": {
|
|
114
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
115
|
+
"@deepseek-ai/schemastery": "^3.18.0",
|
|
116
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.6",
|
|
117
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.6",
|
|
118
|
+
"@deepseek-ai/dsh-subprocess": "0.1.0-rc.6",
|
|
119
|
+
"@deepseek-ai/dsh-subprocess-local": "0.1.0-rc.6",
|
|
120
|
+
"@deepseek-ai/dsh-commands": "0.1.0-rc.6",
|
|
121
|
+
"@deepseek-ai/dsh-timeout": "0.1.0-rc.6",
|
|
122
|
+
"@deepseek-ai/dsh-session": "0.1.0-rc.6",
|
|
123
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.0-rc.6",
|
|
124
|
+
"@types/node": "^22.19.0",
|
|
125
|
+
"@vitest/coverage-v8": "^3.2.0",
|
|
126
|
+
"vitest": "^3.2.0"
|
|
127
|
+
},
|
|
128
|
+
"scripts": {
|
|
129
|
+
"build": "node scripts/prepare.mjs",
|
|
130
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
131
|
+
"typecheck:ci": "tsc -p tsconfig.ci.json --noEmit",
|
|
132
|
+
"test": "vitest run",
|
|
133
|
+
"test:coverage": "vitest run --coverage",
|
|
134
|
+
"prepare": "node scripts/prepare.mjs",
|
|
135
|
+
"verify:self-contained": "node scripts/verify-self-contained.mjs",
|
|
136
|
+
"verify:artifacts": "node scripts/verify-artifacts.mjs",
|
|
137
|
+
"verify:readme-sync": "node scripts/check-readme-sync.mjs",
|
|
138
|
+
"pack:check": "node scripts/prepare.mjs && pnpm pack"
|
|
139
|
+
},
|
|
140
|
+
"license": "Apache-2.0"
|
|
141
|
+
}
|