@nuvin/nuvin-core 1.0.0 → 1.0.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.
package/dist/VERSION CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "version": "1.0.0",
3
- "commit": "63191c8"
2
+ "version": "1.0.1",
3
+ "commit": "d5c55a1"
4
4
  }
package/dist/index.d.ts CHANGED
@@ -799,7 +799,7 @@ declare class SystemClock implements Clock {
799
799
  }
800
800
 
801
801
  declare class SimpleCost implements CostCalculator {
802
- estimate(_model: string, _usage?: UsageData): number | undefined;
802
+ estimate(_model: string, usage?: UsageData): number | undefined;
803
803
  }
804
804
 
805
805
  declare class NoopReminders implements RemindersPort {
@@ -1151,42 +1151,6 @@ declare class GithubAuthTransport implements HttpTransport {
1151
1151
  postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
1152
1152
  }
1153
1153
 
1154
- declare class OpenRouterAuthTransport implements HttpTransport {
1155
- private readonly inner;
1156
- private readonly apiKey?;
1157
- private readonly baseUrl;
1158
- constructor(inner: FetchTransport, apiKey?: string, baseUrl?: string);
1159
- private buildFullUrl;
1160
- private makeAuthHeaders;
1161
- get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
1162
- postJson(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
1163
- postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
1164
- }
1165
-
1166
- declare class DeepInfraAuthTransport implements HttpTransport {
1167
- private readonly inner;
1168
- private readonly apiKey?;
1169
- private readonly baseUrl;
1170
- constructor(inner: FetchTransport, apiKey?: string, baseUrl?: string);
1171
- private buildFullUrl;
1172
- private makeAuthHeaders;
1173
- get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
1174
- postJson(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
1175
- postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
1176
- }
1177
-
1178
- declare class ZAIAuthTransport implements HttpTransport {
1179
- private readonly inner;
1180
- private readonly apiKey?;
1181
- private readonly baseUrl;
1182
- constructor(inner: FetchTransport, apiKey?: string, baseUrl?: string);
1183
- private buildFullUrl;
1184
- private makeAuthHeaders;
1185
- get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
1186
- postJson(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
1187
- postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
1188
- }
1189
-
1190
1154
  declare class LLMError extends Error {
1191
1155
  readonly statusCode?: number;
1192
1156
  readonly isRetryable: boolean;
@@ -1222,138 +1186,6 @@ declare class GithubLLM extends BaseLLM implements LLMPort {
1222
1186
  protected createTransport(): GithubAuthTransport;
1223
1187
  }
1224
1188
 
1225
- type OpenRouterOptions = {
1226
- apiKey?: string;
1227
- apiUrl?: string;
1228
- httpLogFile?: string;
1229
- enablePromptCaching?: boolean;
1230
- includeUsage?: boolean;
1231
- };
1232
- type OpenRouterModel = {
1233
- id: string;
1234
- canonical_slug: string;
1235
- hugging_face_id: string;
1236
- name: string;
1237
- created: number;
1238
- description: string;
1239
- context_length: number;
1240
- architecture: {
1241
- modality: string;
1242
- input_modalities: string[];
1243
- output_modalities: string[];
1244
- tokenizer: string;
1245
- instruct_type: string | null;
1246
- };
1247
- pricing: {
1248
- prompt: string;
1249
- completion: string;
1250
- request: string;
1251
- image: string;
1252
- web_search: string;
1253
- internal_reasoning: string;
1254
- input_cache_read: string;
1255
- };
1256
- top_provider: {
1257
- context_length: number;
1258
- max_completion_tokens: number | null;
1259
- is_moderated: boolean;
1260
- };
1261
- per_request_limits: {
1262
- prompt_tokens: string;
1263
- completion_tokens: string;
1264
- } | null;
1265
- supported_parameters: string[];
1266
- default_parameters: {
1267
- temperature: number | null;
1268
- top_p: number | null;
1269
- frequency_penalty: number | null;
1270
- };
1271
- };
1272
- declare class OpenRouterLLM extends BaseLLM implements LLMPort {
1273
- private readonly includeUsage;
1274
- constructor(opts?: OpenRouterOptions);
1275
- private readonly opts;
1276
- protected createTransport(): OpenRouterAuthTransport;
1277
- generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
1278
- streamCompletion(params: CompletionParams, handlers?: {
1279
- onChunk?: (delta: string, usage?: UsageData) => void;
1280
- onToolCallDelta?: (tc: ToolCall) => void;
1281
- onStreamFinish?: (finishReason?: string, usage?: UsageData) => void;
1282
- }, signal?: AbortSignal): Promise<CompletionResult>;
1283
- getModels(signal?: AbortSignal): Promise<OpenRouterModel[]>;
1284
- }
1285
-
1286
- type DeepInfraOptions = {
1287
- apiKey?: string;
1288
- apiUrl?: string;
1289
- httpLogFile?: string;
1290
- };
1291
- type DeepInfraModel = {
1292
- id: string;
1293
- object: string;
1294
- created: number;
1295
- owned_by: string;
1296
- root: string;
1297
- parent: string | null;
1298
- metadata: {
1299
- description: string;
1300
- context_length: number;
1301
- max_tokens: number;
1302
- pricing: {
1303
- input_tokens: number;
1304
- output_tokens: number;
1305
- cache_read_tokens?: number;
1306
- };
1307
- tags: string[];
1308
- };
1309
- };
1310
- declare class DeepInfraLLM extends BaseLLM implements LLMPort {
1311
- private readonly opts;
1312
- constructor(opts?: DeepInfraOptions);
1313
- protected createTransport(): DeepInfraAuthTransport;
1314
- getModels(signal?: AbortSignal): Promise<DeepInfraModel[]>;
1315
- }
1316
-
1317
- type ZaiOptions = {
1318
- apiKey?: string;
1319
- apiUrl?: string;
1320
- httpLogFile?: string;
1321
- };
1322
- declare class ZaiLLM extends BaseLLM implements LLMPort {
1323
- private readonly opts;
1324
- constructor(opts?: ZaiOptions);
1325
- protected createTransport(): ZAIAuthTransport;
1326
- }
1327
-
1328
- type AnthropicOptions = {
1329
- apiKey?: string;
1330
- oauth?: {
1331
- type: 'oauth';
1332
- access: string;
1333
- refresh: string;
1334
- expires: number;
1335
- };
1336
- apiUrl?: string;
1337
- httpLogFile?: string;
1338
- };
1339
- declare class AnthropicLLM {
1340
- private transport;
1341
- private readonly opts;
1342
- private readonly apiUrl;
1343
- constructor(opts?: AnthropicOptions);
1344
- private getTransport;
1345
- private transformToAnthropicMessages;
1346
- private transformTools;
1347
- private transformToolChoice;
1348
- private transformResponse;
1349
- generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
1350
- streamCompletion(params: CompletionParams, handlers?: {
1351
- onChunk?: (delta: string, usage?: UsageData) => void;
1352
- onToolCallDelta?: (tc: ToolCall) => void;
1353
- onStreamFinish?: (finishReason?: string, usage?: UsageData) => void;
1354
- }, signal?: AbortSignal): Promise<CompletionResult>;
1355
- }
1356
-
1357
1189
  type AnthropicAISDKOptions = {
1358
1190
  apiKey?: string;
1359
1191
  oauth?: {
@@ -1394,6 +1226,17 @@ declare class AnthropicAISDKLLM {
1394
1226
  }, signal?: AbortSignal): Promise<CompletionResult>;
1395
1227
  }
1396
1228
 
1229
+ interface LLMOptions {
1230
+ apiKey?: string;
1231
+ apiUrl?: string;
1232
+ httpLogFile?: string;
1233
+ enablePromptCaching?: boolean;
1234
+ includeUsage?: boolean;
1235
+ }
1236
+ declare function createLLM(providerName: string, options?: LLMOptions): LLMPort;
1237
+ declare function getAvailableProviders(): string[];
1238
+ declare function supportsGetModels(providerName: string): boolean;
1239
+
1397
1240
  type MCPHttpOptions = {
1398
1241
  type: 'http';
1399
1242
  url: string;
@@ -1483,4 +1326,4 @@ declare function resolveBackspaces(s: string): string;
1483
1326
  declare function stripAnsiAndControls(s: string): string;
1484
1327
  declare function canonicalizeTerminalPaste(raw: string): string;
1485
1328
 
1486
- export { AGENT_CREATOR_SYSTEM_PROMPT, type AgentAwareToolPort, type AgentCatalog, type AgentConfig, type AgentEvent, AgentEventTypes, AgentFilePersistence, AgentManager, AgentManagerCommandRunner, AgentOrchestrator, AgentRegistry, type AgentTemplate, AnthropicAISDKLLM, AnthropicLLM, type AssignParams, BashTool, CompositeToolPort, type Conversation, ConversationContext, type ConversationMetadata, type ConversationSnapshot, ConversationStore, CoreMCPClient, DeepInfraLLM, type DeepInfraModel, DefaultDelegationPolicy, DefaultDelegationResultFormatter, DefaultDelegationService, DefaultSpecialistAgentFactory, type DelegationService, type DelegationServiceConfig, DelegationServiceFactory, EchoLLM, type FolderTreeOptions, GithubLLM, InMemoryMemory, InMemoryMetadata, JsonFileMemoryPersistence, type LLMConfig, LLMError, type LLMFactory, type LLMPort, LLMResolver, type MCPConfig, type MCPServerConfig, MCPToolPort, type MemoryPort, MemoryPortMetadataAdapter, type Message, type MessageContent, type MessageContentPart, type MetadataPort, NoopReminders, OpenRouterLLM, type OpenRouterModel, 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, ZaiLLM, buildAgentCreationPrompt, buildInjectedSystem, canonicalizeTerminalPaste, generateFolderTree, loadMCPConfig, normalizeNewlines, renderTemplate, resolveBackspaces, resolveCarriageReturns, stripAnsiAndControls };
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, EchoLLM, 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
@@ -1251,9 +1251,8 @@ var SystemClock = class {
1251
1251
 
1252
1252
  // cost.ts
1253
1253
  var SimpleCost = class {
1254
- // Demo cost: $0.00 (undefined) to avoid implying pricing; could be extended
1255
- estimate(_model, _usage) {
1256
- return void 0;
1254
+ estimate(_model, usage) {
1255
+ return usage?.cost;
1257
1256
  }
1258
1257
  };
1259
1258
 
@@ -3794,9 +3793,7 @@ var BaseLLM = class {
3794
3793
  }
3795
3794
  }
3796
3795
  }
3797
- const userAssistantMessages = messages.filter(
3798
- (msg) => msg.role === "user" || msg.role === "assistant"
3799
- );
3796
+ const userAssistantMessages = messages.filter((msg) => msg.role === "user" || msg.role === "assistant");
3800
3797
  const lastTwoIndices = [];
3801
3798
  if (userAssistantMessages.length >= 2) {
3802
3799
  for (let i = userAssistantMessages.length - 2; i < userAssistantMessages.length; i++) {
@@ -3839,7 +3836,8 @@ var BaseLLM = class {
3839
3836
  ...enhancedParams.usage && { usage: enhancedParams.usage }
3840
3837
  };
3841
3838
  if (enhancedParams.tools && enhancedParams.tools.length > 0) body.tools = enhancedParams.tools;
3842
- if (enhancedParams.tool_choice && enhancedParams.tools && enhancedParams.tools.length > 0) body.tool_choice = enhancedParams.tool_choice;
3839
+ if (enhancedParams.tool_choice && enhancedParams.tools && enhancedParams.tools.length > 0)
3840
+ body.tool_choice = enhancedParams.tool_choice;
3843
3841
  const res = await this.getTransport().postJson("/chat/completions", body, void 0, signal);
3844
3842
  if (!res.ok) {
3845
3843
  const text = await res.text();
@@ -3864,7 +3862,8 @@ var BaseLLM = class {
3864
3862
  ...enhancedParams.usage && { usage: enhancedParams.usage }
3865
3863
  };
3866
3864
  if (enhancedParams.tools && enhancedParams.tools.length > 0) body.tools = enhancedParams.tools;
3867
- if (enhancedParams.tool_choice && enhancedParams.tools && enhancedParams.tools.length > 0) body.tool_choice = enhancedParams.tool_choice;
3865
+ if (enhancedParams.tool_choice && enhancedParams.tools && enhancedParams.tools.length > 0)
3866
+ body.tool_choice = enhancedParams.tool_choice;
3868
3867
  const res = await this.getTransport().postStream(
3869
3868
  "/chat/completions",
3870
3869
  body,
@@ -3883,6 +3882,7 @@ var BaseLLM = class {
3883
3882
  let content = "";
3884
3883
  const mergedToolCalls = [];
3885
3884
  let usage;
3885
+ let lastFinishReason;
3886
3886
  const flushEvent = (rawEvent) => {
3887
3887
  const lines = rawEvent.split("\n");
3888
3888
  const dataLines = [];
@@ -3895,11 +3895,15 @@ var BaseLLM = class {
3895
3895
  try {
3896
3896
  const evt = JSON.parse(dataStr);
3897
3897
  const choices = Array.isArray(evt.choices) ? evt.choices : [];
3898
- const finishReason = choices.find((ch) => ch.finish_reason)?.finish_reason;
3899
- if (evt.usage) {
3900
- usage = normalizeUsage(evt.usage);
3901
- if (finishReason && handlers.onStreamFinish) {
3902
- handlers.onStreamFinish(finishReason, usage);
3898
+ const finishReason = choices.find((ch) => ch.finish_reason && ch.finish_reason !== null)?.finish_reason;
3899
+ if (finishReason) {
3900
+ lastFinishReason = finishReason;
3901
+ }
3902
+ const usageData = evt.usage || choices[0]?.usage;
3903
+ if (usageData) {
3904
+ usage = normalizeUsage(usageData);
3905
+ if (lastFinishReason && handlers.onStreamFinish) {
3906
+ handlers.onStreamFinish(lastFinishReason, usage);
3903
3907
  } else {
3904
3908
  handlers.onChunk?.("", usage);
3905
3909
  }
@@ -4447,91 +4451,15 @@ var GithubAuthTransport = class {
4447
4451
  }
4448
4452
  };
4449
4453
 
4450
- // transports/openrouter-transport.ts
4451
- var OpenRouterAuthTransport = class {
4454
+ // transports/base-bearer-auth-transport.ts
4455
+ var BaseBearerAuthTransport = class {
4452
4456
  inner;
4453
4457
  apiKey;
4454
4458
  baseUrl;
4455
4459
  constructor(inner, apiKey, baseUrl) {
4456
4460
  this.inner = inner;
4457
4461
  this.apiKey = apiKey;
4458
- this.baseUrl = baseUrl ?? "https://openrouter.ai/api/v1";
4459
- }
4460
- buildFullUrl(path9) {
4461
- if (path9.startsWith("/")) {
4462
- return `${this.baseUrl}${path9}`;
4463
- }
4464
- return path9;
4465
- }
4466
- makeAuthHeaders(headers) {
4467
- if (!this.apiKey || this.apiKey.trim() === "") {
4468
- throw new Error("API key missing");
4469
- }
4470
- const base = headers ? { ...headers } : {};
4471
- base["Authorization"] = `Bearer ${this.apiKey}`;
4472
- return base;
4473
- }
4474
- async get(url, headers, signal) {
4475
- const fullUrl = this.buildFullUrl(url);
4476
- return this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
4477
- }
4478
- async postJson(url, body, headers, signal) {
4479
- const fullUrl = this.buildFullUrl(url);
4480
- return this.inner.postJson(fullUrl, body, this.makeAuthHeaders(headers), signal);
4481
- }
4482
- async postStream(url, body, headers, signal) {
4483
- const fullUrl = this.buildFullUrl(url);
4484
- return this.inner.postStream(fullUrl, body, this.makeAuthHeaders(headers), signal);
4485
- }
4486
- };
4487
-
4488
- // transports/deepinfra-transport.ts
4489
- var DeepInfraAuthTransport = class {
4490
- inner;
4491
- apiKey;
4492
- baseUrl;
4493
- constructor(inner, apiKey, baseUrl) {
4494
- this.inner = inner;
4495
- this.apiKey = apiKey;
4496
- this.baseUrl = baseUrl ?? "https://api.deepinfra.com/v1/openai";
4497
- }
4498
- buildFullUrl(path9) {
4499
- if (path9.startsWith("/")) {
4500
- return `${this.baseUrl}${path9}`;
4501
- }
4502
- return path9;
4503
- }
4504
- makeAuthHeaders(headers) {
4505
- if (!this.apiKey || this.apiKey.trim() === "") {
4506
- throw new Error("API key missing");
4507
- }
4508
- const base = headers ? { ...headers } : {};
4509
- base["Authorization"] = `Bearer ${this.apiKey}`;
4510
- return base;
4511
- }
4512
- async get(url, headers, signal) {
4513
- const fullUrl = this.buildFullUrl(url);
4514
- return this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
4515
- }
4516
- async postJson(url, body, headers, signal) {
4517
- const fullUrl = this.buildFullUrl(url);
4518
- return this.inner.postJson(fullUrl, body, this.makeAuthHeaders(headers), signal);
4519
- }
4520
- async postStream(url, body, headers, signal) {
4521
- const fullUrl = this.buildFullUrl(url);
4522
- return this.inner.postStream(fullUrl, body, this.makeAuthHeaders(headers), signal);
4523
- }
4524
- };
4525
-
4526
- // transports/zai-transport.ts
4527
- var ZAIAuthTransport = class {
4528
- inner;
4529
- apiKey;
4530
- baseUrl;
4531
- constructor(inner, apiKey, baseUrl) {
4532
- this.inner = inner;
4533
- this.apiKey = apiKey;
4534
- this.baseUrl = baseUrl ?? "https://api.z.ai/api/coding/paas/v4";
4462
+ this.baseUrl = baseUrl ?? this.getDefaultBaseUrl();
4535
4463
  }
4536
4464
  buildFullUrl(path9) {
4537
4465
  if (path9.startsWith("/")) {
@@ -4561,105 +4489,23 @@ var ZAIAuthTransport = class {
4561
4489
  }
4562
4490
  };
4563
4491
 
4564
- // transports/anthropic-transport.ts
4565
- var AnthropicAuthTransport = class {
4566
- apiKey;
4567
- oauth;
4568
- baseUrl;
4569
- inner;
4570
- constructor(inner, opts = {}) {
4571
- this.inner = inner;
4572
- this.apiKey = opts.apiKey;
4573
- this.oauth = opts.oauth;
4574
- this.baseUrl = opts.baseUrl || "https://api.anthropic.com";
4575
- }
4576
- async refreshOAuth(signal) {
4577
- if (!this.oauth?.refresh) return;
4578
- if (this.oauth.expires > Date.now()) return;
4579
- try {
4580
- const response = await fetch("https://console.anthropic.com/v1/oauth/token", {
4581
- method: "POST",
4582
- headers: {
4583
- "Content-Type": "application/json"
4584
- },
4585
- body: JSON.stringify({
4586
- grant_type: "refresh_token",
4587
- refresh_token: this.oauth.refresh,
4588
- client_id: "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
4589
- }),
4590
- signal
4591
- });
4592
- if (!response.ok) {
4593
- throw new Error(`OAuth token refresh failed: ${response.status} ${response.statusText}`);
4594
- }
4595
- const data = await response.json();
4596
- this.oauth = {
4597
- type: "oauth",
4598
- access: data.access_token,
4599
- refresh: data.refresh_token || this.oauth.refresh,
4600
- expires: Date.now() + data.expires_in * 1e3
4601
- };
4602
- } catch (error) {
4603
- throw new Error(`Failed to refresh OAuth token: ${error instanceof Error ? error.message : String(error)}`);
4604
- }
4605
- }
4606
- buildFullUrl(path9) {
4607
- if (path9.startsWith("/")) {
4608
- return `${this.baseUrl}${path9}`;
4609
- }
4610
- return path9;
4611
- }
4612
- getAuthHeaders() {
4613
- const headers = {};
4614
- if (this.oauth) {
4615
- headers.authorization = `Bearer ${this.oauth.access}`;
4616
- } else if (this.apiKey) {
4617
- headers["x-api-key"] = this.apiKey;
4618
- } else {
4619
- throw new Error("No authentication credentials provided");
4620
- }
4621
- headers["anthropic-version"] = "2023-06-01";
4622
- headers["anthropic-beta"] = [
4623
- "claude-code-20250219",
4624
- "interleaved-thinking-2025-05-14",
4625
- "fine-grained-tool-streaming-2025-05-14"
4626
- ].join(",");
4627
- return headers;
4628
- }
4629
- async get(url, headers, signal) {
4630
- if (this.oauth) {
4631
- await this.refreshOAuth(signal);
4632
- }
4633
- const fullUrl = this.buildFullUrl(url);
4634
- const authHeaders = this.getAuthHeaders();
4635
- const mergedHeaders = { ...authHeaders, ...headers };
4636
- return this.inner.get(fullUrl, mergedHeaders, signal);
4492
+ // transports/simple-bearer-transport.ts
4493
+ var SimpleBearerAuthTransport = class extends BaseBearerAuthTransport {
4494
+ defaultUrl;
4495
+ constructor(inner, defaultBaseUrl, apiKey, baseUrl) {
4496
+ super(inner, apiKey, baseUrl ?? defaultBaseUrl);
4497
+ this.defaultUrl = defaultBaseUrl;
4637
4498
  }
4638
- async postJson(url, body, headers, signal) {
4639
- if (this.oauth) {
4640
- await this.refreshOAuth(signal);
4641
- }
4642
- const fullUrl = this.buildFullUrl(url);
4643
- const authHeaders = this.getAuthHeaders();
4644
- const mergedHeaders = { ...authHeaders, ...headers };
4645
- return this.inner.postJson(fullUrl, body, mergedHeaders, signal);
4646
- }
4647
- async postStream(url, body, headers, signal) {
4648
- if (this.oauth) {
4649
- await this.refreshOAuth(signal);
4650
- }
4651
- const fullUrl = this.buildFullUrl(url);
4652
- const authHeaders = this.getAuthHeaders();
4653
- const mergedHeaders = { ...authHeaders, ...headers };
4654
- return this.inner.postStream(fullUrl, body, mergedHeaders, signal);
4655
- }
4656
- // Method to update OAuth credentials (useful for token refresh from config)
4657
- updateCredentials(opts) {
4658
- if (opts.apiKey) this.apiKey = opts.apiKey;
4659
- if (opts.oauth) this.oauth = opts.oauth;
4499
+ getDefaultBaseUrl() {
4500
+ return this.defaultUrl;
4660
4501
  }
4661
4502
  };
4662
4503
 
4504
+ // transports/transport-factory.ts
4505
+ function createTransport(_name, inner, defaultBaseUrl, apiKey, baseUrl) {
4506
+ return new SimpleBearerAuthTransport(inner, defaultBaseUrl, apiKey, baseUrl);
4507
+ }
4508
+
4663
4509
  // llm-providers/llm-github.ts
4664
4510
  var GithubLLM = class extends BaseLLM {
4665
4511
  opts;
@@ -4685,392 +4531,6 @@ var GithubLLM = class extends BaseLLM {
4685
4531
  }
4686
4532
  };
4687
4533
 
4688
- // llm-providers/llm-openrouter.ts
4689
- var OpenRouterLLM = class extends BaseLLM {
4690
- includeUsage;
4691
- constructor(opts = {}) {
4692
- const { enablePromptCaching = true, includeUsage = true, ...restOpts } = opts;
4693
- super("https://openrouter.ai/api/v1", { enablePromptCaching });
4694
- this.includeUsage = includeUsage;
4695
- this.opts = restOpts;
4696
- }
4697
- opts;
4698
- createTransport() {
4699
- const base = new FetchTransport({ persistFile: this.opts.httpLogFile });
4700
- return new OpenRouterAuthTransport(base, this.opts.apiKey, this.apiUrl);
4701
- }
4702
- async generateCompletion(params, signal) {
4703
- let enhancedParams = params;
4704
- if (this.includeUsage && !enhancedParams.usage) {
4705
- enhancedParams = { ...enhancedParams, usage: { include: true } };
4706
- }
4707
- return super.generateCompletion(enhancedParams, signal);
4708
- }
4709
- async streamCompletion(params, handlers, signal) {
4710
- let enhancedParams = params;
4711
- if (this.includeUsage && !enhancedParams.usage) {
4712
- enhancedParams = { ...enhancedParams, usage: { include: true } };
4713
- }
4714
- return super.streamCompletion(enhancedParams, handlers, signal);
4715
- }
4716
- async getModels(signal) {
4717
- const transport = this.createTransport();
4718
- const res = await transport.get("/models", void 0, signal);
4719
- if (!res.ok) {
4720
- const text = await res.text();
4721
- throw new Error(`Failed to fetch models: ${res.status} ${text}`);
4722
- }
4723
- const data = await res.json();
4724
- return data.data;
4725
- }
4726
- };
4727
-
4728
- // llm-providers/llm-deepinfra.ts
4729
- var DeepInfraLLM = class extends BaseLLM {
4730
- opts;
4731
- constructor(opts = {}) {
4732
- super(opts.apiUrl || "https://api.deepinfra.com/v1/openai");
4733
- this.opts = opts;
4734
- }
4735
- createTransport() {
4736
- const base = new FetchTransport({ persistFile: this.opts.httpLogFile });
4737
- return new DeepInfraAuthTransport(base, this.opts.apiKey || process.env.DEEPINFRA_API_KEY, this.opts.apiUrl);
4738
- }
4739
- async getModels(signal) {
4740
- const transport = this.createTransport();
4741
- const res = await transport.get("/models", void 0, signal);
4742
- if (!res.ok) {
4743
- const text = await res.text();
4744
- throw new Error(`Failed to fetch models: ${res.status} ${text}`);
4745
- }
4746
- const data = await res.json();
4747
- return data.data;
4748
- }
4749
- };
4750
-
4751
- // llm-providers/llm-zai.ts
4752
- var ZaiLLM = class extends BaseLLM {
4753
- opts;
4754
- constructor(opts = {}) {
4755
- super("https://api.z.ai/api/coding/paas/v4");
4756
- this.opts = opts;
4757
- }
4758
- createTransport() {
4759
- const base = new FetchTransport({
4760
- persistFile: this.opts.httpLogFile,
4761
- logLevel: "INFO",
4762
- enableConsoleLog: false,
4763
- maxFileSize: 5 * 1024 * 1024,
4764
- // 5MB before rotation
4765
- captureResponseBody: true
4766
- // Disable for better performance
4767
- });
4768
- return new ZAIAuthTransport(base, this.opts.apiKey, this.apiUrl);
4769
- }
4770
- };
4771
-
4772
- // llm-providers/llm-anthropic.ts
4773
- var AnthropicLLM = class {
4774
- transport = null;
4775
- opts;
4776
- apiUrl;
4777
- constructor(opts = {}) {
4778
- this.opts = opts;
4779
- this.apiUrl = opts.apiUrl || "https://api.anthropic.com";
4780
- }
4781
- getTransport() {
4782
- if (!this.transport) {
4783
- const base = new FetchTransport({
4784
- persistFile: this.opts.httpLogFile
4785
- });
4786
- this.transport = new AnthropicAuthTransport(base, {
4787
- apiKey: this.opts.apiKey,
4788
- oauth: this.opts.oauth,
4789
- baseUrl: this.apiUrl
4790
- });
4791
- }
4792
- return this.transport;
4793
- }
4794
- transformToAnthropicMessages(messages) {
4795
- const systemMessages = [];
4796
- const anthropicMessages = [];
4797
- for (const msg of messages) {
4798
- if (msg.role === "system") {
4799
- if (typeof msg.content === "string") {
4800
- systemMessages.push(msg.content);
4801
- } else if (Array.isArray(msg.content)) {
4802
- for (const part of msg.content) {
4803
- if (part.type === "text") {
4804
- systemMessages.push(part.text);
4805
- }
4806
- }
4807
- }
4808
- continue;
4809
- }
4810
- if (msg.role === "tool") {
4811
- const lastMsg = anthropicMessages[anthropicMessages.length - 1];
4812
- if (lastMsg && lastMsg.role === "user" && Array.isArray(lastMsg.content)) {
4813
- lastMsg.content.push({
4814
- type: "tool_result",
4815
- tool_use_id: msg.tool_call_id || "",
4816
- content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
4817
- });
4818
- } else {
4819
- anthropicMessages.push({
4820
- role: "user",
4821
- content: [
4822
- {
4823
- type: "tool_result",
4824
- tool_use_id: msg.tool_call_id || "",
4825
- content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
4826
- }
4827
- ]
4828
- });
4829
- }
4830
- continue;
4831
- }
4832
- const content = [];
4833
- if (typeof msg.content === "string" && msg.content) {
4834
- content.push({ type: "text", text: msg.content });
4835
- } else if (Array.isArray(msg.content)) {
4836
- for (const part of msg.content) {
4837
- if (part.type === "text") {
4838
- content.push({ type: "text", text: part.text });
4839
- } else if (part.type === "image_url") {
4840
- const url = part.image_url.url;
4841
- if (url.startsWith("data:")) {
4842
- const match = url.match(/^data:([^;]+);base64,(.+)$/);
4843
- if (match) {
4844
- content.push({
4845
- type: "image",
4846
- source: {
4847
- type: "base64",
4848
- media_type: match[1],
4849
- data: match[2]
4850
- }
4851
- });
4852
- }
4853
- }
4854
- }
4855
- }
4856
- }
4857
- if (msg.tool_calls) {
4858
- for (const toolCall of msg.tool_calls) {
4859
- content.push({
4860
- type: "tool_use",
4861
- id: toolCall.id,
4862
- name: toolCall.function.name,
4863
- input: JSON.parse(toolCall.function.arguments || "{}")
4864
- });
4865
- }
4866
- }
4867
- if (content.length > 0) {
4868
- anthropicMessages.push({
4869
- role: msg.role === "assistant" ? "assistant" : "user",
4870
- content: content.length === 1 && content[0].type === "text" ? content[0].text : content
4871
- });
4872
- }
4873
- }
4874
- const result = {
4875
- messages: anthropicMessages
4876
- };
4877
- if (systemMessages.length > 0) {
4878
- result.system = [
4879
- {
4880
- type: "text",
4881
- text: "You are Claude Code, Anthropic's official CLI for Claude."
4882
- },
4883
- { type: "text", text: systemMessages.join("\n\n") }
4884
- ];
4885
- }
4886
- return result;
4887
- }
4888
- transformTools(tools) {
4889
- if (!tools || tools.length === 0) return void 0;
4890
- return tools.map((tool) => ({
4891
- name: tool.function.name,
4892
- description: tool.function.description,
4893
- input_schema: tool.function.parameters
4894
- }));
4895
- }
4896
- transformToolChoice(toolChoice) {
4897
- if (!toolChoice || toolChoice === "auto") {
4898
- return { type: "auto" };
4899
- }
4900
- if (toolChoice === "none") {
4901
- return void 0;
4902
- }
4903
- if (typeof toolChoice === "object" && toolChoice.type === "function") {
4904
- return { type: "tool", name: toolChoice.function.name };
4905
- }
4906
- return { type: "auto" };
4907
- }
4908
- transformResponse(response) {
4909
- let content = "";
4910
- const tool_calls = [];
4911
- for (const block of response.content) {
4912
- if (block.type === "text") {
4913
- content += block.text;
4914
- } else if (block.type === "tool_use") {
4915
- tool_calls.push({
4916
- id: block.id,
4917
- type: "function",
4918
- function: {
4919
- name: block.name,
4920
- arguments: JSON.stringify(block.input)
4921
- }
4922
- });
4923
- }
4924
- }
4925
- const usage = {
4926
- prompt_tokens: response.usage.input_tokens,
4927
- completion_tokens: response.usage.output_tokens,
4928
- total_tokens: response.usage.input_tokens + response.usage.output_tokens
4929
- };
4930
- return {
4931
- content,
4932
- ...tool_calls.length > 0 ? { tool_calls } : {},
4933
- usage
4934
- };
4935
- }
4936
- async generateCompletion(params, signal) {
4937
- const { system, messages } = this.transformToAnthropicMessages(params.messages);
4938
- const tools = this.transformTools(params.tools);
4939
- const tool_choice = tools ? this.transformToolChoice(params.tool_choice) : void 0;
4940
- const body = {
4941
- model: params.model,
4942
- messages,
4943
- max_tokens: params.maxTokens ?? 10240,
4944
- temperature: params.temperature,
4945
- stream: false,
4946
- // ...(params.topP !== undefined && { top_p: params.topP }),
4947
- ...system && { system },
4948
- ...tools && { tools },
4949
- ...tool_choice && { tool_choice }
4950
- };
4951
- const res = await this.getTransport().postJson("/v1/messages", body, void 0, signal);
4952
- if (!res.ok) {
4953
- const text = await res.text();
4954
- throw new Error(text || `Anthropic API error ${res.status}`);
4955
- }
4956
- const data = await res.json();
4957
- return this.transformResponse(data);
4958
- }
4959
- async streamCompletion(params, handlers = {}, signal) {
4960
- const { system, messages } = this.transformToAnthropicMessages(params.messages);
4961
- const tools = this.transformTools(params.tools);
4962
- const tool_choice = tools ? this.transformToolChoice(params.tool_choice) : void 0;
4963
- const body = {
4964
- model: params.model,
4965
- messages,
4966
- max_tokens: params.maxTokens ?? 10240,
4967
- temperature: params.temperature,
4968
- stream: true,
4969
- // ...(params.topP !== undefined && { top_p: params.topP }),
4970
- ...system && { system },
4971
- ...tools && { tools },
4972
- ...tool_choice && { tool_choice }
4973
- };
4974
- const res = await this.getTransport().postStream("/v1/messages", body, { Accept: "text/event-stream" }, signal);
4975
- if (!res.ok) {
4976
- const text = await res.text();
4977
- throw new Error(text || `Anthropic stream error ${res.status}`);
4978
- }
4979
- const reader = res.body?.getReader();
4980
- if (!reader) return { content: "" };
4981
- const decoder = new TextDecoder("utf-8");
4982
- let buffer = "";
4983
- let content = "";
4984
- const toolCalls = /* @__PURE__ */ new Map();
4985
- let usage;
4986
- let inputTokens = 0;
4987
- let stopReason = null;
4988
- const processEvent = (eventData) => {
4989
- try {
4990
- const event = JSON.parse(eventData);
4991
- if (event.type === "message_start") {
4992
- if (event.message?.usage) {
4993
- inputTokens = event.message.usage.input_tokens || 0;
4994
- }
4995
- } else if (event.type === "content_block_start") {
4996
- const block = event.content_block;
4997
- if (block?.type === "tool_use" && "id" in block && "name" in block) {
4998
- toolCalls.set(event.index, {
4999
- id: String(block.id),
5000
- type: "function",
5001
- function: {
5002
- name: String(block.name) || "",
5003
- arguments: ""
5004
- }
5005
- });
5006
- }
5007
- } else if (event.type === "content_block_delta") {
5008
- if (event.delta.type === "text_delta") {
5009
- const textDelta = event.delta.text;
5010
- if (textDelta) {
5011
- content += textDelta;
5012
- handlers.onChunk?.(textDelta);
5013
- }
5014
- } else if (event.delta.type === "input_json_delta") {
5015
- const toolCall = toolCalls.get(event.index);
5016
- if (toolCall) {
5017
- toolCall.function.arguments += event.delta.partial_json;
5018
- handlers.onToolCallDelta?.(toolCall);
5019
- }
5020
- }
5021
- } else if (event.type === "message_delta") {
5022
- if (event.delta.stop_reason) {
5023
- stopReason = event.delta.stop_reason;
5024
- }
5025
- if (event.usage) {
5026
- usage = {
5027
- prompt_tokens: inputTokens,
5028
- completion_tokens: event.usage.output_tokens,
5029
- total_tokens: inputTokens + event.usage.output_tokens
5030
- };
5031
- }
5032
- } else if (event.type === "message_stop") {
5033
- if (handlers.onStreamFinish) {
5034
- handlers.onStreamFinish(stopReason || void 0, usage);
5035
- }
5036
- }
5037
- } catch (err2) {
5038
- }
5039
- };
5040
- while (true) {
5041
- const { value, done } = await reader.read();
5042
- if (done) break;
5043
- const chunk = decoder.decode(value, { stream: true });
5044
- buffer += chunk;
5045
- const lines = buffer.split("\n");
5046
- buffer = lines.pop() || "";
5047
- for (const line of lines) {
5048
- if (line.startsWith("data: ")) {
5049
- const data = line.slice(6).trim();
5050
- if (data && data !== "[DONE]") {
5051
- processEvent(data);
5052
- }
5053
- }
5054
- }
5055
- }
5056
- if (buffer.trim()) {
5057
- const line = buffer.trim();
5058
- if (line.startsWith("data: ")) {
5059
- const data = line.slice(6).trim();
5060
- if (data && data !== "[DONE]") {
5061
- processEvent(data);
5062
- }
5063
- }
5064
- }
5065
- const tool_calls = toolCalls.size > 0 ? Array.from(toolCalls.values()) : void 0;
5066
- return {
5067
- content,
5068
- ...tool_calls && { tool_calls },
5069
- ...usage && { usage }
5070
- };
5071
- }
5072
- };
5073
-
5074
4534
  // llm-providers/llm-anthropic-aisdk.ts
5075
4535
  import { createAnthropic } from "@ai-sdk/anthropic";
5076
4536
  import {
@@ -5515,6 +4975,125 @@ var AnthropicAISDKLLM = class {
5515
4975
  }
5516
4976
  };
5517
4977
 
4978
+ // llm-providers/llm-provider-config.json
4979
+ var llm_provider_config_default = {
4980
+ providers: [
4981
+ {
4982
+ name: "deepinfra",
4983
+ className: "DeepInfraLLM",
4984
+ baseUrl: "https://api.deepinfra.com/v1/openai",
4985
+ transportName: "deepinfra",
4986
+ features: {
4987
+ promptCaching: false,
4988
+ getModels: true
4989
+ }
4990
+ },
4991
+ {
4992
+ name: "openrouter",
4993
+ className: "OpenRouterLLM",
4994
+ baseUrl: "https://openrouter.ai/api/v1",
4995
+ transportName: "openrouter",
4996
+ features: {
4997
+ promptCaching: true,
4998
+ getModels: true,
4999
+ includeUsage: true
5000
+ }
5001
+ },
5002
+ {
5003
+ name: "zai",
5004
+ className: "ZaiLLM",
5005
+ baseUrl: "https://api.z.ai/api/coding/paas/v4",
5006
+ transportName: "zai",
5007
+ features: {
5008
+ promptCaching: false,
5009
+ getModels: false
5010
+ }
5011
+ },
5012
+ {
5013
+ name: "moonshot",
5014
+ className: "MoonshotLLM",
5015
+ baseUrl: "https://api.moonshot.ai/v1",
5016
+ transportName: "moonshot",
5017
+ features: {
5018
+ promptCaching: false,
5019
+ getModels: true
5020
+ }
5021
+ }
5022
+ ]
5023
+ };
5024
+
5025
+ // llm-providers/llm-factory.ts
5026
+ var providers = llm_provider_config_default.providers;
5027
+ var GenericLLM = class extends BaseLLM {
5028
+ opts;
5029
+ transportName;
5030
+ includeUsage;
5031
+ supportsModels;
5032
+ constructor(transportName, baseUrl, supportsModels, opts = {}) {
5033
+ const { enablePromptCaching = false, includeUsage = false, ...restOpts } = opts;
5034
+ super(opts.apiUrl || baseUrl, { enablePromptCaching });
5035
+ this.transportName = transportName;
5036
+ this.includeUsage = includeUsage;
5037
+ this.supportsModels = supportsModels;
5038
+ this.opts = restOpts;
5039
+ }
5040
+ createTransport() {
5041
+ const base = new FetchTransport({
5042
+ persistFile: this.opts.httpLogFile,
5043
+ logLevel: "INFO",
5044
+ enableConsoleLog: false,
5045
+ maxFileSize: 5 * 1024 * 1024,
5046
+ captureResponseBody: true
5047
+ });
5048
+ return createTransport(this.transportName, base, this.apiUrl, this.opts.apiKey, this.opts.apiUrl);
5049
+ }
5050
+ async getModels(signal) {
5051
+ if (!this.supportsModels) {
5052
+ throw new Error(`Provider ${this.transportName} does not support getModels`);
5053
+ }
5054
+ const transport = this.createTransport();
5055
+ const res = await transport.get("/models", void 0, signal);
5056
+ if (!res.ok) {
5057
+ const text = await res.text();
5058
+ throw new Error(`Failed to fetch models: ${res.status} ${text}`);
5059
+ }
5060
+ const data = await res.json();
5061
+ return data.data;
5062
+ }
5063
+ async generateCompletion(params, signal) {
5064
+ let enhancedParams = params;
5065
+ if (this.includeUsage && !enhancedParams.usage) {
5066
+ enhancedParams = { ...enhancedParams, usage: { include: true } };
5067
+ }
5068
+ return super.generateCompletion(enhancedParams, signal);
5069
+ }
5070
+ async streamCompletion(params, handlers, signal) {
5071
+ let enhancedParams = params;
5072
+ if (this.includeUsage && !enhancedParams.usage) {
5073
+ enhancedParams = { ...enhancedParams, usage: { include: true } };
5074
+ }
5075
+ return super.streamCompletion(enhancedParams, handlers, signal);
5076
+ }
5077
+ };
5078
+ function createLLM(providerName, options = {}) {
5079
+ const config = providers.find((p) => p.name.toLowerCase() === providerName.toLowerCase());
5080
+ if (!config) {
5081
+ throw new Error(`Unknown LLM provider: ${providerName}. Available: ${providers.map((p) => p.name).join(", ")}`);
5082
+ }
5083
+ return new GenericLLM(config.transportName, config.baseUrl, config.features.getModels ?? false, {
5084
+ ...options,
5085
+ enablePromptCaching: options.enablePromptCaching ?? config.features.promptCaching,
5086
+ includeUsage: options.includeUsage ?? config.features.includeUsage
5087
+ });
5088
+ }
5089
+ function getAvailableProviders() {
5090
+ return providers.map((p) => p.name);
5091
+ }
5092
+ function supportsGetModels(providerName) {
5093
+ const config = providers.find((p) => p.name.toLowerCase() === providerName.toLowerCase());
5094
+ return config?.features.getModels ?? false;
5095
+ }
5096
+
5518
5097
  // mcp/mcp-client.ts
5519
5098
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
5520
5099
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
@@ -5815,13 +5394,11 @@ export {
5815
5394
  AgentOrchestrator,
5816
5395
  AgentRegistry,
5817
5396
  AnthropicAISDKLLM,
5818
- AnthropicLLM,
5819
5397
  BashTool,
5820
5398
  CompositeToolPort,
5821
5399
  ConversationContext,
5822
5400
  ConversationStore,
5823
5401
  CoreMCPClient,
5824
- DeepInfraLLM,
5825
5402
  DefaultDelegationPolicy,
5826
5403
  DefaultDelegationResultFormatter,
5827
5404
  DefaultDelegationService,
@@ -5837,7 +5414,6 @@ export {
5837
5414
  MCPToolPort,
5838
5415
  MemoryPortMetadataAdapter,
5839
5416
  NoopReminders,
5840
- OpenRouterLLM,
5841
5417
  PersistedMemory,
5842
5418
  PersistingConsoleEventPort,
5843
5419
  RuntimeEnv,
@@ -5846,15 +5422,17 @@ export {
5846
5422
  SimpleId,
5847
5423
  SystemClock,
5848
5424
  ToolRegistry,
5849
- ZaiLLM,
5850
5425
  buildAgentCreationPrompt,
5851
5426
  buildInjectedSystem,
5852
5427
  canonicalizeTerminalPaste,
5428
+ createLLM,
5853
5429
  generateFolderTree,
5430
+ getAvailableProviders,
5854
5431
  loadMCPConfig,
5855
5432
  normalizeNewlines,
5856
5433
  renderTemplate,
5857
5434
  resolveBackspaces,
5858
5435
  resolveCarriageReturns,
5859
- stripAnsiAndControls
5436
+ stripAnsiAndControls,
5437
+ supportsGetModels
5860
5438
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuvin/nuvin-core",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "",
5
5
  "private": false,
6
6
  "main": "dist/index.js",