archbyte 0.2.9 → 0.3.1

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.
@@ -1,162 +0,0 @@
1
- export class OllamaProvider {
2
- name = "ollama";
3
- baseUrl;
4
- constructor(baseUrl = "http://localhost:11434") {
5
- this.baseUrl = baseUrl.replace(/\/$/, "");
6
- }
7
- async chat(params) {
8
- const messages = [
9
- { role: "system", content: params.system },
10
- ...params.messages.map((m) => this.toOllamaMessage(m)),
11
- ];
12
- const body = {
13
- model: params.model,
14
- messages,
15
- stream: false,
16
- };
17
- if (params.tools?.length) {
18
- body.tools = params.tools.map((t) => ({
19
- type: "function",
20
- function: {
21
- name: t.name,
22
- description: t.description,
23
- parameters: t.input_schema,
24
- },
25
- }));
26
- }
27
- const response = await fetch(`${this.baseUrl}/api/chat`, {
28
- method: "POST",
29
- headers: { "Content-Type": "application/json" },
30
- body: JSON.stringify(body),
31
- });
32
- if (!response.ok) {
33
- const text = await response.text();
34
- throw new Error(`Ollama error ${response.status}: ${text}`);
35
- }
36
- const data = (await response.json());
37
- const content = [];
38
- if (data.message.content) {
39
- content.push({ type: "text", text: data.message.content });
40
- }
41
- let hasToolCalls = false;
42
- if (data.message.tool_calls) {
43
- hasToolCalls = true;
44
- for (const tc of data.message.tool_calls) {
45
- content.push({
46
- type: "tool_use",
47
- id: tc.id ?? `call_${Date.now()}`,
48
- name: tc.function.name,
49
- input: JSON.parse(tc.function.arguments),
50
- });
51
- }
52
- }
53
- return {
54
- content,
55
- stopReason: hasToolCalls ? "tool_use" : "end_turn",
56
- usage: {
57
- inputTokens: data.prompt_eval_count ?? 0,
58
- outputTokens: data.eval_count ?? 0,
59
- },
60
- };
61
- }
62
- async *stream(params) {
63
- const messages = [
64
- { role: "system", content: params.system },
65
- ...params.messages.map((m) => this.toOllamaMessage(m)),
66
- ];
67
- const body = {
68
- model: params.model,
69
- messages,
70
- stream: true,
71
- };
72
- if (params.tools?.length) {
73
- body.tools = params.tools.map((t) => ({
74
- type: "function",
75
- function: {
76
- name: t.name,
77
- description: t.description,
78
- parameters: t.input_schema,
79
- },
80
- }));
81
- }
82
- const response = await fetch(`${this.baseUrl}/api/chat`, {
83
- method: "POST",
84
- headers: { "Content-Type": "application/json" },
85
- body: JSON.stringify(body),
86
- });
87
- if (!response.ok) {
88
- const text = await response.text();
89
- throw new Error(`Ollama error ${response.status}: ${text}`);
90
- }
91
- const reader = response.body?.getReader();
92
- if (!reader)
93
- throw new Error("No response body");
94
- const decoder = new TextDecoder();
95
- let buffer = "";
96
- while (true) {
97
- const { done, value } = await reader.read();
98
- if (done)
99
- break;
100
- buffer += decoder.decode(value, { stream: true });
101
- const lines = buffer.split("\n");
102
- buffer = lines.pop() ?? "";
103
- for (const line of lines) {
104
- if (!line.trim())
105
- continue;
106
- const data = JSON.parse(line);
107
- if (data.message?.content) {
108
- yield { type: "text", text: data.message.content };
109
- }
110
- if (data.message?.tool_calls) {
111
- for (const tc of data.message.tool_calls) {
112
- yield {
113
- type: "tool_use_start",
114
- toolName: tc.function.name,
115
- toolId: tc.id ?? `call_${Date.now()}`,
116
- };
117
- yield { type: "tool_use_input", input: tc.function.arguments };
118
- }
119
- }
120
- if (data.done) {
121
- yield { type: "done" };
122
- }
123
- }
124
- }
125
- }
126
- toOllamaMessage(m) {
127
- if (typeof m.content === "string") {
128
- return { role: m.role, content: m.content };
129
- }
130
- const toolResults = m.content.filter((b) => b.type === "tool_result");
131
- if (toolResults.length > 0) {
132
- return {
133
- role: "tool",
134
- content: toolResults[0].content ?? "",
135
- tool_call_id: toolResults[0].tool_use_id,
136
- };
137
- }
138
- const toolUses = m.content.filter((b) => b.type === "tool_use");
139
- if (toolUses.length > 0) {
140
- const text = m.content
141
- .filter((b) => b.type === "text")
142
- .map((b) => b.text ?? "")
143
- .join("");
144
- return {
145
- role: "assistant",
146
- content: text,
147
- tool_calls: toolUses.map((b) => ({
148
- id: b.id ?? "",
149
- type: "function",
150
- function: {
151
- name: b.name ?? "",
152
- arguments: JSON.stringify(b.input ?? {}),
153
- },
154
- })),
155
- };
156
- }
157
- return {
158
- role: m.role,
159
- content: m.content.map((b) => b.text ?? "").join(""),
160
- };
161
- }
162
- }