@nuvin/nuvin-core 1.0.1 → 1.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/dist/VERSION +2 -2
- package/dist/index.d.ts +17 -15
- package/dist/index.js +176 -138
- package/package.json +1 -1
package/dist/VERSION
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -290,6 +290,7 @@ type Message = {
|
|
|
290
290
|
tool_calls?: ToolCall[];
|
|
291
291
|
tool_call_id?: string;
|
|
292
292
|
name?: string;
|
|
293
|
+
usage?: UsageData;
|
|
293
294
|
};
|
|
294
295
|
type MessageResponse = {
|
|
295
296
|
id: string;
|
|
@@ -439,7 +440,6 @@ declare const AgentEventTypes: {
|
|
|
439
440
|
readonly AssistantChunk: "assistant_chunk";
|
|
440
441
|
readonly AssistantMessage: "assistant_message";
|
|
441
442
|
readonly StreamFinish: "stream_finish";
|
|
442
|
-
readonly MemoryAppended: "memory_appended";
|
|
443
443
|
readonly Done: "done";
|
|
444
444
|
readonly Error: "error";
|
|
445
445
|
readonly MCPStderr: "mcp_stderr";
|
|
@@ -461,6 +461,7 @@ type AgentEvent = {
|
|
|
461
461
|
conversationId: string;
|
|
462
462
|
messageId: string;
|
|
463
463
|
toolCalls: ToolCall[];
|
|
464
|
+
usage?: UsageData;
|
|
464
465
|
} | {
|
|
465
466
|
type: typeof AgentEventTypes.ToolApprovalRequired;
|
|
466
467
|
conversationId: string;
|
|
@@ -497,10 +498,6 @@ type AgentEvent = {
|
|
|
497
498
|
messageId: string;
|
|
498
499
|
finishReason?: string;
|
|
499
500
|
usage?: UsageData;
|
|
500
|
-
} | {
|
|
501
|
-
type: typeof AgentEventTypes.MemoryAppended;
|
|
502
|
-
conversationId: string;
|
|
503
|
-
delta: Message[];
|
|
504
501
|
} | {
|
|
505
502
|
type: typeof AgentEventTypes.Done;
|
|
506
503
|
conversationId: string;
|
|
@@ -1088,12 +1085,6 @@ declare class BashTool implements FunctionTool<BashParams, ToolExecutionContext>
|
|
|
1088
1085
|
private shellArgs;
|
|
1089
1086
|
}
|
|
1090
1087
|
|
|
1091
|
-
declare class EchoLLM implements LLMPort {
|
|
1092
|
-
generateCompletion(params: CompletionParams): Promise<CompletionResult>;
|
|
1093
|
-
private hasTool;
|
|
1094
|
-
private id;
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
1088
|
type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
|
|
1098
1089
|
type LogFormat = 'json' | 'structured';
|
|
1099
1090
|
type PersistOptions = {
|
|
@@ -1226,16 +1217,27 @@ declare class AnthropicAISDKLLM {
|
|
|
1226
1217
|
}, signal?: AbortSignal): Promise<CompletionResult>;
|
|
1227
1218
|
}
|
|
1228
1219
|
|
|
1220
|
+
type ModelConfig = false | true | string | string[] | Array<{
|
|
1221
|
+
id: string;
|
|
1222
|
+
name?: string;
|
|
1223
|
+
[key: string]: unknown;
|
|
1224
|
+
}>;
|
|
1229
1225
|
interface LLMOptions {
|
|
1230
1226
|
apiKey?: string;
|
|
1231
1227
|
apiUrl?: string;
|
|
1232
1228
|
httpLogFile?: string;
|
|
1233
1229
|
enablePromptCaching?: boolean;
|
|
1234
1230
|
includeUsage?: boolean;
|
|
1231
|
+
version?: string;
|
|
1232
|
+
}
|
|
1233
|
+
interface CustomProviderDefinition {
|
|
1234
|
+
type?: 'openai-compat' | 'anthropic';
|
|
1235
|
+
baseUrl?: string;
|
|
1236
|
+
models?: ModelConfig;
|
|
1235
1237
|
}
|
|
1236
|
-
declare function createLLM(providerName: string, options?: LLMOptions): LLMPort;
|
|
1237
|
-
declare function getAvailableProviders(): string[];
|
|
1238
|
-
declare function supportsGetModels(providerName: string): boolean;
|
|
1238
|
+
declare function createLLM(providerName: string, options?: LLMOptions, customProviders?: Record<string, CustomProviderDefinition>): LLMPort;
|
|
1239
|
+
declare function getAvailableProviders(customProviders?: Record<string, CustomProviderDefinition>): string[];
|
|
1240
|
+
declare function supportsGetModels(providerName: string, customProviders?: Record<string, CustomProviderDefinition>): boolean;
|
|
1239
1241
|
|
|
1240
1242
|
type MCPHttpOptions = {
|
|
1241
1243
|
type: 'http';
|
|
@@ -1326,4 +1328,4 @@ declare function resolveBackspaces(s: string): string;
|
|
|
1326
1328
|
declare function stripAnsiAndControls(s: string): string;
|
|
1327
1329
|
declare function canonicalizeTerminalPaste(raw: string): string;
|
|
1328
1330
|
|
|
1329
|
-
export { AGENT_CREATOR_SYSTEM_PROMPT, type AgentAwareToolPort, type AgentCatalog, type AgentConfig, type AgentEvent, AgentEventTypes, AgentFilePersistence, AgentManager, AgentManagerCommandRunner, AgentOrchestrator, AgentRegistry, type AgentTemplate, AnthropicAISDKLLM, type AssignParams, BashTool, CompositeToolPort, type Conversation, ConversationContext, type ConversationMetadata, type ConversationSnapshot, ConversationStore, CoreMCPClient, DefaultDelegationPolicy, DefaultDelegationResultFormatter, DefaultDelegationService, DefaultSpecialistAgentFactory, type DelegationService, type DelegationServiceConfig, DelegationServiceFactory,
|
|
1331
|
+
export { AGENT_CREATOR_SYSTEM_PROMPT, type AgentAwareToolPort, type AgentCatalog, type AgentConfig, type AgentEvent, AgentEventTypes, AgentFilePersistence, AgentManager, AgentManagerCommandRunner, AgentOrchestrator, AgentRegistry, type AgentTemplate, AnthropicAISDKLLM, type AssignParams, BashTool, CompositeToolPort, type Conversation, ConversationContext, type ConversationMetadata, type ConversationSnapshot, ConversationStore, CoreMCPClient, DefaultDelegationPolicy, DefaultDelegationResultFormatter, DefaultDelegationService, DefaultSpecialistAgentFactory, type DelegationService, type DelegationServiceConfig, DelegationServiceFactory, type FolderTreeOptions, GithubLLM, InMemoryMemory, InMemoryMetadata, JsonFileMemoryPersistence, type LLMConfig, LLMError, type LLMFactory, type LLMOptions, type LLMPort, LLMResolver, type MCPConfig, type MCPServerConfig, MCPToolPort, type MemoryPort, MemoryPortMetadataAdapter, type Message, type MessageContent, type MessageContentPart, type MetadataPort, NoopReminders, type OrchestratorAwareToolPort, PersistedMemory, PersistingConsoleEventPort, RuntimeEnv, type SendMessageOptions, SimpleContextBuilder, SimpleCost, SimpleId, type SpecialistAgentConfig, type SpecialistAgentResult, SystemClock, type ToolApprovalDecision, type ToolCall, type ToolExecutionResult, type ToolPort, ToolRegistry, type UserAttachment, type UserMessagePayload, buildAgentCreationPrompt, buildInjectedSystem, canonicalizeTerminalPaste, createLLM, generateFolderTree, getAvailableProviders, loadMCPConfig, normalizeNewlines, renderTemplate, resolveBackspaces, resolveCarriageReturns, stripAnsiAndControls, supportsGetModels };
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,6 @@ var AgentEventTypes = {
|
|
|
14
14
|
AssistantChunk: "assistant_chunk",
|
|
15
15
|
AssistantMessage: "assistant_message",
|
|
16
16
|
StreamFinish: "stream_finish",
|
|
17
|
-
MemoryAppended: "memory_appended",
|
|
18
17
|
Done: "done",
|
|
19
18
|
Error: "error",
|
|
20
19
|
MCPStderr: "mcp_stderr",
|
|
@@ -161,19 +160,22 @@ var AgentOrchestrator = class {
|
|
|
161
160
|
const todoTools = ["todo_write", "todo_read"];
|
|
162
161
|
return readOnlyTools.includes(toolName) || todoTools.includes(toolName);
|
|
163
162
|
}
|
|
164
|
-
async handleToolDenial(denialMessage, conversationId, messageId, accumulatedMessages, turnHistory, originalToolCalls, assistantContent) {
|
|
165
|
-
|
|
166
|
-
role: "assistant",
|
|
167
|
-
content: assistantContent ?? null,
|
|
168
|
-
tool_calls: originalToolCalls
|
|
169
|
-
});
|
|
170
|
-
turnHistory.push({
|
|
163
|
+
async handleToolDenial(denialMessage, conversationId, messageId, accumulatedMessages, turnHistory, originalToolCalls, assistantContent, usage) {
|
|
164
|
+
const assistantMsg = {
|
|
171
165
|
id: this.deps.ids.uuid(),
|
|
172
166
|
role: "assistant",
|
|
173
167
|
content: assistantContent ?? null,
|
|
174
168
|
timestamp: this.deps.clock.iso(),
|
|
169
|
+
tool_calls: originalToolCalls,
|
|
170
|
+
usage
|
|
171
|
+
};
|
|
172
|
+
accumulatedMessages.push({
|
|
173
|
+
role: "assistant",
|
|
174
|
+
content: assistantContent ?? null,
|
|
175
175
|
tool_calls: originalToolCalls
|
|
176
176
|
});
|
|
177
|
+
turnHistory.push(assistantMsg);
|
|
178
|
+
const toolResultMsgs = [];
|
|
177
179
|
for (const toolCall of originalToolCalls) {
|
|
178
180
|
const toolDenialResult = "Tool execution denied by user";
|
|
179
181
|
accumulatedMessages.push({
|
|
@@ -182,23 +184,27 @@ var AgentOrchestrator = class {
|
|
|
182
184
|
tool_call_id: toolCall.id,
|
|
183
185
|
name: toolCall.function.name
|
|
184
186
|
});
|
|
185
|
-
|
|
187
|
+
const toolMsg = {
|
|
186
188
|
id: toolCall.id,
|
|
187
189
|
role: "tool",
|
|
188
190
|
content: toolDenialResult,
|
|
189
191
|
timestamp: this.deps.clock.iso(),
|
|
190
192
|
tool_call_id: toolCall.id,
|
|
191
193
|
name: toolCall.function.name
|
|
192
|
-
}
|
|
194
|
+
};
|
|
195
|
+
turnHistory.push(toolMsg);
|
|
196
|
+
toolResultMsgs.push(toolMsg);
|
|
193
197
|
}
|
|
198
|
+
await this.deps.memory.append(conversationId, [assistantMsg, ...toolResultMsgs]);
|
|
194
199
|
await this.deps.events?.emit({
|
|
195
200
|
type: AgentEventTypes.AssistantMessage,
|
|
196
201
|
conversationId,
|
|
197
202
|
messageId,
|
|
198
|
-
content: denialMessage
|
|
203
|
+
content: denialMessage,
|
|
204
|
+
usage: void 0
|
|
199
205
|
});
|
|
200
206
|
}
|
|
201
|
-
async processToolApproval(toolCalls, conversationId, messageId, accumulatedMessages, turnHistory, assistantContent) {
|
|
207
|
+
async processToolApproval(toolCalls, conversationId, messageId, accumulatedMessages, turnHistory, assistantContent, usage) {
|
|
202
208
|
if (this.cfg.requireToolApproval === false) {
|
|
203
209
|
return { approvedCalls: toolCalls, wasDenied: false };
|
|
204
210
|
}
|
|
@@ -220,7 +226,8 @@ var AgentOrchestrator = class {
|
|
|
220
226
|
accumulatedMessages,
|
|
221
227
|
turnHistory,
|
|
222
228
|
toolCalls,
|
|
223
|
-
assistantContent
|
|
229
|
+
assistantContent,
|
|
230
|
+
usage
|
|
224
231
|
);
|
|
225
232
|
return { approvedCalls: [], wasDenied: true, denialMessage };
|
|
226
233
|
}
|
|
@@ -263,6 +270,7 @@ var AgentOrchestrator = class {
|
|
|
263
270
|
userDisplay = resolveDisplayText(normalized.text, attachments, normalized.displayText);
|
|
264
271
|
const userTimestamp = this.deps.clock.iso();
|
|
265
272
|
userMessages = [{ id: this.deps.ids.uuid(), role: "user", content: userContent, timestamp: userTimestamp }];
|
|
273
|
+
await this.deps.memory.append(convo, userMessages);
|
|
266
274
|
}
|
|
267
275
|
if (opts.signal?.aborted) throw new Error("Aborted");
|
|
268
276
|
const toolDefs = this.deps.tools.getToolDefinitions(this.cfg.enabledTools ?? []);
|
|
@@ -293,8 +301,10 @@ var AgentOrchestrator = class {
|
|
|
293
301
|
let result;
|
|
294
302
|
let toolApprovalDenied = false;
|
|
295
303
|
let denialMessage = "";
|
|
304
|
+
let finalResponseSaved = false;
|
|
296
305
|
try {
|
|
297
306
|
if (opts.stream && typeof this.deps.llm.streamCompletion === "function") {
|
|
307
|
+
let isFirstChunk = true;
|
|
298
308
|
result = await this.deps.llm.streamCompletion(
|
|
299
309
|
params,
|
|
300
310
|
{
|
|
@@ -303,7 +313,8 @@ var AgentOrchestrator = class {
|
|
|
303
313
|
streamedAssistantContent += delta;
|
|
304
314
|
} catch {
|
|
305
315
|
}
|
|
306
|
-
const cleanDelta = delta.replace(/^\n+/, "");
|
|
316
|
+
const cleanDelta = isFirstChunk ? delta.replace(/^\n+/, "") : delta;
|
|
317
|
+
isFirstChunk = false;
|
|
307
318
|
const chunkEvent = {
|
|
308
319
|
type: AgentEventTypes.AssistantChunk,
|
|
309
320
|
conversationId: convo,
|
|
@@ -329,6 +340,28 @@ var AgentOrchestrator = class {
|
|
|
329
340
|
} else {
|
|
330
341
|
result = await this.deps.llm.generateCompletion(params, opts.signal);
|
|
331
342
|
}
|
|
343
|
+
if (!result.tool_calls?.length && result.content && !finalResponseSaved) {
|
|
344
|
+
const content2 = opts.stream ? streamedAssistantContent : result.content;
|
|
345
|
+
const assistantMsg = {
|
|
346
|
+
id: msgId,
|
|
347
|
+
role: "assistant",
|
|
348
|
+
content: content2,
|
|
349
|
+
timestamp: this.deps.clock.iso(),
|
|
350
|
+
usage: result.usage
|
|
351
|
+
};
|
|
352
|
+
await this.deps.memory.append(convo, [assistantMsg]);
|
|
353
|
+
finalResponseSaved = true;
|
|
354
|
+
if (content2.trim()) {
|
|
355
|
+
const messageEvent = {
|
|
356
|
+
type: AgentEventTypes.AssistantMessage,
|
|
357
|
+
conversationId: convo,
|
|
358
|
+
messageId: msgId,
|
|
359
|
+
content: content2,
|
|
360
|
+
...result.usage && { usage: result.usage }
|
|
361
|
+
};
|
|
362
|
+
await this.deps.events?.emit(messageEvent);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
332
365
|
while (result.tool_calls?.length) {
|
|
333
366
|
if (result.content?.trim()) {
|
|
334
367
|
const messageEvent = {
|
|
@@ -345,7 +378,8 @@ var AgentOrchestrator = class {
|
|
|
345
378
|
type: AgentEventTypes.ToolCalls,
|
|
346
379
|
conversationId: convo,
|
|
347
380
|
messageId: msgId,
|
|
348
|
-
toolCalls: result.tool_calls
|
|
381
|
+
toolCalls: result.tool_calls,
|
|
382
|
+
usage: result.usage
|
|
349
383
|
});
|
|
350
384
|
const approvalResult = await this.processToolApproval(
|
|
351
385
|
result.tool_calls,
|
|
@@ -353,7 +387,8 @@ var AgentOrchestrator = class {
|
|
|
353
387
|
msgId,
|
|
354
388
|
accumulatedMessages,
|
|
355
389
|
turnHistory,
|
|
356
|
-
result.content
|
|
390
|
+
result.content,
|
|
391
|
+
result.usage
|
|
357
392
|
);
|
|
358
393
|
if (approvalResult.wasDenied) {
|
|
359
394
|
denialMessage = approvalResult.denialMessage || "";
|
|
@@ -375,18 +410,18 @@ var AgentOrchestrator = class {
|
|
|
375
410
|
opts.signal
|
|
376
411
|
);
|
|
377
412
|
allToolResults.push(...toolResults);
|
|
378
|
-
|
|
379
|
-
turnHistory.push({
|
|
413
|
+
const assistantMsg = {
|
|
380
414
|
id: this.deps.ids.uuid(),
|
|
381
415
|
role: "assistant",
|
|
382
416
|
content: result.content ?? null,
|
|
383
417
|
timestamp: this.deps.clock.iso(),
|
|
384
|
-
tool_calls: approvedCalls
|
|
385
|
-
|
|
418
|
+
tool_calls: approvedCalls,
|
|
419
|
+
usage: result.usage
|
|
420
|
+
};
|
|
421
|
+
const toolResultMsgs = [];
|
|
386
422
|
for (const tr of toolResults) {
|
|
387
423
|
const contentStr = tr.status === "error" ? String(tr.result) : typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
|
|
388
|
-
|
|
389
|
-
turnHistory.push({
|
|
424
|
+
toolResultMsgs.push({
|
|
390
425
|
id: tr.id,
|
|
391
426
|
role: "tool",
|
|
392
427
|
content: contentStr,
|
|
@@ -401,8 +436,16 @@ var AgentOrchestrator = class {
|
|
|
401
436
|
result: tr
|
|
402
437
|
});
|
|
403
438
|
}
|
|
439
|
+
await this.deps.memory.append(convo, [assistantMsg, ...toolResultMsgs]);
|
|
440
|
+
accumulatedMessages.push({ role: "assistant", content: result.content ?? null, tool_calls: approvedCalls });
|
|
441
|
+
for (const tr of toolResults) {
|
|
442
|
+
const contentStr = tr.status === "error" ? String(tr.result) : typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
|
|
443
|
+
accumulatedMessages.push({ role: "tool", content: contentStr, tool_call_id: tr.id, name: tr.name });
|
|
444
|
+
}
|
|
404
445
|
if (opts.signal?.aborted) throw new Error("Aborted");
|
|
446
|
+
streamedAssistantContent = "";
|
|
405
447
|
if (opts.stream && typeof this.deps.llm.streamCompletion === "function") {
|
|
448
|
+
let isFirstChunk = true;
|
|
406
449
|
result = await this.deps.llm.streamCompletion(
|
|
407
450
|
{ ...params, messages: accumulatedMessages },
|
|
408
451
|
{
|
|
@@ -411,7 +454,8 @@ var AgentOrchestrator = class {
|
|
|
411
454
|
streamedAssistantContent += delta;
|
|
412
455
|
} catch {
|
|
413
456
|
}
|
|
414
|
-
const cleanDelta = delta.replace(/^\n+/, "");
|
|
457
|
+
const cleanDelta = isFirstChunk ? delta.replace(/^\n+/, "") : delta;
|
|
458
|
+
isFirstChunk = false;
|
|
415
459
|
const chunkEvent = {
|
|
416
460
|
type: AgentEventTypes.AssistantChunk,
|
|
417
461
|
conversationId: convo,
|
|
@@ -437,16 +481,32 @@ var AgentOrchestrator = class {
|
|
|
437
481
|
} else {
|
|
438
482
|
result = await this.deps.llm.generateCompletion({ ...params, messages: accumulatedMessages }, opts.signal);
|
|
439
483
|
}
|
|
484
|
+
if (!result.tool_calls?.length && result.content && !finalResponseSaved) {
|
|
485
|
+
const content2 = opts.stream ? streamedAssistantContent : result.content;
|
|
486
|
+
const assistantMsg2 = {
|
|
487
|
+
id: msgId,
|
|
488
|
+
role: "assistant",
|
|
489
|
+
content: content2,
|
|
490
|
+
timestamp: this.deps.clock.iso(),
|
|
491
|
+
usage: result.usage
|
|
492
|
+
};
|
|
493
|
+
await this.deps.memory.append(convo, [assistantMsg2]);
|
|
494
|
+
finalResponseSaved = true;
|
|
495
|
+
if (content2.trim()) {
|
|
496
|
+
const messageEvent = {
|
|
497
|
+
type: AgentEventTypes.AssistantMessage,
|
|
498
|
+
conversationId: convo,
|
|
499
|
+
messageId: msgId,
|
|
500
|
+
content: content2,
|
|
501
|
+
...result.usage && { usage: result.usage }
|
|
502
|
+
};
|
|
503
|
+
await this.deps.events?.emit(messageEvent);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
440
506
|
}
|
|
441
507
|
const t1 = this.deps.clock.now();
|
|
442
508
|
const timestamp = this.deps.clock.iso();
|
|
443
|
-
const
|
|
444
|
-
for (const m of userMessages) newHistory.push(m);
|
|
445
|
-
for (const m of turnHistory) newHistory.push(m);
|
|
446
|
-
if (!toolApprovalDenied) {
|
|
447
|
-
newHistory.push({ id: msgId, role: "assistant", content: result.content, timestamp });
|
|
448
|
-
}
|
|
449
|
-
const shouldEmitFinalMessage = result.content?.trim() && !toolApprovalDenied;
|
|
509
|
+
const shouldEmitFinalMessage = result.content?.trim() && !toolApprovalDenied && !finalResponseSaved;
|
|
450
510
|
if (shouldEmitFinalMessage) {
|
|
451
511
|
const messageEvent = {
|
|
452
512
|
type: AgentEventTypes.AssistantMessage,
|
|
@@ -475,8 +535,6 @@ var AgentOrchestrator = class {
|
|
|
475
535
|
toolCalls: allToolResults.length
|
|
476
536
|
}
|
|
477
537
|
};
|
|
478
|
-
await this.deps.memory.append(convo, newHistory);
|
|
479
|
-
await this.deps.events?.emit({ type: AgentEventTypes.MemoryAppended, conversationId: convo, delta: newHistory });
|
|
480
538
|
await this.deps.events?.emit({
|
|
481
539
|
type: AgentEventTypes.Done,
|
|
482
540
|
conversationId: convo,
|
|
@@ -486,26 +544,6 @@ var AgentOrchestrator = class {
|
|
|
486
544
|
});
|
|
487
545
|
return resp;
|
|
488
546
|
} catch (err2) {
|
|
489
|
-
try {
|
|
490
|
-
const partial = [];
|
|
491
|
-
for (const m of userMessages) partial.push(m);
|
|
492
|
-
for (const m of turnHistory) partial.push(m);
|
|
493
|
-
const partialAssistant = (streamedAssistantContent || "").trim();
|
|
494
|
-
const assistantAlreadyRecorded = turnHistory.some((m) => m.role === "assistant");
|
|
495
|
-
if (partialAssistant && !assistantAlreadyRecorded) {
|
|
496
|
-
partial.push({
|
|
497
|
-
id: this.deps.ids.uuid(),
|
|
498
|
-
role: "assistant",
|
|
499
|
-
content: partialAssistant,
|
|
500
|
-
timestamp: this.deps.clock.iso()
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
if (partial.length) {
|
|
504
|
-
await this.deps.memory.append(convo, partial);
|
|
505
|
-
await this.deps.events?.emit({ type: AgentEventTypes.MemoryAppended, conversationId: convo, delta: partial });
|
|
506
|
-
}
|
|
507
|
-
} catch {
|
|
508
|
-
}
|
|
509
547
|
throw err2;
|
|
510
548
|
}
|
|
511
549
|
}
|
|
@@ -1842,7 +1880,10 @@ var FileReadTool = class {
|
|
|
1842
1880
|
parameters = {
|
|
1843
1881
|
type: "object",
|
|
1844
1882
|
properties: {
|
|
1845
|
-
description: {
|
|
1883
|
+
description: {
|
|
1884
|
+
type: "string",
|
|
1885
|
+
description: 'Explanation of what file is being read and why (e.g., "Read package.json to check dependencies")'
|
|
1886
|
+
},
|
|
1846
1887
|
path: { type: "string", description: "Read contents of this file" },
|
|
1847
1888
|
lineStart: { type: "integer", minimum: 1, description: "Start reading from this line number (1-based)" },
|
|
1848
1889
|
lineEnd: { type: "integer", minimum: 1, description: "Stop reading at this line number (inclusive)" }
|
|
@@ -1883,7 +1924,7 @@ var FileReadTool = class {
|
|
|
1883
1924
|
const [lo, hi] = a <= b ? [a, b] : [b, a];
|
|
1884
1925
|
const numberedLines = lines.slice(lo - 1, hi).map((line, index) => {
|
|
1885
1926
|
const lineNum = lo + index;
|
|
1886
|
-
return `${lineNum}
|
|
1927
|
+
return `${lineNum}\u2502${line}`;
|
|
1887
1928
|
});
|
|
1888
1929
|
const slice = numberedLines.join("\n");
|
|
1889
1930
|
return ok(slice, {
|
|
@@ -3642,59 +3683,6 @@ var AgentFilePersistence = class {
|
|
|
3642
3683
|
}
|
|
3643
3684
|
};
|
|
3644
3685
|
|
|
3645
|
-
// llm-providers/llm-echo.ts
|
|
3646
|
-
var EchoLLM = class {
|
|
3647
|
-
async generateCompletion(params) {
|
|
3648
|
-
const last = [...params.messages].reverse().find((m) => m.role === "user");
|
|
3649
|
-
const content = String(last?.content ?? "");
|
|
3650
|
-
const toolCalls = [];
|
|
3651
|
-
if (content.startsWith("!reverse ") && this.hasTool(params, "reverse_text")) {
|
|
3652
|
-
const text = content.slice("!reverse ".length);
|
|
3653
|
-
toolCalls.push({
|
|
3654
|
-
id: this.id("rev"),
|
|
3655
|
-
type: "function",
|
|
3656
|
-
function: { name: "reverse_text", arguments: JSON.stringify({ text }) }
|
|
3657
|
-
});
|
|
3658
|
-
} else if (content.startsWith("!wc ") && this.hasTool(params, "word_count")) {
|
|
3659
|
-
const text = content.slice("!wc ".length);
|
|
3660
|
-
toolCalls.push({
|
|
3661
|
-
id: this.id("wc"),
|
|
3662
|
-
type: "function",
|
|
3663
|
-
function: { name: "word_count", arguments: JSON.stringify({ text }) }
|
|
3664
|
-
});
|
|
3665
|
-
} else if (content.startsWith("!todo ") && this.hasTool(params, "todo_write")) {
|
|
3666
|
-
const payload = content.slice("!todo ".length);
|
|
3667
|
-
let todos;
|
|
3668
|
-
try {
|
|
3669
|
-
todos = JSON.parse(payload);
|
|
3670
|
-
} catch {
|
|
3671
|
-
todos = [];
|
|
3672
|
-
}
|
|
3673
|
-
toolCalls.push({
|
|
3674
|
-
id: this.id("todo"),
|
|
3675
|
-
type: "function",
|
|
3676
|
-
function: { name: "todo_write", arguments: JSON.stringify({ todos }) }
|
|
3677
|
-
});
|
|
3678
|
-
}
|
|
3679
|
-
const sawTool = params.messages.some((m) => m.role === "tool");
|
|
3680
|
-
if (sawTool) {
|
|
3681
|
-
const lastTool = [...params.messages].reverse().find((m) => m.role === "tool");
|
|
3682
|
-
const toolText = typeof lastTool?.content === "string" ? lastTool.content : "";
|
|
3683
|
-
return { content: `Tool result: ${toolText}` };
|
|
3684
|
-
}
|
|
3685
|
-
if (toolCalls.length > 0) {
|
|
3686
|
-
return { content: "", tool_calls: toolCalls };
|
|
3687
|
-
}
|
|
3688
|
-
return { content: `Echo: ${content}` };
|
|
3689
|
-
}
|
|
3690
|
-
hasTool(params, name) {
|
|
3691
|
-
return !!params.tools?.some((t) => t.function.name === name);
|
|
3692
|
-
}
|
|
3693
|
-
id(prefix) {
|
|
3694
|
-
return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;
|
|
3695
|
-
}
|
|
3696
|
-
};
|
|
3697
|
-
|
|
3698
3686
|
// llm-providers/llm-utils.ts
|
|
3699
3687
|
function mergeChoices(choices) {
|
|
3700
3688
|
const contentParts = [];
|
|
@@ -4456,10 +4444,12 @@ var BaseBearerAuthTransport = class {
|
|
|
4456
4444
|
inner;
|
|
4457
4445
|
apiKey;
|
|
4458
4446
|
baseUrl;
|
|
4459
|
-
|
|
4447
|
+
version;
|
|
4448
|
+
constructor(inner, apiKey, baseUrl, version) {
|
|
4460
4449
|
this.inner = inner;
|
|
4461
4450
|
this.apiKey = apiKey;
|
|
4462
4451
|
this.baseUrl = baseUrl ?? this.getDefaultBaseUrl();
|
|
4452
|
+
this.version = version;
|
|
4463
4453
|
}
|
|
4464
4454
|
buildFullUrl(path9) {
|
|
4465
4455
|
if (path9.startsWith("/")) {
|
|
@@ -4473,6 +4463,9 @@ var BaseBearerAuthTransport = class {
|
|
|
4473
4463
|
}
|
|
4474
4464
|
const base = headers ? { ...headers } : {};
|
|
4475
4465
|
base.Authorization = `Bearer ${this.apiKey}`;
|
|
4466
|
+
if (!base["User-Agent"] && this.version) {
|
|
4467
|
+
base["User-Agent"] = `nuvin-cli/${this.version}`;
|
|
4468
|
+
}
|
|
4476
4469
|
return base;
|
|
4477
4470
|
}
|
|
4478
4471
|
async get(url, headers, signal) {
|
|
@@ -4492,8 +4485,8 @@ var BaseBearerAuthTransport = class {
|
|
|
4492
4485
|
// transports/simple-bearer-transport.ts
|
|
4493
4486
|
var SimpleBearerAuthTransport = class extends BaseBearerAuthTransport {
|
|
4494
4487
|
defaultUrl;
|
|
4495
|
-
constructor(inner, defaultBaseUrl, apiKey, baseUrl) {
|
|
4496
|
-
super(inner, apiKey, baseUrl ?? defaultBaseUrl);
|
|
4488
|
+
constructor(inner, defaultBaseUrl, apiKey, baseUrl, version) {
|
|
4489
|
+
super(inner, apiKey, baseUrl ?? defaultBaseUrl, version);
|
|
4497
4490
|
this.defaultUrl = defaultBaseUrl;
|
|
4498
4491
|
}
|
|
4499
4492
|
getDefaultBaseUrl() {
|
|
@@ -4502,8 +4495,8 @@ var SimpleBearerAuthTransport = class extends BaseBearerAuthTransport {
|
|
|
4502
4495
|
};
|
|
4503
4496
|
|
|
4504
4497
|
// transports/transport-factory.ts
|
|
4505
|
-
function createTransport(
|
|
4506
|
-
return new SimpleBearerAuthTransport(inner, defaultBaseUrl, apiKey, baseUrl);
|
|
4498
|
+
function createTransport(inner, defaultBaseUrl, apiKey, baseUrl, version) {
|
|
4499
|
+
return new SimpleBearerAuthTransport(inner, defaultBaseUrl, apiKey, baseUrl, version);
|
|
4507
4500
|
}
|
|
4508
4501
|
|
|
4509
4502
|
// llm-providers/llm-github.ts
|
|
@@ -4980,9 +4973,8 @@ var llm_provider_config_default = {
|
|
|
4980
4973
|
providers: [
|
|
4981
4974
|
{
|
|
4982
4975
|
name: "deepinfra",
|
|
4983
|
-
|
|
4976
|
+
type: "openai-compat",
|
|
4984
4977
|
baseUrl: "https://api.deepinfra.com/v1/openai",
|
|
4985
|
-
transportName: "deepinfra",
|
|
4986
4978
|
features: {
|
|
4987
4979
|
promptCaching: false,
|
|
4988
4980
|
getModels: true
|
|
@@ -4990,9 +4982,8 @@ var llm_provider_config_default = {
|
|
|
4990
4982
|
},
|
|
4991
4983
|
{
|
|
4992
4984
|
name: "openrouter",
|
|
4993
|
-
|
|
4985
|
+
type: "openai-compat",
|
|
4994
4986
|
baseUrl: "https://openrouter.ai/api/v1",
|
|
4995
|
-
transportName: "openrouter",
|
|
4996
4987
|
features: {
|
|
4997
4988
|
promptCaching: true,
|
|
4998
4989
|
getModels: true,
|
|
@@ -5001,9 +4992,8 @@ var llm_provider_config_default = {
|
|
|
5001
4992
|
},
|
|
5002
4993
|
{
|
|
5003
4994
|
name: "zai",
|
|
5004
|
-
|
|
4995
|
+
type: "openai-compat",
|
|
5005
4996
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
|
5006
|
-
transportName: "zai",
|
|
5007
4997
|
features: {
|
|
5008
4998
|
promptCaching: false,
|
|
5009
4999
|
getModels: false
|
|
@@ -5011,9 +5001,8 @@ var llm_provider_config_default = {
|
|
|
5011
5001
|
},
|
|
5012
5002
|
{
|
|
5013
5003
|
name: "moonshot",
|
|
5014
|
-
|
|
5004
|
+
type: "openai-compat",
|
|
5015
5005
|
baseUrl: "https://api.moonshot.ai/v1",
|
|
5016
|
-
transportName: "moonshot",
|
|
5017
5006
|
features: {
|
|
5018
5007
|
promptCaching: false,
|
|
5019
5008
|
getModels: true
|
|
@@ -5026,15 +5015,13 @@ var llm_provider_config_default = {
|
|
|
5026
5015
|
var providers = llm_provider_config_default.providers;
|
|
5027
5016
|
var GenericLLM = class extends BaseLLM {
|
|
5028
5017
|
opts;
|
|
5029
|
-
transportName;
|
|
5030
5018
|
includeUsage;
|
|
5031
|
-
|
|
5032
|
-
constructor(
|
|
5019
|
+
modelConfig;
|
|
5020
|
+
constructor(baseUrl, modelConfig, opts = {}) {
|
|
5033
5021
|
const { enablePromptCaching = false, includeUsage = false, ...restOpts } = opts;
|
|
5034
5022
|
super(opts.apiUrl || baseUrl, { enablePromptCaching });
|
|
5035
|
-
this.transportName = transportName;
|
|
5036
5023
|
this.includeUsage = includeUsage;
|
|
5037
|
-
this.
|
|
5024
|
+
this.modelConfig = modelConfig;
|
|
5038
5025
|
this.opts = restOpts;
|
|
5039
5026
|
}
|
|
5040
5027
|
createTransport() {
|
|
@@ -5045,11 +5032,24 @@ var GenericLLM = class extends BaseLLM {
|
|
|
5045
5032
|
maxFileSize: 5 * 1024 * 1024,
|
|
5046
5033
|
captureResponseBody: true
|
|
5047
5034
|
});
|
|
5048
|
-
return createTransport(
|
|
5035
|
+
return createTransport(base, this.apiUrl, this.opts.apiKey, this.opts.apiUrl, this.opts.version);
|
|
5049
5036
|
}
|
|
5050
5037
|
async getModels(signal) {
|
|
5051
|
-
if (
|
|
5052
|
-
throw new Error(
|
|
5038
|
+
if (this.modelConfig === false) {
|
|
5039
|
+
throw new Error("Provider does not support getModels");
|
|
5040
|
+
}
|
|
5041
|
+
if (Array.isArray(this.modelConfig)) {
|
|
5042
|
+
return this.modelConfig.map((m) => typeof m === "string" ? { id: m } : m);
|
|
5043
|
+
}
|
|
5044
|
+
if (typeof this.modelConfig === "string") {
|
|
5045
|
+
const transport2 = this.createTransport();
|
|
5046
|
+
const res2 = await transport2.get(this.modelConfig, void 0, signal);
|
|
5047
|
+
if (!res2.ok) {
|
|
5048
|
+
const text = await res2.text();
|
|
5049
|
+
throw new Error(`Failed to fetch models: ${res2.status} ${text}`);
|
|
5050
|
+
}
|
|
5051
|
+
const data2 = await res2.json();
|
|
5052
|
+
return data2.data;
|
|
5053
5053
|
}
|
|
5054
5054
|
const transport = this.createTransport();
|
|
5055
5055
|
const res = await transport.get("/models", void 0, signal);
|
|
@@ -5075,23 +5075,62 @@ var GenericLLM = class extends BaseLLM {
|
|
|
5075
5075
|
return super.streamCompletion(enhancedParams, handlers, signal);
|
|
5076
5076
|
}
|
|
5077
5077
|
};
|
|
5078
|
-
function
|
|
5079
|
-
|
|
5078
|
+
function normalizeModelConfig(config) {
|
|
5079
|
+
if (config.models !== void 0) {
|
|
5080
|
+
return config.models;
|
|
5081
|
+
}
|
|
5082
|
+
return config.features.getModels ?? false;
|
|
5083
|
+
}
|
|
5084
|
+
function mergeProviders(customProviders) {
|
|
5085
|
+
const merged = /* @__PURE__ */ new Map();
|
|
5086
|
+
for (const provider of providers) {
|
|
5087
|
+
merged.set(provider.name.toLowerCase(), provider);
|
|
5088
|
+
}
|
|
5089
|
+
if (customProviders) {
|
|
5090
|
+
for (const [name, custom] of Object.entries(customProviders)) {
|
|
5091
|
+
if (!custom.baseUrl) {
|
|
5092
|
+
continue;
|
|
5093
|
+
}
|
|
5094
|
+
const existing = merged.get(name.toLowerCase());
|
|
5095
|
+
const providerConfig = {
|
|
5096
|
+
name,
|
|
5097
|
+
type: custom.type ?? "openai-compat",
|
|
5098
|
+
baseUrl: custom.baseUrl,
|
|
5099
|
+
models: custom.models ?? false,
|
|
5100
|
+
features: existing?.features ?? {
|
|
5101
|
+
promptCaching: false,
|
|
5102
|
+
getModels: custom.models !== false,
|
|
5103
|
+
includeUsage: false
|
|
5104
|
+
}
|
|
5105
|
+
};
|
|
5106
|
+
merged.set(name.toLowerCase(), providerConfig);
|
|
5107
|
+
}
|
|
5108
|
+
}
|
|
5109
|
+
return Array.from(merged.values());
|
|
5110
|
+
}
|
|
5111
|
+
function createLLM(providerName, options = {}, customProviders) {
|
|
5112
|
+
const allProviders = mergeProviders(customProviders);
|
|
5113
|
+
const config = allProviders.find((p) => p.name.toLowerCase() === providerName.toLowerCase());
|
|
5080
5114
|
if (!config) {
|
|
5081
|
-
throw new Error(`Unknown LLM provider: ${providerName}. Available: ${
|
|
5115
|
+
throw new Error(`Unknown LLM provider: ${providerName}. Available: ${allProviders.map((p) => p.name).join(", ")}`);
|
|
5082
5116
|
}
|
|
5083
|
-
|
|
5117
|
+
const modelConfig = normalizeModelConfig(config);
|
|
5118
|
+
return new GenericLLM(config.baseUrl, modelConfig, {
|
|
5084
5119
|
...options,
|
|
5085
5120
|
enablePromptCaching: options.enablePromptCaching ?? config.features.promptCaching,
|
|
5086
5121
|
includeUsage: options.includeUsage ?? config.features.includeUsage
|
|
5087
5122
|
});
|
|
5088
5123
|
}
|
|
5089
|
-
function getAvailableProviders() {
|
|
5090
|
-
|
|
5124
|
+
function getAvailableProviders(customProviders) {
|
|
5125
|
+
const allProviders = mergeProviders(customProviders);
|
|
5126
|
+
return allProviders.map((p) => p.name);
|
|
5091
5127
|
}
|
|
5092
|
-
function supportsGetModels(providerName) {
|
|
5093
|
-
const
|
|
5094
|
-
|
|
5128
|
+
function supportsGetModels(providerName, customProviders) {
|
|
5129
|
+
const allProviders = mergeProviders(customProviders);
|
|
5130
|
+
const config = allProviders.find((p) => p.name.toLowerCase() === providerName.toLowerCase());
|
|
5131
|
+
if (!config) return false;
|
|
5132
|
+
const modelConfig = normalizeModelConfig(config);
|
|
5133
|
+
return modelConfig !== false;
|
|
5095
5134
|
}
|
|
5096
5135
|
|
|
5097
5136
|
// mcp/mcp-client.ts
|
|
@@ -5404,7 +5443,6 @@ export {
|
|
|
5404
5443
|
DefaultDelegationService,
|
|
5405
5444
|
DefaultSpecialistAgentFactory,
|
|
5406
5445
|
DelegationServiceFactory,
|
|
5407
|
-
EchoLLM,
|
|
5408
5446
|
GithubLLM,
|
|
5409
5447
|
InMemoryMemory,
|
|
5410
5448
|
InMemoryMetadata,
|