@nuvin/nuvin-core 1.1.2 → 1.2.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 CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "version": "1.1.2",
3
- "commit": "76be190"
2
+ "version": "1.2.0",
3
+ "commit": "aafc9e1"
4
4
  }
package/dist/index.d.ts CHANGED
@@ -237,6 +237,7 @@ type ChatMessage = {
237
237
  tool_calls?: ToolCall[];
238
238
  tool_call_id?: string;
239
239
  name?: string;
240
+ [key: string]: unknown;
240
241
  };
241
242
  type CompletionParams = {
242
243
  messages: ChatMessage[];
@@ -264,6 +265,7 @@ type CompletionParams = {
264
265
  usage?: {
265
266
  include?: boolean;
266
267
  };
268
+ [key: string]: unknown;
267
269
  };
268
270
  type UsageData = {
269
271
  prompt_tokens?: number;
@@ -286,6 +288,7 @@ type CompletionResult = {
286
288
  content: string;
287
289
  tool_calls?: ToolCall[];
288
290
  usage?: UsageData;
291
+ [key: string]: unknown;
289
292
  };
290
293
  type Message = {
291
294
  id: string;
@@ -296,6 +299,7 @@ type Message = {
296
299
  tool_call_id?: string;
297
300
  name?: string;
298
301
  usage?: UsageData;
302
+ [key: string]: unknown;
299
303
  };
300
304
  type MessageResponse = {
301
305
  id: string;
@@ -335,6 +339,10 @@ interface LLMPort {
335
339
  onToolCallDelta?: (tc: ToolCall) => void;
336
340
  onStreamFinish?: (finishReason?: string, usage?: UsageData) => void;
337
341
  }, signal?: AbortSignal): Promise<CompletionResult>;
342
+ getModels?(signal?: AbortSignal): Promise<Array<{
343
+ id: string;
344
+ [key: string]: unknown;
345
+ }>>;
338
346
  }
339
347
  type LLMConfig = {
340
348
  provider?: string;
@@ -1174,7 +1182,7 @@ declare abstract class BaseLLM implements LLMPort {
1174
1182
  enablePromptCaching?: boolean;
1175
1183
  });
1176
1184
  protected abstract createTransport(): HttpTransport;
1177
- private getTransport;
1185
+ protected getTransport(): HttpTransport;
1178
1186
  protected applyCacheControl(params: CompletionParams): CompletionParams;
1179
1187
  generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
1180
1188
  streamCompletion(params: CompletionParams, handlers?: {
@@ -1190,10 +1198,32 @@ type GithubOptions = {
1190
1198
  apiUrl?: string;
1191
1199
  httpLogFile?: string;
1192
1200
  };
1201
+ type GithubModel = {
1202
+ id: string;
1203
+ name: string;
1204
+ capable_endpoints?: string[];
1205
+ supported_endpoints?: string[];
1206
+ capabilities: {
1207
+ family: string;
1208
+ type: string;
1209
+ limits?: {
1210
+ max_context_window_tokens?: number;
1211
+ max_output_tokens?: number;
1212
+ };
1213
+ };
1214
+ };
1193
1215
  declare class GithubLLM extends BaseLLM implements LLMPort {
1194
1216
  private readonly opts;
1195
1217
  constructor(opts?: GithubOptions);
1196
1218
  protected createTransport(): GithubAuthTransport;
1219
+ getModels(signal?: AbortSignal): Promise<GithubModel[]>;
1220
+ private handleError;
1221
+ generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
1222
+ streamCompletion(params: CompletionParams, handlers?: {
1223
+ onChunk?: (delta: string, usage?: UsageData) => void;
1224
+ onToolCallDelta?: (tc: ToolCall) => void;
1225
+ onStreamFinish?: (finishReason?: string, usage?: UsageData) => void;
1226
+ }, signal?: AbortSignal): Promise<CompletionResult>;
1197
1227
  }
1198
1228
 
1199
1229
  type AnthropicAISDKOptions = {
package/dist/index.js CHANGED
@@ -450,7 +450,13 @@ var AgentOrchestrator = class {
450
450
  });
451
451
  }
452
452
  await this.deps.memory.append(convo, [assistantMsg, ...toolResultMsgs]);
453
- accumulatedMessages.push({ role: "assistant", content: result.content ?? null, tool_calls: approvedCalls });
453
+ const { usage: _usage, ...extraField } = result;
454
+ accumulatedMessages.push({
455
+ ...extraField,
456
+ role: "assistant",
457
+ content: result.content ?? null,
458
+ tool_calls: approvedCalls
459
+ });
454
460
  for (const tr of toolResults) {
455
461
  const contentStr = tr.status === "error" ? String(tr.result) : typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
456
462
  accumulatedMessages.push({ role: "tool", content: contentStr, tool_call_id: tr.id, name: tr.name });
@@ -638,9 +644,18 @@ var SimpleContextBuilder = class {
638
644
  transformed.push({ role: "user", content: providerContent ?? "" });
639
645
  } else if (m.role === "assistant") {
640
646
  if (m.tool_calls && m.tool_calls.length > 0) {
641
- transformed.push({ role: "assistant", content: providerContent ?? null, tool_calls: m.tool_calls });
647
+ transformed.push({
648
+ ...m,
649
+ role: "assistant",
650
+ content: providerContent ?? null,
651
+ tool_calls: m.tool_calls
652
+ });
642
653
  } else {
643
- transformed.push({ role: "assistant", content: providerContent ?? "" });
654
+ transformed.push({
655
+ ...m,
656
+ role: "assistant",
657
+ content: providerContent ?? ""
658
+ });
644
659
  }
645
660
  } else if (m.role === "tool") {
646
661
  if (m.tool_call_id) {
@@ -3717,6 +3732,7 @@ var AgentFilePersistence = class {
3717
3732
  function mergeChoices(choices) {
3718
3733
  const contentParts = [];
3719
3734
  const mergedToolCalls = [];
3735
+ const extraFields = {};
3720
3736
  const collectText = (value) => {
3721
3737
  if (typeof value === "string") {
3722
3738
  const trimmed = value.trim();
@@ -3737,10 +3753,20 @@ function mergeChoices(choices) {
3737
3753
  if (!msg) continue;
3738
3754
  collectText(msg.content);
3739
3755
  if (Array.isArray(msg.tool_calls)) mergedToolCalls.push(...msg.tool_calls);
3756
+ const knownKeys = ["content", "tool_calls", "role"];
3757
+ for (const key of Object.keys(msg)) {
3758
+ if (!knownKeys.includes(key)) {
3759
+ extraFields[key] = msg[key];
3760
+ }
3761
+ }
3740
3762
  }
3741
3763
  const content = contentParts.join("\n\n");
3742
3764
  const tool_calls = mergedToolCalls.length ? mergedToolCalls : void 0;
3743
- return { content, ...tool_calls ? { tool_calls } : {} };
3765
+ return {
3766
+ content,
3767
+ ...tool_calls ? { tool_calls } : {},
3768
+ ...extraFields
3769
+ };
3744
3770
  }
3745
3771
  function normalizeUsage(usage) {
3746
3772
  if (!usage) return void 0;
@@ -3901,6 +3927,7 @@ var BaseLLM = class {
3901
3927
  const mergedToolCalls = [];
3902
3928
  let usage;
3903
3929
  let lastFinishReason;
3930
+ const extraFields = {};
3904
3931
  const flushEvent = (rawEvent) => {
3905
3932
  const lines = rawEvent.split("\n");
3906
3933
  const dataLines = [];
@@ -3941,6 +3968,16 @@ var BaseLLM = class {
3941
3968
  handlers.onChunk?.(textDelta);
3942
3969
  }
3943
3970
  }
3971
+ const knownKeys = ["role", "content", "tool_calls"];
3972
+ for (const key of Object.keys(delta)) {
3973
+ if (knownKeys.includes(key)) continue;
3974
+ const val = delta[key];
3975
+ if (typeof val === "string") {
3976
+ extraFields[key] = (extraFields[key] || "") + val;
3977
+ } else if (val !== void 0 && val !== null) {
3978
+ extraFields[key] = val;
3979
+ }
3980
+ }
3944
3981
  const toolDeltas = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];
3945
3982
  for (const td of toolDeltas) {
3946
3983
  let toolCall;
@@ -3948,6 +3985,7 @@ var BaseLLM = class {
3948
3985
  toolCall = mergedToolCalls.find((tc) => tc.id === td.id);
3949
3986
  if (!toolCall) {
3950
3987
  toolCall = {
3988
+ ...td,
3951
3989
  id: td.id,
3952
3990
  type: "function",
3953
3991
  function: { name: td.function?.name ?? "", arguments: "" }
@@ -3994,7 +4032,12 @@ var BaseLLM = class {
3994
4032
  if (buffer.trim()) flushEvent(buffer);
3995
4033
  content = content.replace(/^\n+/, "");
3996
4034
  const tool_calls = mergedToolCalls.length ? mergedToolCalls : void 0;
3997
- return { content, ...tool_calls ? { tool_calls } : {}, ...usage ? { usage } : {} };
4035
+ return {
4036
+ content,
4037
+ ...tool_calls ? { tool_calls } : {},
4038
+ ...usage ? { usage } : {},
4039
+ ...extraFields
4040
+ };
3998
4041
  }
3999
4042
  };
4000
4043
 
@@ -4364,8 +4407,9 @@ var GithubAuthTransport = class {
4364
4407
  method: "GET",
4365
4408
  headers: {
4366
4409
  Authorization: `Bearer ${this.accessToken}`,
4367
- "user-agent": "GitHubCopilotChat/0.31.3",
4368
- "editor-version": "vscode/1.104.2",
4410
+ "user-agent": "GitHubCopilotChat/0.33.1",
4411
+ "editor-version": "vscode/1.106.1",
4412
+ "x-github-api-version": "2025-10-01",
4369
4413
  accept: "application/json"
4370
4414
  },
4371
4415
  signal
@@ -4454,11 +4498,12 @@ var GithubAuthTransport = class {
4454
4498
  return res;
4455
4499
  }
4456
4500
  async postStream(url, body, headers, signal) {
4457
- if (!this.apiKey && this.accessToken) {
4501
+ let hdrs = this.makeAuthHeaders({ Accept: "text/event-stream", ...headers || {} }, body);
4502
+ if ((!this.apiKey || !hdrs.Authorization) && this.accessToken) {
4458
4503
  await this.exchangeToken(signal);
4504
+ hdrs = this.makeAuthHeaders({ Accept: "text/event-stream", ...headers || {} }, body);
4459
4505
  }
4460
4506
  const fullUrl = this.buildFullUrl(url);
4461
- const hdrs = this.makeAuthHeaders({ Accept: "text/event-stream", ...headers || {} }, body);
4462
4507
  let res = await this.inner.postStream(fullUrl, body, hdrs, signal);
4463
4508
  if (res.status === 401 && this.accessToken) {
4464
4509
  await this.exchangeToken(signal);
@@ -4552,6 +4597,49 @@ var GithubLLM = class extends BaseLLM {
4552
4597
  accessToken: this.opts.accessToken
4553
4598
  });
4554
4599
  }
4600
+ async getModels(signal) {
4601
+ const res = await this.getTransport().get("/models", void 0, signal);
4602
+ if (!res.ok) {
4603
+ const text = await res.text();
4604
+ throw new LLMError(text || `Failed to fetch models: ${res.status}`, res.status);
4605
+ }
4606
+ const body = await res.json();
4607
+ return body.data;
4608
+ }
4609
+ handleError(error, model) {
4610
+ if (error instanceof LLMError) {
4611
+ try {
4612
+ const errorBody = JSON.parse(error.message);
4613
+ if (errorBody?.error?.code === "unsupported_api_for_model") {
4614
+ throw new LLMError(
4615
+ `The model '${model}' is not supported for chat completions. Please select a different model using '/model'.`,
4616
+ error.statusCode,
4617
+ false
4618
+ // Not retryable
4619
+ );
4620
+ }
4621
+ } catch (e) {
4622
+ if (e instanceof LLMError && e.message.includes("not supported")) {
4623
+ throw e;
4624
+ }
4625
+ }
4626
+ }
4627
+ throw error;
4628
+ }
4629
+ async generateCompletion(params, signal) {
4630
+ try {
4631
+ return await super.generateCompletion(params, signal);
4632
+ } catch (error) {
4633
+ this.handleError(error, params.model);
4634
+ }
4635
+ }
4636
+ async streamCompletion(params, handlers, signal) {
4637
+ try {
4638
+ return await super.streamCompletion(params, handlers, signal);
4639
+ } catch (error) {
4640
+ this.handleError(error, params.model);
4641
+ }
4642
+ }
4555
4643
  };
4556
4644
 
4557
4645
  // llm-providers/llm-anthropic-aisdk.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuvin/nuvin-core",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "",
5
5
  "private": false,
6
6
  "main": "dist/index.js",