musonda 1.0.8 → 1.0.9

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 (71) hide show
  1. package/README.md +44 -5
  2. package/dist/agent/chatCompletionsClient.d.ts +56 -0
  3. package/dist/agent/chatCompletionsClient.js +345 -0
  4. package/dist/agent/chatCompletionsClient.js.map +1 -0
  5. package/dist/agent/harness.d.ts +6 -3
  6. package/dist/agent/harness.js +93 -20
  7. package/dist/agent/harness.js.map +1 -1
  8. package/dist/agent/modelFactory.d.ts +13 -0
  9. package/dist/agent/modelFactory.js +65 -0
  10. package/dist/agent/modelFactory.js.map +1 -0
  11. package/dist/agent/modelTypes.d.ts +46 -0
  12. package/dist/agent/modelTypes.js +2 -0
  13. package/dist/agent/modelTypes.js.map +1 -0
  14. package/dist/agent/openaiResponsesClient.d.ts +7 -11
  15. package/dist/agent/openaiResponsesClient.js +48 -0
  16. package/dist/agent/openaiResponsesClient.js.map +1 -1
  17. package/dist/agent/systemPrompt.js +1 -1
  18. package/dist/agent/systemPrompt.js.map +1 -1
  19. package/dist/cli/commands/connect.d.ts +1 -0
  20. package/dist/cli/commands/connect.js +17 -2
  21. package/dist/cli/commands/connect.js.map +1 -1
  22. package/dist/cli/commands/doctor.js +45 -5
  23. package/dist/cli/commands/doctor.js.map +1 -1
  24. package/dist/cli/commands/help.js +73 -2
  25. package/dist/cli/commands/help.js.map +1 -1
  26. package/dist/cli/commands/langfuse.d.ts +18 -0
  27. package/dist/cli/commands/langfuse.js +139 -0
  28. package/dist/cli/commands/langfuse.js.map +1 -0
  29. package/dist/cli/commands/model.d.ts +38 -0
  30. package/dist/cli/commands/model.js +446 -0
  31. package/dist/cli/commands/model.js.map +1 -0
  32. package/dist/cli/commands/status.js +6 -2
  33. package/dist/cli/commands/status.js.map +1 -1
  34. package/dist/cli/interactiveMenu.js +18 -4
  35. package/dist/cli/interactiveMenu.js.map +1 -1
  36. package/dist/cli/musondaCli.d.ts +9 -0
  37. package/dist/cli/musondaCli.js +124 -1
  38. package/dist/cli/musondaCli.js.map +1 -1
  39. package/dist/cli.js +1 -1
  40. package/dist/cli.js.map +1 -1
  41. package/dist/config/loader.js +89 -15
  42. package/dist/config/loader.js.map +1 -1
  43. package/dist/config/types.d.ts +35 -4
  44. package/dist/config/types.js +26 -3
  45. package/dist/config/types.js.map +1 -1
  46. package/dist/gateway/channels/cli.js +3 -2
  47. package/dist/gateway/channels/cli.js.map +1 -1
  48. package/dist/gateway/channels/discord.js +4 -0
  49. package/dist/gateway/channels/discord.js.map +1 -1
  50. package/dist/gateway/channels/slack.js +39 -17
  51. package/dist/gateway/channels/slack.js.map +1 -1
  52. package/dist/gateway/channels/telegram.js +4 -0
  53. package/dist/gateway/channels/telegram.js.map +1 -1
  54. package/dist/gateway/http.js +20 -7
  55. package/dist/gateway/http.js.map +1 -1
  56. package/dist/gateway/server.d.ts +2 -2
  57. package/dist/gateway/server.js +24 -3
  58. package/dist/gateway/server.js.map +1 -1
  59. package/dist/index.d.ts +1 -0
  60. package/dist/index.js +1 -0
  61. package/dist/index.js.map +1 -1
  62. package/dist/observability/langfuse.d.ts +91 -0
  63. package/dist/observability/langfuse.js +247 -0
  64. package/dist/observability/langfuse.js.map +1 -0
  65. package/dist/tools/registry.d.ts +2 -0
  66. package/dist/tools/registry.js +4 -0
  67. package/dist/tools/registry.js.map +1 -1
  68. package/dist/wizard/onboarding.d.ts +1 -1
  69. package/dist/wizard/onboarding.js +92 -20
  70. package/dist/wizard/onboarding.js.map +1 -1
  71. package/package.json +12 -5
