@corbat-tech/coco 2.3.0 → 2.4.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/cli/index.js CHANGED
@@ -1363,10 +1363,12 @@ var init_openai = __esm({
1363
1363
  provider: this.id
1364
1364
  });
1365
1365
  }
1366
+ const defaultHeaders = this.id === "kimi-code" ? { "User-Agent": "claude-code" } : {};
1366
1367
  this.client = new OpenAI({
1367
1368
  apiKey,
1368
1369
  baseURL: config.baseUrl,
1369
- timeout: config.timeout ?? 12e4
1370
+ timeout: config.timeout ?? 12e4,
1371
+ defaultHeaders
1370
1372
  });
1371
1373
  }
1372
1374
  /**
@@ -4001,8 +4003,10 @@ var init_pricing = __esm({
4001
4003
  deepseek: { inputPerMillion: 0.14, outputPerMillion: 0.28, contextWindow: 128e3 },
4002
4004
  // Very cheap
4003
4005
  together: { inputPerMillion: 0.2, outputPerMillion: 0.2, contextWindow: 32768 },
4004
- huggingface: { inputPerMillion: 0, outputPerMillion: 0, contextWindow: 32768 }
4006
+ huggingface: { inputPerMillion: 0, outputPerMillion: 0, contextWindow: 32768 },
4005
4007
  // Free tier
4008
+ qwen: { inputPerMillion: 0.3, outputPerMillion: 1.2, contextWindow: 131072 }
4009
+ // qwen-coder-plus pricing
4006
4010
  };
4007
4011
  }
4008
4012
  });
@@ -4496,6 +4500,8 @@ function getApiKey(provider) {
4496
4500
  return process.env["TOGETHER_API_KEY"];
4497
4501
  case "huggingface":
4498
4502
  return process.env["HF_TOKEN"] ?? process.env["HUGGINGFACE_API_KEY"];
4503
+ case "qwen":
4504
+ return process.env["DASHSCOPE_API_KEY"] ?? process.env["QWEN_API_KEY"];
4499
4505
  default:
4500
4506
  return void 0;
4501
4507
  }
@@ -4528,6 +4534,8 @@ function getBaseUrl(provider) {
4528
4534
  return process.env["TOGETHER_BASE_URL"] ?? "https://api.together.xyz/v1";
4529
4535
  case "huggingface":
4530
4536
  return process.env["HF_BASE_URL"] ?? "https://api-inference.huggingface.co/v1";
4537
+ case "qwen":
4538
+ return process.env["DASHSCOPE_BASE_URL"] ?? "https://dashscope-intl.aliyuncs.com/compatible-mode/v1";
4531
4539
  default:
4532
4540
  return void 0;
4533
4541
  }
@@ -4562,6 +4570,8 @@ function getDefaultModel(provider) {
4562
4570
  return process.env["TOGETHER_MODEL"] ?? "Qwen/Qwen2.5-Coder-32B-Instruct";
4563
4571
  case "huggingface":
4564
4572
  return process.env["HF_MODEL"] ?? "Qwen/Qwen2.5-Coder-32B-Instruct";
4573
+ case "qwen":
4574
+ return process.env["QWEN_MODEL"] ?? "qwen-coder-plus";
4565
4575
  default:
4566
4576
  return "gpt-5.3-codex";
4567
4577
  }
@@ -4669,7 +4679,8 @@ var init_env = __esm({
4669
4679
  "mistral",
4670
4680
  "deepseek",
4671
4681
  "together",
4672
- "huggingface"
4682
+ "huggingface",
4683
+ "qwen"
4673
4684
  ];
4674
4685
  cachedPreferences = null;
4675
4686
  env = {
@@ -4780,6 +4791,10 @@ async function createProvider(type, config = {}) {
4780
4791
  provider = new OpenAIProvider("huggingface", "HuggingFace Inference");
4781
4792
  mergedConfig.baseUrl = mergedConfig.baseUrl ?? "https://api-inference.huggingface.co/v1";
4782
4793
  break;
4794
+ case "qwen":
4795
+ provider = new OpenAIProvider("qwen", "Alibaba Qwen");
4796
+ mergedConfig.baseUrl = mergedConfig.baseUrl ?? "https://dashscope-intl.aliyuncs.com/compatible-mode/v1";
4797
+ break;
4783
4798
  default:
4784
4799
  throw new ProviderError(`Unknown provider type: ${type}`, {
4785
4800
  provider: type
@@ -4812,6 +4827,7 @@ function listProviders() {
4812
4827
  { id: "deepseek", name: "DeepSeek", configured: !!getApiKey("deepseek") },
4813
4828
  { id: "together", name: "Together AI", configured: !!getApiKey("together") },
4814
4829
  { id: "huggingface", name: "HuggingFace Inference", configured: !!getApiKey("huggingface") },
4830
+ { id: "qwen", name: "Alibaba Qwen (DashScope)", configured: !!getApiKey("qwen") },
4815
4831
  { id: "lmstudio", name: "LM Studio (Local)", configured: true },
4816
4832
  { id: "ollama", name: "Ollama (Local)", configured: true }
4817
4833
  ];
@@ -24175,6 +24191,70 @@ var PROVIDER_DEFINITIONS = {
24175
24191
  }
24176
24192
  ]
24177
24193
  },
24194
+ // Alibaba Qwen - DashScope API (OpenAI-compatible)
24195
+ qwen: {
24196
+ id: "qwen",
24197
+ name: "Alibaba Qwen",
24198
+ emoji: "\u{1F7E6}",
24199
+ description: "Qwen models via Alibaba DashScope \u2014 strong coding at low cost",
24200
+ envVar: "DASHSCOPE_API_KEY",
24201
+ apiKeyUrl: "https://modelstudio.console.alibabacloud.com",
24202
+ docsUrl: "https://help.aliyun.com/zh/model-studio/developer-reference/",
24203
+ baseUrl: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
24204
+ supportsCustomModels: true,
24205
+ openaiCompatible: true,
24206
+ paymentType: "api",
24207
+ features: {
24208
+ streaming: true,
24209
+ functionCalling: true,
24210
+ vision: true
24211
+ },
24212
+ models: [
24213
+ {
24214
+ id: "qwen-coder-plus",
24215
+ name: "Qwen Coder Plus",
24216
+ description: "Best coding model \u2014 Qwen3 based, 131K context",
24217
+ contextWindow: 131072,
24218
+ maxOutputTokens: 8192,
24219
+ recommended: true
24220
+ },
24221
+ {
24222
+ id: "qwen-max",
24223
+ name: "Qwen Max",
24224
+ description: "Most capable general model \u2014 32K context",
24225
+ contextWindow: 32768,
24226
+ maxOutputTokens: 8192
24227
+ },
24228
+ {
24229
+ id: "qwen-plus",
24230
+ name: "Qwen Plus",
24231
+ description: "Good balance of speed and quality \u2014 131K context",
24232
+ contextWindow: 131072,
24233
+ maxOutputTokens: 8192
24234
+ },
24235
+ {
24236
+ id: "qwen-turbo",
24237
+ name: "Qwen Turbo",
24238
+ description: "Fastest and cheapest \u2014 1M context",
24239
+ contextWindow: 1e6,
24240
+ maxOutputTokens: 8192
24241
+ },
24242
+ {
24243
+ id: "qwen2.5-coder-32b-instruct",
24244
+ name: "Qwen 2.5 Coder 32B",
24245
+ description: "Open weights coding model \u2014 32K context",
24246
+ contextWindow: 32768,
24247
+ maxOutputTokens: 8192
24248
+ },
24249
+ {
24250
+ id: "qwq-plus",
24251
+ name: "QwQ Plus",
24252
+ description: "Reasoning model \u2014 chain-of-thought, 131K context",
24253
+ contextWindow: 131072,
24254
+ maxOutputTokens: 8192
24255
+ }
24256
+ ]
24257
+ },
24178
24258
  // HuggingFace Inference - Free tier for open models
24179
24259
  huggingface: {
24180
24260
  id: "huggingface",
@@ -28434,6 +28514,18 @@ async function testConnection(provider, apiKey, model, baseUrl) {
28434
28514
  p25.log.message(chalk25.dim(" \u2022 Ensure your account has credits"));
28435
28515
  p25.log.message(chalk25.dim(" \u2022 Try model: moonshot-v1-8k (most compatible)"));
28436
28516
  }
28517
+ if (provider.id === "qwen") {
28518
+ p25.log.message(chalk25.dim("\n\u{1F7E6} Alibaba Qwen specific:"));
28519
+ p25.log.message(chalk25.dim(" \u2022 International console: modelstudio.console.alibabacloud.com"));
28520
+ p25.log.message(chalk25.dim(" \u2022 International API endpoint: dashscope-intl.aliyuncs.com"));
28521
+ p25.log.message(chalk25.dim(" \u2022 China domestic endpoint: dashscope.aliyuncs.com"));
28522
+ p25.log.message(
28523
+ chalk25.dim(
28524
+ " \u2022 If using China endpoint, set: DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1"
28525
+ )
28526
+ );
28527
+ p25.log.message(chalk25.dim(" \u2022 Ensure your account has API access enabled"));
28528
+ }
28437
28529
  return false;
28438
28530
  }
28439
28531
  spinner19.stop(chalk25.green("\u2705 Connected successfully!"));
@@ -28725,7 +28817,6 @@ async function selectProviderInteractively(providers, currentProviderId) {
28725
28817
  let lastTotalLines = 0;
28726
28818
  const clearPrevious = () => {
28727
28819
  if (lastTotalLines === 0) return;
28728
- process.stdout.write("\x1B[2K\r");
28729
28820
  for (let i = 0; i < lastTotalLines; i++) {
28730
28821
  process.stdout.write("\x1B[1A\x1B[2K");
28731
28822
  }
@@ -28745,10 +28836,6 @@ async function selectProviderInteractively(providers, currentProviderId) {
28745
28836
  line += chalk25.bgBlue.white(truncate(provider.description, descWidth, "\u2026"));
28746
28837
  process.stdout.write(line + "\n");
28747
28838
  totalLines++;
28748
- if (provider.description.length > descWidth) {
28749
- process.stdout.write(chalk25.bgBlue.white(` ${provider.description}`) + "\n");
28750
- totalLines++;
28751
- }
28752
28839
  } else {
28753
28840
  const marker = isCurrent ? chalk25.green(" \u25CF ") : chalk25.dim(" \u25CB ");
28754
28841
  const status = provider.isConfigured ? chalk25.green("\u2713") : chalk25.dim("\u25CB");
@@ -43605,9 +43692,28 @@ async function startRepl(options = {}) {
43605
43692
  if (!input && !hasPendingImage()) continue;
43606
43693
  let agentMessage = null;
43607
43694
  if (input && isSlashCommand(input)) {
43695
+ const prevProviderType = session.config.provider.type;
43696
+ const prevProviderModel = session.config.provider.model;
43608
43697
  const { command, args } = parseSlashCommand(input);
43609
43698
  const commandResult = await executeSlashCommand(command, args, session);
43610
43699
  if (commandResult.shouldExit) break;
43700
+ if (session.config.provider.type !== prevProviderType || session.config.provider.model !== prevProviderModel) {
43701
+ try {
43702
+ const newInternalId = getInternalProviderId(session.config.provider.type);
43703
+ provider = await createProvider(newInternalId, {
43704
+ model: session.config.provider.model || void 0,
43705
+ maxTokens: session.config.provider.maxTokens
43706
+ });
43707
+ setAgentProvider(provider);
43708
+ initializeContextManager(session, provider);
43709
+ } catch (err) {
43710
+ session.config.provider.type = prevProviderType;
43711
+ session.config.provider.model = prevProviderModel;
43712
+ renderError(
43713
+ `Failed to switch provider: ${err instanceof Error ? err.message : String(err)}`
43714
+ );
43715
+ }
43716
+ }
43611
43717
  if (commandResult.forkPrompt) {
43612
43718
  agentMessage = commandResult.forkPrompt;
43613
43719
  } else if (hasPendingImage()) {