@corbat-tech/coco 2.4.1 → 2.5.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/cli/index.js +409 -144
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +161 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2911,11 +2911,12 @@ declare function createOutputExecutor(config?: Partial<OutputConfig>): OutputExe
|
|
|
2911
2911
|
* Anthropic provider implementation
|
|
2912
2912
|
*/
|
|
2913
2913
|
declare class AnthropicProvider implements LLMProvider {
|
|
2914
|
-
readonly id
|
|
2915
|
-
readonly name
|
|
2914
|
+
readonly id: string;
|
|
2915
|
+
readonly name: string;
|
|
2916
2916
|
private client;
|
|
2917
2917
|
private config;
|
|
2918
2918
|
private retryConfig;
|
|
2919
|
+
constructor(id?: string, name?: string);
|
|
2919
2920
|
/**
|
|
2920
2921
|
* Initialize the provider
|
|
2921
2922
|
*/
|
package/dist/index.js
CHANGED
|
@@ -153,7 +153,7 @@ function getBaseUrl(provider) {
|
|
|
153
153
|
case "kimi":
|
|
154
154
|
return process.env["KIMI_BASE_URL"] ?? "https://api.moonshot.ai/v1";
|
|
155
155
|
case "kimi-code":
|
|
156
|
-
return process.env["KIMI_CODE_BASE_URL"] ?? "https://api.kimi.com/coding
|
|
156
|
+
return process.env["KIMI_CODE_BASE_URL"] ?? "https://api.kimi.com/coding";
|
|
157
157
|
case "lmstudio":
|
|
158
158
|
return process.env["LMSTUDIO_BASE_URL"] ?? "http://localhost:1234/v1";
|
|
159
159
|
case "ollama":
|
|
@@ -8180,6 +8180,129 @@ function getLogger() {
|
|
|
8180
8180
|
return globalLogger;
|
|
8181
8181
|
}
|
|
8182
8182
|
|
|
8183
|
+
// src/utils/error-humanizer.ts
|
|
8184
|
+
function extractQuotedPath(msg) {
|
|
8185
|
+
const single = msg.match(/'([^']+)'/);
|
|
8186
|
+
if (single?.[1]) return single[1];
|
|
8187
|
+
const double = msg.match(/"([^"]+)"/);
|
|
8188
|
+
return double?.[1] ?? null;
|
|
8189
|
+
}
|
|
8190
|
+
function humanizeError(message, toolName) {
|
|
8191
|
+
const msg = message.trim();
|
|
8192
|
+
if (!msg) return msg;
|
|
8193
|
+
if (/ECONNREFUSED/i.test(msg)) {
|
|
8194
|
+
return "Connection refused \u2014 the server may not be running";
|
|
8195
|
+
}
|
|
8196
|
+
if (/ENOTFOUND/i.test(msg)) {
|
|
8197
|
+
return "Host not found \u2014 check the URL or your internet connection";
|
|
8198
|
+
}
|
|
8199
|
+
if (/EHOSTUNREACH/i.test(msg)) {
|
|
8200
|
+
return "Host unreachable \u2014 check your network connection";
|
|
8201
|
+
}
|
|
8202
|
+
if (/ECONNRESET/i.test(msg)) {
|
|
8203
|
+
return "Connection reset \u2014 the server closed the connection unexpectedly";
|
|
8204
|
+
}
|
|
8205
|
+
if (/ERR_INVALID_URL/i.test(msg)) {
|
|
8206
|
+
return "Invalid URL format \u2014 check the URL syntax";
|
|
8207
|
+
}
|
|
8208
|
+
if (/CERT_|ERR_CERT_|SSL_ERROR|UNABLE_TO_VERIFY_LEAF_SIGNATURE/i.test(msg)) {
|
|
8209
|
+
return "SSL/TLS certificate error \u2014 the server certificate may be untrusted";
|
|
8210
|
+
}
|
|
8211
|
+
if (/fetch failed|network error|Failed to fetch/i.test(msg)) {
|
|
8212
|
+
return "Network request failed \u2014 check your internet connection";
|
|
8213
|
+
}
|
|
8214
|
+
if (/ENOENT/i.test(msg)) {
|
|
8215
|
+
const path38 = extractQuotedPath(msg);
|
|
8216
|
+
return path38 ? `File or directory not found: ${path38}` : "File or directory not found";
|
|
8217
|
+
}
|
|
8218
|
+
if (/EACCES/i.test(msg)) {
|
|
8219
|
+
const path38 = extractQuotedPath(msg);
|
|
8220
|
+
return path38 ? `Permission denied: ${path38}` : "Permission denied \u2014 check file permissions";
|
|
8221
|
+
}
|
|
8222
|
+
if (/EISDIR/i.test(msg)) {
|
|
8223
|
+
return "Expected a file but found a directory at the specified path";
|
|
8224
|
+
}
|
|
8225
|
+
if (/ENOTDIR/i.test(msg)) {
|
|
8226
|
+
return "Expected a directory but found a file in the path";
|
|
8227
|
+
}
|
|
8228
|
+
if (/EEXIST/i.test(msg)) {
|
|
8229
|
+
return "File or directory already exists";
|
|
8230
|
+
}
|
|
8231
|
+
if (/ENOSPC/i.test(msg)) {
|
|
8232
|
+
return "No disk space left \u2014 free up some space and try again";
|
|
8233
|
+
}
|
|
8234
|
+
if (/EROFS/i.test(msg)) {
|
|
8235
|
+
return "Write failed \u2014 the file system is read-only";
|
|
8236
|
+
}
|
|
8237
|
+
if (/EMFILE|ENFILE/i.test(msg)) {
|
|
8238
|
+
return "Too many open files \u2014 try restarting and running again";
|
|
8239
|
+
}
|
|
8240
|
+
if (/not a git repository/i.test(msg)) {
|
|
8241
|
+
return "Not a git repository \u2014 run 'git init' to initialize one";
|
|
8242
|
+
}
|
|
8243
|
+
if (/nothing to commit/i.test(msg)) {
|
|
8244
|
+
return "Nothing to commit \u2014 the working tree is clean";
|
|
8245
|
+
}
|
|
8246
|
+
if (/merge conflict|CONFLICT/i.test(msg)) {
|
|
8247
|
+
return "Merge conflict detected \u2014 resolve the conflicts before continuing";
|
|
8248
|
+
}
|
|
8249
|
+
if (/non-fast-forward|rejected.*push/i.test(msg)) {
|
|
8250
|
+
return "Push rejected \u2014 pull the latest changes first (git pull)";
|
|
8251
|
+
}
|
|
8252
|
+
if (/authentication failed/i.test(msg) && /git/i.test(msg)) {
|
|
8253
|
+
return "Git authentication failed \u2014 check your credentials or SSH key";
|
|
8254
|
+
}
|
|
8255
|
+
if (/branch.*already exists/i.test(msg)) {
|
|
8256
|
+
return "Branch already exists \u2014 choose a different name or use the existing branch";
|
|
8257
|
+
}
|
|
8258
|
+
if (/detached HEAD/i.test(msg)) {
|
|
8259
|
+
return "Detached HEAD \u2014 checkout a branch to start committing";
|
|
8260
|
+
}
|
|
8261
|
+
if (/(bad revision|does not exist on|unknown revision)/i.test(msg)) {
|
|
8262
|
+
return "Git reference not found \u2014 the branch or commit may not exist";
|
|
8263
|
+
}
|
|
8264
|
+
if (/Unexpected token.*JSON|JSON\.parse|Unexpected end of JSON/i.test(msg)) {
|
|
8265
|
+
return "Failed to parse JSON \u2014 the data may be malformed";
|
|
8266
|
+
}
|
|
8267
|
+
if (/SyntaxError.*Unexpected token/i.test(msg)) {
|
|
8268
|
+
return "Syntax error in the data \u2014 check for formatting issues";
|
|
8269
|
+
}
|
|
8270
|
+
const moduleMatch = msg.match(/Cannot find module ['"]([^'"]+)['"]/i);
|
|
8271
|
+
if (moduleMatch) {
|
|
8272
|
+
return `Module not found: '${moduleMatch[1]}' \u2014 run the install command to add it`;
|
|
8273
|
+
}
|
|
8274
|
+
if (/ERR_MODULE_NOT_FOUND|MODULE_NOT_FOUND/i.test(msg)) {
|
|
8275
|
+
return "Required module not found \u2014 run the install command first";
|
|
8276
|
+
}
|
|
8277
|
+
if (/ERR_REQUIRE_ESM/i.test(msg)) {
|
|
8278
|
+
return "Module format mismatch \u2014 this package requires ESM (type: module)";
|
|
8279
|
+
}
|
|
8280
|
+
if (/command not found/i.test(msg) || /spawn.*ENOENT/i.test(msg) && toolName === "bash_exec") {
|
|
8281
|
+
const cmdMatch = msg.match(/Command '([^']+)' not found|spawn ([^\s]+) ENOENT/);
|
|
8282
|
+
const cmd = cmdMatch?.[1] ?? cmdMatch?.[2];
|
|
8283
|
+
return cmd ? `Command '${cmd}' not found \u2014 is it installed and in your PATH?` : "Command not found \u2014 check it is installed and available in PATH";
|
|
8284
|
+
}
|
|
8285
|
+
if (/permission denied/i.test(msg) && /spawn|exec/i.test(msg)) {
|
|
8286
|
+
return "Permission denied \u2014 the script may not be executable (try: chmod +x)";
|
|
8287
|
+
}
|
|
8288
|
+
if (/\b401\b|Unauthorized/i.test(msg)) {
|
|
8289
|
+
return "Authentication failed (401) \u2014 check your API key or credentials";
|
|
8290
|
+
}
|
|
8291
|
+
if (/\b403\b|Forbidden/i.test(msg)) {
|
|
8292
|
+
return "Access denied (403) \u2014 you don't have permission for this action";
|
|
8293
|
+
}
|
|
8294
|
+
if (/\b429\b|rate.?limit/i.test(msg)) {
|
|
8295
|
+
return "Rate limit exceeded (429) \u2014 too many requests, wait a moment and retry";
|
|
8296
|
+
}
|
|
8297
|
+
if (/\b503\b|Service Unavailable/i.test(msg)) {
|
|
8298
|
+
return "Service temporarily unavailable (503) \u2014 try again in a few minutes";
|
|
8299
|
+
}
|
|
8300
|
+
if (/invalid.*api.?key|api.?key.*invalid|api.?key.*not.*found/i.test(msg)) {
|
|
8301
|
+
return "Invalid or missing API key \u2014 check your provider credentials";
|
|
8302
|
+
}
|
|
8303
|
+
return msg;
|
|
8304
|
+
}
|
|
8305
|
+
|
|
8183
8306
|
// src/tools/registry.ts
|
|
8184
8307
|
var ToolRegistry = class {
|
|
8185
8308
|
tools = /* @__PURE__ */ new Map();
|
|
@@ -8271,7 +8394,17 @@ var ToolRegistry = class {
|
|
|
8271
8394
|
};
|
|
8272
8395
|
} catch (error) {
|
|
8273
8396
|
const duration = performance.now() - startTime;
|
|
8274
|
-
|
|
8397
|
+
let errorMessage;
|
|
8398
|
+
if (error instanceof z.ZodError) {
|
|
8399
|
+
const fields = error.issues.map((issue) => {
|
|
8400
|
+
const field = issue.path.join(".") || "input";
|
|
8401
|
+
return `${field} (${issue.message.toLowerCase()})`;
|
|
8402
|
+
});
|
|
8403
|
+
errorMessage = `Invalid tool input \u2014 ${fields.join(", ")}`;
|
|
8404
|
+
} else {
|
|
8405
|
+
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
8406
|
+
errorMessage = humanizeError(rawMessage, name);
|
|
8407
|
+
}
|
|
8275
8408
|
this.logger.error(`Tool '${name}' failed`, { error: errorMessage, duration });
|
|
8276
8409
|
options?.onProgress?.({
|
|
8277
8410
|
phase: "failed",
|
|
@@ -11491,6 +11624,8 @@ async function withRetry(fn, config = {}) {
|
|
|
11491
11624
|
// src/providers/anthropic.ts
|
|
11492
11625
|
var DEFAULT_MODEL = "claude-opus-4-6-20260115";
|
|
11493
11626
|
var CONTEXT_WINDOWS = {
|
|
11627
|
+
// Kimi Code model (Anthropic-compatible endpoint)
|
|
11628
|
+
"kimi-for-coding": 131072,
|
|
11494
11629
|
// Claude 4.6 (latest, Jan 2026) - 200K-1M context, 128K output
|
|
11495
11630
|
"claude-opus-4-6-20260115": 2e5,
|
|
11496
11631
|
// Claude 4.5 models (Nov 2025)
|
|
@@ -11513,11 +11648,15 @@ var CONTEXT_WINDOWS = {
|
|
|
11513
11648
|
"claude-3-haiku-20240307": 2e5
|
|
11514
11649
|
};
|
|
11515
11650
|
var AnthropicProvider = class {
|
|
11516
|
-
id
|
|
11517
|
-
name
|
|
11651
|
+
id;
|
|
11652
|
+
name;
|
|
11518
11653
|
client = null;
|
|
11519
11654
|
config = {};
|
|
11520
11655
|
retryConfig = DEFAULT_RETRY_CONFIG;
|
|
11656
|
+
constructor(id = "anthropic", name = "Anthropic Claude") {
|
|
11657
|
+
this.id = id;
|
|
11658
|
+
this.name = name;
|
|
11659
|
+
}
|
|
11521
11660
|
/**
|
|
11522
11661
|
* Initialize the provider
|
|
11523
11662
|
*/
|
|
@@ -11674,8 +11813,8 @@ var AnthropicProvider = class {
|
|
|
11674
11813
|
try {
|
|
11675
11814
|
currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
|
|
11676
11815
|
} catch {
|
|
11677
|
-
|
|
11678
|
-
`
|
|
11816
|
+
getLogger().warn(
|
|
11817
|
+
`Failed to parse tool call arguments: ${currentToolInputJson?.slice(0, 100)}`
|
|
11679
11818
|
);
|
|
11680
11819
|
currentToolCall.input = {};
|
|
11681
11820
|
}
|
|
@@ -11906,6 +12045,20 @@ function createAnthropicProvider(config) {
|
|
|
11906
12045
|
}
|
|
11907
12046
|
return provider;
|
|
11908
12047
|
}
|
|
12048
|
+
function createKimiCodeProvider(config) {
|
|
12049
|
+
const provider = new AnthropicProvider("kimi-code", "Kimi Code");
|
|
12050
|
+
const kimiCodeConfig = {
|
|
12051
|
+
...config,
|
|
12052
|
+
baseUrl: config?.baseUrl ?? process.env["KIMI_CODE_BASE_URL"] ?? "https://api.kimi.com/coding",
|
|
12053
|
+
apiKey: config?.apiKey ?? process.env["KIMI_CODE_API_KEY"],
|
|
12054
|
+
model: config?.model ?? "kimi-for-coding"
|
|
12055
|
+
};
|
|
12056
|
+
if (kimiCodeConfig.apiKey) {
|
|
12057
|
+
provider.initialize(kimiCodeConfig).catch(() => {
|
|
12058
|
+
});
|
|
12059
|
+
}
|
|
12060
|
+
return provider;
|
|
12061
|
+
}
|
|
11909
12062
|
var DEFAULT_MODEL2 = "gpt-5.3-codex";
|
|
11910
12063
|
var CONTEXT_WINDOWS2 = {
|
|
11911
12064
|
// OpenAI models
|
|
@@ -11933,7 +12086,6 @@ var CONTEXT_WINDOWS2 = {
|
|
|
11933
12086
|
"kimi-k2.5": 262144,
|
|
11934
12087
|
"kimi-k2-0324": 131072,
|
|
11935
12088
|
"kimi-latest": 131072,
|
|
11936
|
-
"kimi-for-coding": 131072,
|
|
11937
12089
|
"moonshot-v1-8k": 8e3,
|
|
11938
12090
|
"moonshot-v1-32k": 32e3,
|
|
11939
12091
|
"moonshot-v1-128k": 128e3,
|
|
@@ -12010,12 +12162,7 @@ var LOCAL_MODEL_PATTERNS = [
|
|
|
12010
12162
|
"gemma",
|
|
12011
12163
|
"starcoder"
|
|
12012
12164
|
];
|
|
12013
|
-
var MODELS_WITH_THINKING_MODE = [
|
|
12014
|
-
"kimi-k2.5",
|
|
12015
|
-
"kimi-k2-0324",
|
|
12016
|
-
"kimi-latest",
|
|
12017
|
-
"kimi-for-coding"
|
|
12018
|
-
];
|
|
12165
|
+
var MODELS_WITH_THINKING_MODE = ["kimi-k2.5", "kimi-k2-0324", "kimi-latest"];
|
|
12019
12166
|
var OpenAIProvider = class {
|
|
12020
12167
|
id;
|
|
12021
12168
|
name;
|
|
@@ -12044,12 +12191,10 @@ var OpenAIProvider = class {
|
|
|
12044
12191
|
provider: this.id
|
|
12045
12192
|
});
|
|
12046
12193
|
}
|
|
12047
|
-
const defaultHeaders = this.id === "kimi-code" ? { "User-Agent": "claude-code" } : {};
|
|
12048
12194
|
this.client = new OpenAI({
|
|
12049
12195
|
apiKey,
|
|
12050
12196
|
baseURL: config.baseUrl,
|
|
12051
|
-
timeout: config.timeout ?? 12e4
|
|
12052
|
-
defaultHeaders
|
|
12197
|
+
timeout: config.timeout ?? 12e4
|
|
12053
12198
|
});
|
|
12054
12199
|
}
|
|
12055
12200
|
/**
|
|
@@ -12636,20 +12781,6 @@ function createKimiProvider(config) {
|
|
|
12636
12781
|
}
|
|
12637
12782
|
return provider;
|
|
12638
12783
|
}
|
|
12639
|
-
function createKimiCodeProvider(config) {
|
|
12640
|
-
const provider = new OpenAIProvider("kimi-code", "Kimi Code");
|
|
12641
|
-
const kimiCodeConfig = {
|
|
12642
|
-
...config,
|
|
12643
|
-
baseUrl: config?.baseUrl ?? process.env["KIMI_CODE_BASE_URL"] ?? "https://api.kimi.com/coding/v1",
|
|
12644
|
-
apiKey: config?.apiKey ?? process.env["KIMI_CODE_API_KEY"],
|
|
12645
|
-
model: config?.model ?? "kimi-for-coding"
|
|
12646
|
-
};
|
|
12647
|
-
if (kimiCodeConfig.apiKey) {
|
|
12648
|
-
provider.initialize(kimiCodeConfig).catch(() => {
|
|
12649
|
-
});
|
|
12650
|
-
}
|
|
12651
|
-
return provider;
|
|
12652
|
-
}
|
|
12653
12784
|
var OAUTH_CONFIGS = {
|
|
12654
12785
|
/**
|
|
12655
12786
|
* OpenAI OAuth (ChatGPT Plus/Pro subscriptions)
|