package/README.md CHANGED
@@ -50,8 +50,11 @@ or a companion you message on Discord.
50
50
 
51
51
  ## Getting started
52
52
 
53
- You need [Node.js](https://nodejs.org/) 20 or newer and an OpenAI API key.
54
- Discord and Slack are optional—you can start entirely in your terminal.
53
+ You need [Node.js](https://nodejs.org/) 20 or newer and a model API key.
54
+ Musonda is model-agnostic: use OpenAI, Ollama (local, no key), LM Studio,
55
+ OpenRouter, Anthropic, Google, Groq, Mistral, DeepSeek, Together, or any
56
+ OpenAI-compatible endpoint. Discord and Slack are optional—you can start
57
+ entirely in your terminal.
55
58
 
56
59
  ### Quick install (npm)
57
60
 
@@ -154,7 +157,26 @@ Musonda includes a production multi-stage Dockerfile and Docker Compose configur
154
157
  cp .env.example .env
155
158
  ```
156
159
 
157
- 2. Add your OpenAI API key and optional Discord/Slack tokens to `.env`.
160
+ 2. Add your model credentials to `.env` (generic or provider-specific):
161
+
162
+ ```bash
163
+ # Hosted (OpenAI example)
164
+ MODEL_PROVIDER=openai
165
+ MODEL_NAME=gpt-4o-mini
166
+ MODEL_API_KEY=sk-...
167
+
168
+ # Local (Ollama example — no key needed)
169
+ MODEL_PROVIDER=ollama
170
+ MODEL_NAME=llama3.1
171
+ MODEL_BASE_URL=http://localhost:11434/v1
172
+ ```
173
+
174
+ Or configure interactively at any time:
175
+
176
+ ```bash
177
+ musonda model setup
178
+ musonda model use ollama/llama3.1
179
+ ```
158
180
 
159
181
  3. Launch the container:
160
182
 
@@ -199,7 +221,16 @@ conversation.
199
221
  |---|---|
200
222
  | `musonda` | Opens the interactive dashboard and menu |
201
223
  | `musonda setup` | Runs the personal onboarding and channel setup wizard |
224
+ | `musonda model` | Shows current AI model provider and model |
225
+ | `musonda model setup` | Configures AI model provider without onboarding |
226
+ | `musonda model use <provider>/<model>` | Switches provider + model (e.g. `ollama/llama3.1`) |
227
+ | `musonda connect model` | Alias for `musonda model setup` |
228
+ | `musonda connect <provider>` | Sets up a model provider's key (e.g. `deepseek`, `openai`, `ollama`) |
229
+ | `musonda change model <provider>[/<model>]` | Switches active model (provider must be set up first) |
202
230
  | `musonda connect <channel>` | Connects a channel (telegram\|discord\|slack) without onboarding |
231
+ | `musonda connect langfuse` | Connects Langfuse tracing (agent observability) |
232
+ | `musonda disconnect langfuse` | Disables Langfuse tracing (keys are kept) |
233
+ | `musonda langfuse status` | Shows Langfuse tracing status |
203
234
  | `musonda disconnect <channel>` | Disables a connected channel (tokens are kept) |
204
235
  | `musonda channels` | Shows channel connection status |
205
236
  | `musonda cli` | Starts an interactive terminal conversation |
@@ -225,8 +256,16 @@ You can also supply environment variables in a `.env` file in your working direc
225
256
 
226
257
  | Environment Variable | Description | Default |
227
258
  |---|---|---|
228
- | `OPENAI_API_KEY` | OpenAI API key for assistant completions | Required |
229
- | `OPENAI_MODEL` | Target language model | `gpt-5.6-luna` |
259
+ | `MODEL_PROVIDER` | Model provider (`openai`, `ollama`, `lmstudio`, `openrouter`, `anthropic`, `google`, `groq`, `mistral`, `deepseek`, `together`, custom) | `openai` |
260
+ | `MODEL_NAME` | Target language model (any provider model name) | `gpt-5.6-luna` |
261
+ | `MODEL_API_KEY` | Provider API key (not needed for `ollama`/`lmstudio`) | |
262
+ | `MODEL_BASE_URL` | Custom OpenAI-compatible base URL | provider default |
263
+ | `MODEL_API` | API dialect: `auto` / `chat` (universal) / `responses` (OpenAI-only) | `auto` |
264
+ | `OPENAI_API_KEY` / `OPENAI_MODEL` / `OPENAI_BASE_URL` | Legacy fallbacks (still supported) | |
265
+ | `ANTHROPIC_API_KEY` / `GOOGLE_API_KEY` / `OPENROUTER_API_KEY` / `GROQ_API_KEY` | Provider-specific keys (auto-detected) | |
266
+ | `LANGFUSE_SECRET_KEY` / `LANGFUSE_PUBLIC_KEY` | Langfuse tracing keys (or use `musonda connect langfuse`) | |
267
+ | `LANGFUSE_BASE_URL` | Langfuse server (Cloud EU default) | `https://cloud.langfuse.com` |
268
+ | `LANGFUSE_ENABLED` | Enable Langfuse tracing (`true`/`1`) | `false` |
230
269
  | `PORT` or `GATEWAY_PORT` | HTTP Gateway listening port | `4141` |
231
270
  | `HOST` or `GATEWAY_HOST` | HTTP Gateway binding address | `127.0.0.1` |
232
271
  | `DISCORD_BOT_TOKEN` | Discord Bot token (optional) | |
@@ -0,0 +1,56 @@
1
+ import { ModelConfig } from '../config/types.js';
2
+ import { OpenAIFunctionToolSchema } from '../tools/types.js';
3
+ import { ModelResponseResult } from './modelTypes.js';
4
+ /**
5
+ * Generic OpenAI-compatible Chat Completions client.
6
+ *
7
+ * Speaks the `/chat/completions` dialect understood by OpenAI itself
8
+ * plus Ollama, LM Studio, vLLM, OpenRouter, Groq, Mistral, DeepSeek,
9
+ * Together, Azure OpenAI, and any other OpenAI-compatible endpoint.
10
+ * This is what makes Musonda model-agnostic: point `baseUrl` at any
11
+ * compatible server and set `model` to any hosted model name.
12
+ */
13
+ export declare class ChatCompletionsClient {
14
+ private client;
15
+ private model;
16
+ private provider;
17
+ private temperature?;
18
+ private maxOutputTokens;
19
+ private readinessCache;
20
+ constructor(config: ModelConfig);
21
+ getModelName(): string;
22
+ getProviderName(): string;
23
+ private withRetry;
24
+ checkReadiness(cacheMs?: number): Promise<{
25
+ ready: boolean;
26
+ reason?: string;
27
+ }>;
28
+ generateImage(params: {
29
+ prompt: string;
30
+ size?: string;
31
+ model?: string;
32
+ quality?: 'standard' | 'hd';
33
+ style?: 'vivid' | 'natural';
34
+ }): Promise<{
35
+ b64_json?: string;
36
+ url?: string;
37
+ revised_prompt?: string;
38
+ }>;
39
+ private supportsTemperature;
40
+ /** Convert Responses-style input items + instructions into Chat Completions messages. */
41
+ private toChatMessages;
42
+ /** Convert Responses content parts (input_text/input_image) to Chat content parts. */
43
+ private toChatContent;
44
+ private toChatTools;
45
+ generate(params: {
46
+ instructions: string;
47
+ input: any[];
48
+ tools?: OpenAIFunctionToolSchema[];
49
+ onDelta?: (delta: string) => void | Promise<void>;
50
+ onReasoningSummaryDelta?: (delta: string) => void | Promise<void>;
51
+ }): Promise<ModelResponseResult>;
52
+ private summarizeInput;
53
+ private doGenerate;
54
+ private isTempError;
55
+ private toProviderError;
56
+ }
@@ -0,0 +1,345 @@
1
+ import OpenAI from 'openai';
2
+ import { logger } from '../utils/logger.js';
3
+ import { langfuseTracer } from '../observability/langfuse.js';
4
+ /**
5
+ * Generic OpenAI-compatible Chat Completions client.
6
+ *
7
+ * Speaks the `/chat/completions` dialect understood by OpenAI itself
8
+ * plus Ollama, LM Studio, vLLM, OpenRouter, Groq, Mistral, DeepSeek,
9
+ * Together, Azure OpenAI, and any other OpenAI-compatible endpoint.
10
+ * This is what makes Musonda model-agnostic: point `baseUrl` at any
11
+ * compatible server and set `model` to any hosted model name.
12
+ */
13
+ export class ChatCompletionsClient {
14
+ client;
15
+ model;
16
+ provider;
17
+ temperature;
18
+ maxOutputTokens;
19
+ readinessCache = null;
20
+ constructor(config) {
21
+ this.model = config.model || 'gpt-4o-mini';
22
+ this.provider = config.provider || 'openai-compatible';
23
+ this.temperature = config.temperature;
24
+ this.maxOutputTokens = config.maxOutputTokens ?? 4096;
25
+ this.client = new OpenAI({
26
+ // Local runtimes (Ollama / LM Studio) typically need no key.
27
+ apiKey: config.apiKey || 'not-needed',
28
+ baseURL: config.baseUrl || undefined,
29
+ });
30
+ }
31
+ getModelName() {
32
+ return this.model;
33
+ }
34
+ getProviderName() {
35
+ return this.provider;
36
+ }
37
+ async withRetry(fn, opts) {
38
+ const tries = opts?.tries ?? 3;
39
+ let lastErr;
40
+ for (let attempt = 1; attempt <= tries; attempt++) {
41
+ try {
42
+ return await fn();
43
+ }
44
+ catch (err) {
45
+ lastErr = err;
46
+ const status = err?.status;
47
+ const retryable = status === 429 || (typeof status === 'number' && status >= 500) || status === undefined;
48
+ if (!retryable || attempt === tries)
49
+ throw err;
50
+ const retryAfter = Number(err?.headers?.['retry-after']);
51
+ const base = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1000 : 1000 * 2 ** (attempt - 1);
52
+ const delay = Math.min(base + Math.floor(Math.random() * 500), 10000);
53
+ logger.debug(`Model ${opts?.label || 'request'} transient failure (attempt ${attempt}/${tries}, status ${status}). Retrying in ${delay}ms...`);
54
+ await new Promise((r) => setTimeout(r, delay));
55
+ }
56
+ }
57
+ throw lastErr;
58
+ }
59
+ async checkReadiness(cacheMs = 30000) {
60
+ const now = Date.now();
61
+ if (this.readinessCache && now - this.readinessCache.checkedAt < cacheMs) {
62
+ return { ready: this.readinessCache.ready, reason: this.readinessCache.reason };
63
+ }
64
+ try {
65
+ await this.client.models.retrieve(this.model, { timeout: 4000, maxRetries: 0 });
66
+ this.readinessCache = { checkedAt: now, ready: true };
67
+ }
68
+ catch (err) {
69
+ // Local providers (Ollama/LM Studio) often lack a /models/:id endpoint.
70
+ // Fall back to listing models and checking reachability.
71
+ try {
72
+ await this.client.models.list({ timeout: 4000, maxRetries: 0 });
73
+ this.readinessCache = { checkedAt: now, ready: true };
74
+ }
75
+ catch (inner) {
76
+ const reason = inner?.status === 401 || inner?.status === 403
77
+ ? 'credentials_rejected'
78
+ : inner?.status === 404
79
+ ? 'model_unavailable'
80
+ : 'provider_unreachable';
81
+ this.readinessCache = { checkedAt: now, ready: false, reason };
82
+ }
83
+ }
84
+ return { ready: this.readinessCache.ready, reason: this.readinessCache.reason };
85
+ }
86
+ async generateImage(params) {
87
+ try {
88
+ const response = await this.client.images.generate({
89
+ model: params.model || 'dall-e-3',
90
+ prompt: params.prompt,
91
+ n: 1,
92
+ size: params.size || '1024x1024',
93
+ response_format: 'b64_json',
94
+ quality: params.quality,
95
+ style: params.style,
96
+ });
97
+ const item = response.data?.[0];
98
+ return { b64_json: item?.b64_json, url: item?.url, revised_prompt: item?.revised_prompt };
99
+ }
100
+ catch (err) {
101
+ logger.debug(`Image generation unavailable on provider "${this.provider}" (${this.model}):`, err.message || err);
102
+ throw err;
103
+ }
104
+ }
105
+ supportsTemperature(model) {
106
+ const m = model.toLowerCase();
107
+ if (m.startsWith('gpt-5') || m.startsWith('o1') || m.startsWith('o3') || m.startsWith('o4'))
108
+ return false;
109
+ return true;
110
+ }
111
+ /** Convert Responses-style input items + instructions into Chat Completions messages. */
112
+ toChatMessages(instructions, input) {
113
+ const messages = [{ role: 'system', content: instructions }];
114
+ for (const item of input || []) {
115
+ if (!item || typeof item !== 'object')
116
+ continue;
117
+ if (item.type === 'function_call') {
118
+ messages.push({
119
+ role: 'assistant',
120
+ content: null,
121
+ tool_calls: [
122
+ {
123
+ id: item.call_id || item.callId,
124
+ type: 'function',
125
+ function: {
126
+ name: item.name,
127
+ arguments: typeof item.arguments === 'string' ? item.arguments : JSON.stringify(item.arguments || {}),
128
+ },
129
+ },
130
+ ],
131
+ });
132
+ continue;
133
+ }
134
+ if (item.type === 'function_call_output') {
135
+ messages.push({
136
+ role: 'tool',
137
+ tool_call_id: item.call_id || item.callId,
138
+ content: typeof item.output === 'string' ? item.output : JSON.stringify(item.output ?? ''),
139
+ });
140
+ continue;
141
+ }
142
+ const role = item.role === 'assistant' || item.role === 'user' || item.role === 'system' ? item.role : 'user';
143
+ messages.push({ role, content: this.toChatContent(item.content) });
144
+ }
145
+ return messages;
146
+ }
147
+ /** Convert Responses content parts (input_text/input_image) to Chat content parts. */
148
+ toChatContent(content) {
149
+ if (typeof content === 'string' || content === null || content === undefined)
150
+ return content ?? '';
151
+ if (!Array.isArray(content))
152
+ return content;
153
+ return content.map((part) => {
154
+ if (!part || typeof part !== 'object')
155
+ return { type: 'text', text: String(part) };
156
+ if (part.type === 'input_text')
157
+ return { type: 'text', text: part.text ?? '' };
158
+ if (part.type === 'input_image') {
159
+ const url = typeof part.image_url === 'string' ? part.image_url : part.image_url?.url || part.url;
160
+ return { type: 'image_url', image_url: { url } };
161
+ }
162
+ if (part.type === 'text' || part.type === 'image_url')
163
+ return part;
164
+ return part;
165
+ });
166
+ }
167
+ toChatTools(tools) {
168
+ if (!tools || tools.length === 0)
169
+ return undefined;
170
+ return tools.map((t) => ({
171
+ type: 'function',
172
+ function: {
173
+ name: t.name || t.function?.name,
174
+ description: t.description || t.function?.description || '',
175
+ parameters: t.parameters || t.function?.parameters || { type: 'object', properties: {} },
176
+ },
177
+ }));
178
+ }
179
+ async generate(params) {
180
+ const genSpan = langfuseTracer.startGeneration('musonda-llm-generation', {
181
+ model: this.model,
182
+ input: this.summarizeInput(params.instructions, params.input, params.tools),
183
+ metadata: { provider: this.provider, model: this.model, inputItems: params.input?.length || 0, tools: params.tools?.length || 0 },
184
+ });
185
+ const startedAt = Date.now();
186
+ try {
187
+ const result = await this.doGenerate(params);
188
+ langfuseTracer.endSpan(genSpan, {
189
+ output: { text: result.text?.slice(0, 4000), toolCalls: result.toolCalls?.length || 0 },
190
+ metadata: { provider: this.provider, model: this.model, latencyMs: Date.now() - startedAt, toolCalls: result.toolCalls?.length || 0 },
191
+ });
192
+ return result;
193
+ }
194
+ catch (err) {
195
+ langfuseTracer.endSpan(genSpan, {
196
+ metadata: { provider: this.provider, model: this.model, latencyMs: Date.now() - startedAt, error: err?.message || String(err) },
197
+ });
198
+ throw err;
199
+ }
200
+ }
201
+ summarizeInput(instructions, input, tools) {
202
+ try {
203
+ const last = input?.slice(-6).map((item) => {
204
+ if (typeof item === 'string')
205
+ return item.slice(0, 500);
206
+ const content = typeof item?.content === 'string'
207
+ ? item.content.slice(0, 500)
208
+ : JSON.stringify(item?.content ?? item).slice(0, 500);
209
+ return { type: item?.type || item?.role, name: item?.name, content };
210
+ });
211
+ return {
212
+ instructions: instructions?.slice(0, 2000),
213
+ recentInput: last,
214
+ toolNames: (tools || []).map((t) => t?.name || t?.function?.name).filter(Boolean),
215
+ };
216
+ }
217
+ catch {
218
+ return { instructions: instructions?.slice(0, 500), inputItems: input?.length || 0 };
219
+ }
220
+ }
221
+ async doGenerate(params) {
222
+ logger.debug(`Calling Chat Completions (provider "${this.provider}") with model "${this.model}", ${params.input.length} input items...`);
223
+ const messages = this.toChatMessages(params.instructions, params.input);
224
+ const tools = this.toChatTools(params.tools);
225
+ const basePayload = {
226
+ model: this.model,
227
+ messages,
228
+ max_tokens: this.maxOutputTokens,
229
+ };
230
+ if (this.temperature !== undefined && this.supportsTemperature(this.model)) {
231
+ basePayload.temperature = this.temperature;
232
+ }
233
+ if (tools)
234
+ basePayload.tools = tools;
235
+ // Streaming path
236
+ if (params.onDelta) {
237
+ let stream;
238
+ try {
239
+ stream = await this.withRetry(() => this.client.chat.completions.create({ ...basePayload, stream: true }), { label: 'chat.stream' });
240
+ }
241
+ catch (err) {
242
+ if (this.isTempError(err) && basePayload.temperature !== undefined) {
243
+ delete basePayload.temperature;
244
+ stream = await this.withRetry(() => this.client.chat.completions.create({ ...basePayload, stream: true }), { label: 'chat.stream' });
245
+ }
246
+ else {
247
+ throw this.toProviderError(err);
248
+ }
249
+ }
250
+ let accumulatedText = '';
251
+ const toolCallMap = new Map();
252
+ const orderedIds = [];
253
+ for await (const chunk of stream) {
254
+ const choice = chunk?.choices?.[0];
255
+ const delta = choice?.delta;
256
+ if (!delta)
257
+ continue;
258
+ const textDelta = delta.content || '';
259
+ if (textDelta) {
260
+ accumulatedText += textDelta;
261
+ try {
262
+ await params.onDelta(textDelta);
263
+ }
264
+ catch (cbErr) {
265
+ logger.debug('Error in onDelta streaming callback:', cbErr);
266
+ }
267
+ }
268
+ const deltaToolCalls = delta.tool_calls;
269
+ if (Array.isArray(deltaToolCalls)) {
270
+ for (const tc of deltaToolCalls) {
271
+ const idx = typeof tc.index === 'number' ? tc.index : 0;
272
+ const key = `idx:${idx}`;
273
+ let entry = toolCallMap.get(key);
274
+ if (!entry) {
275
+ entry = { id: tc.id || '', name: tc.function?.name || '', args: '' };
276
+ toolCallMap.set(key, entry);
277
+ orderedIds.push(key);
278
+ }
279
+ if (tc.id)
280
+ entry.id = tc.id;
281
+ if (tc.function?.name)
282
+ entry.name = tc.function.name;
283
+ if (tc.function?.arguments)
284
+ entry.args += tc.function.arguments;
285
+ }
286
+ }
287
+ }
288
+ const toolCalls = [];
289
+ for (const key of orderedIds) {
290
+ const entry = toolCallMap.get(key);
291
+ if (!entry.name)
292
+ continue;
293
+ toolCalls.push({
294
+ callId: entry.id || `call_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
295
+ name: entry.name,
296
+ arguments: entry.args || '{}',
297
+ });
298
+ }
299
+ return { text: accumulatedText.trim(), toolCalls, rawOutput: [] };
300
+ }
301
+ // Non-streaming path
302
+ let response;
303
+ try {
304
+ response = await this.withRetry(() => this.client.chat.completions.create(basePayload), {
305
+ label: 'chat.create',
306
+ });
307
+ }
308
+ catch (err) {
309
+ if (this.isTempError(err) && basePayload.temperature !== undefined) {
310
+ delete basePayload.temperature;
311
+ response = await this.withRetry(() => this.client.chat.completions.create(basePayload), {
312
+ label: 'chat.create',
313
+ });
314
+ }
315
+ else {
316
+ throw this.toProviderError(err);
317
+ }
318
+ }
319
+ const message = response?.choices?.[0]?.message;
320
+ const text = typeof message?.content === 'string' ? message.content : '';
321
+ const toolCalls = [];
322
+ if (Array.isArray(message?.tool_calls)) {
323
+ for (const tc of message.tool_calls) {
324
+ toolCalls.push({
325
+ callId: tc.id || `call_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
326
+ name: tc.function?.name,
327
+ arguments: typeof tc.function?.arguments === 'string' ? tc.function.arguments : JSON.stringify(tc.function?.arguments || {}),
328
+ });
329
+ }
330
+ }
331
+ return { text: (text || '').trim(), toolCalls, rawOutput: [] };
332
+ }
333
+ isTempError(err) {
334
+ return (err?.status === 400 &&
335
+ (err?.message?.includes('temperature') || err?.param === 'temperature' || err?.error?.param === 'temperature'));
336
+ }
337
+ toProviderError(err) {
338
+ logger.error(`Chat Completions error (provider "${this.provider}", model "${this.model}"):`, err.message || err);
339
+ if (err.status === 401 || (err.message && err.message.includes('API key'))) {
340
+ return new Error(`Model Authentication Error [${this.provider}]: API key is invalid or missing for model "${this.model}". Run 'musonda setup' or 'musonda model setup' to configure credentials.`);
341
+ }
342
+ return err;
343
+ }
344
+ }
345
+ //# sourceMappingURL=chatCompletionsClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatCompletionsClient.js","sourceRoot":"","sources":["../../src/agent/chatCompletionsClient.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { MusondaConfig } from '../config/types.js';
2
2
  import { MemoryManager } from '../memory/memoryManager.js';
3
3
  import { ToolRegistry } from '../tools/registry.js';
4
- import { OpenAIResponsesClient } from './openaiResponsesClient.js';
4
+ import { ModelClient } from './modelTypes.js';
5
5
  import { AgentRunInput, AgentRunResult } from './types.js';
6
6
  import { FileRunLedger } from './runLedger.js';
7
7
  import { MediaManager } from '../media/mediaManager.js';
@@ -16,7 +16,7 @@ export declare class AgentHarness {
16
16
  private gateway?;
17
17
  private mediaManager?;
18
18
  private runLedger?;
19
- constructor(config: MusondaConfig, memory: MemoryManager, tools: ToolRegistry, client: OpenAIResponsesClient, scheduler?: any, pluginManager?: any, gateway?: any, mediaManager?: MediaManager);
19
+ constructor(config: MusondaConfig, memory: MemoryManager, tools: ToolRegistry, client: ModelClient, scheduler?: any, pluginManager?: any, gateway?: any, mediaManager?: MediaManager);
20
20
  setMediaManager(mediaManager: MediaManager): void;
21
21
  getMediaManager(): MediaManager | undefined;
22
22
  setGateway(gateway: any): void;
@@ -27,7 +27,9 @@ export declare class AgentHarness {
27
27
  getPluginManager(): any;
28
28
  getMemoryManager(): MemoryManager;
29
29
  getToolRegistry(): ToolRegistry;
30
- getClient(): OpenAIResponsesClient;
30
+ getClient(): ModelClient;
31
+ /** Swap the model client at runtime (e.g. after `musonda model` changes). */
32
+ setClient(client: ModelClient): void;
31
33
  /** Inject a file-backed run ledger (durable journal). Optional — harness works without it. */
32
34
  setRunLedger(ledger: FileRunLedger): void;
33
35
  getRunLedger(): FileRunLedger | undefined;
@@ -38,4 +40,5 @@ export declare class AgentHarness {
38
40
  private formatToolStatus;
39
41
  private formatToolReviewStatus;
40
42
  processMessage(input: AgentRunInput): Promise<AgentRunResult>;
43
+ private doProcessMessage;
41
44
  }