@corbat-tech/coco 2.19.0 → 2.20.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 +2257 -1444
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1148 -877
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
package/dist/index.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as fs16 from 'fs/promises';
|
|
2
|
+
import fs16__default, { readFile, access, readdir } from 'fs/promises';
|
|
2
3
|
import * as path17 from 'path';
|
|
3
4
|
import path17__default, { dirname, join, basename, resolve } from 'path';
|
|
5
|
+
import { randomUUID } from 'crypto';
|
|
6
|
+
import 'http';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
4
8
|
import * as fs4 from 'fs';
|
|
5
9
|
import fs4__default, { readFileSync, constants } from 'fs';
|
|
6
|
-
import
|
|
7
|
-
import fs16__default, { readFile, access, readdir } from 'fs/promises';
|
|
8
|
-
import chalk4 from 'chalk';
|
|
10
|
+
import { z } from 'zod';
|
|
9
11
|
import * as p4 from '@clack/prompts';
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
+
import chalk5 from 'chalk';
|
|
13
|
+
import { exec, execSync, execFile } from 'child_process';
|
|
14
|
+
import { promisify } from 'util';
|
|
15
|
+
import { homedir } from 'os';
|
|
16
|
+
import JSON5 from 'json5';
|
|
12
17
|
import { execa } from 'execa';
|
|
13
18
|
import { parse } from '@typescript-eslint/typescript-estree';
|
|
14
19
|
import { glob } from 'glob';
|
|
15
|
-
import { exec, execFile, execSync } from 'child_process';
|
|
16
|
-
import { promisify } from 'util';
|
|
17
|
-
import { z } from 'zod';
|
|
18
20
|
import { Logger } from 'tslog';
|
|
19
21
|
import Anthropic from '@anthropic-ai/sdk';
|
|
20
22
|
import { jsonrepair } from 'jsonrepair';
|
|
21
23
|
import OpenAI from 'openai';
|
|
22
|
-
import 'http';
|
|
23
24
|
import { GoogleGenerativeAI, FunctionCallingMode } from '@google/generative-ai';
|
|
24
|
-
import JSON5 from 'json5';
|
|
25
25
|
import 'events';
|
|
26
26
|
import 'minimatch';
|
|
27
27
|
import { simpleGit } from 'simple-git';
|
|
@@ -50,6 +50,665 @@ var __export = (target, all) => {
|
|
|
50
50
|
for (var name in all)
|
|
51
51
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
52
52
|
};
|
|
53
|
+
|
|
54
|
+
// src/utils/errors.ts
|
|
55
|
+
function isCocoError(error) {
|
|
56
|
+
return error instanceof CocoError;
|
|
57
|
+
}
|
|
58
|
+
var CocoError, FileSystemError, ProviderError, ConfigError, PhaseError, TaskError, ToolError, TimeoutError;
|
|
59
|
+
var init_errors = __esm({
|
|
60
|
+
"src/utils/errors.ts"() {
|
|
61
|
+
CocoError = class _CocoError extends Error {
|
|
62
|
+
code;
|
|
63
|
+
context;
|
|
64
|
+
recoverable;
|
|
65
|
+
suggestion;
|
|
66
|
+
constructor(message, options) {
|
|
67
|
+
super(message, { cause: options.cause });
|
|
68
|
+
this.name = "CocoError";
|
|
69
|
+
this.code = options.code;
|
|
70
|
+
this.context = options.context ?? {};
|
|
71
|
+
this.recoverable = options.recoverable ?? false;
|
|
72
|
+
this.suggestion = options.suggestion;
|
|
73
|
+
Error.captureStackTrace(this, _CocoError);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Convert to JSON for logging
|
|
77
|
+
*/
|
|
78
|
+
toJSON() {
|
|
79
|
+
return {
|
|
80
|
+
name: this.name,
|
|
81
|
+
code: this.code,
|
|
82
|
+
message: this.message,
|
|
83
|
+
context: this.context,
|
|
84
|
+
recoverable: this.recoverable,
|
|
85
|
+
suggestion: this.suggestion,
|
|
86
|
+
stack: this.stack,
|
|
87
|
+
cause: this.cause instanceof Error ? this.cause.message : this.cause
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
FileSystemError = class extends CocoError {
|
|
92
|
+
constructor(message, options) {
|
|
93
|
+
super(message, {
|
|
94
|
+
code: "FILESYSTEM_ERROR",
|
|
95
|
+
context: { path: options.path, operation: options.operation },
|
|
96
|
+
recoverable: false,
|
|
97
|
+
suggestion: `Check that the path exists and you have permissions: ${options.path}`,
|
|
98
|
+
cause: options.cause
|
|
99
|
+
});
|
|
100
|
+
this.name = "FileSystemError";
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
ProviderError = class extends CocoError {
|
|
104
|
+
provider;
|
|
105
|
+
statusCode;
|
|
106
|
+
constructor(message, options) {
|
|
107
|
+
super(message, {
|
|
108
|
+
code: "PROVIDER_ERROR",
|
|
109
|
+
context: { provider: options.provider, statusCode: options.statusCode },
|
|
110
|
+
recoverable: options.retryable ?? false,
|
|
111
|
+
suggestion: options.retryable ? "The request can be retried" : "Check your API key and provider configuration",
|
|
112
|
+
cause: options.cause
|
|
113
|
+
});
|
|
114
|
+
this.name = "ProviderError";
|
|
115
|
+
this.provider = options.provider;
|
|
116
|
+
this.statusCode = options.statusCode;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
ConfigError = class extends CocoError {
|
|
120
|
+
issues;
|
|
121
|
+
constructor(message, options = {}) {
|
|
122
|
+
super(message, {
|
|
123
|
+
code: "CONFIG_ERROR",
|
|
124
|
+
context: { configPath: options.configPath, issues: options.issues },
|
|
125
|
+
recoverable: true,
|
|
126
|
+
suggestion: "Check your .coco/config.json for errors",
|
|
127
|
+
cause: options.cause
|
|
128
|
+
});
|
|
129
|
+
this.name = "ConfigError";
|
|
130
|
+
this.issues = options.issues ?? [];
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Format issues as a readable string
|
|
134
|
+
*/
|
|
135
|
+
formatIssues() {
|
|
136
|
+
if (this.issues.length === 0) return "";
|
|
137
|
+
return this.issues.map((i) => ` - ${i.path}: ${i.message}`).join("\n");
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
PhaseError = class extends CocoError {
|
|
141
|
+
phase;
|
|
142
|
+
constructor(message, options) {
|
|
143
|
+
super(message, {
|
|
144
|
+
code: "PHASE_ERROR",
|
|
145
|
+
context: { phase: options.phase },
|
|
146
|
+
recoverable: options.recoverable ?? true,
|
|
147
|
+
suggestion: `Phase '${options.phase}' failed. Try 'coco resume' to continue.`,
|
|
148
|
+
cause: options.cause
|
|
149
|
+
});
|
|
150
|
+
this.name = "PhaseError";
|
|
151
|
+
this.phase = options.phase;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
TaskError = class extends CocoError {
|
|
155
|
+
taskId;
|
|
156
|
+
iteration;
|
|
157
|
+
constructor(message, options) {
|
|
158
|
+
super(message, {
|
|
159
|
+
code: "TASK_ERROR",
|
|
160
|
+
context: { taskId: options.taskId, iteration: options.iteration },
|
|
161
|
+
recoverable: options.recoverable ?? true,
|
|
162
|
+
suggestion: "The task can be retried from the last checkpoint",
|
|
163
|
+
cause: options.cause
|
|
164
|
+
});
|
|
165
|
+
this.name = "TaskError";
|
|
166
|
+
this.taskId = options.taskId;
|
|
167
|
+
this.iteration = options.iteration;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
ToolError = class extends CocoError {
|
|
171
|
+
tool;
|
|
172
|
+
constructor(message, options) {
|
|
173
|
+
super(message, {
|
|
174
|
+
code: "TOOL_ERROR",
|
|
175
|
+
context: { tool: options.tool },
|
|
176
|
+
recoverable: true,
|
|
177
|
+
suggestion: `Tool '${options.tool}' failed. Check the logs for details.`,
|
|
178
|
+
cause: options.cause
|
|
179
|
+
});
|
|
180
|
+
this.name = "ToolError";
|
|
181
|
+
this.tool = options.tool;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
TimeoutError = class extends CocoError {
|
|
185
|
+
timeoutMs;
|
|
186
|
+
operation;
|
|
187
|
+
constructor(message, options) {
|
|
188
|
+
super(message, {
|
|
189
|
+
code: "TIMEOUT_ERROR",
|
|
190
|
+
context: { timeoutMs: options.timeoutMs, operation: options.operation },
|
|
191
|
+
recoverable: true,
|
|
192
|
+
suggestion: "Try increasing the timeout or simplifying the operation"
|
|
193
|
+
});
|
|
194
|
+
this.name = "TimeoutError";
|
|
195
|
+
this.timeoutMs = options.timeoutMs;
|
|
196
|
+
this.operation = options.operation;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
async function refreshAccessToken(provider, refreshToken) {
|
|
202
|
+
const config = OAUTH_CONFIGS[provider];
|
|
203
|
+
if (!config) {
|
|
204
|
+
throw new Error(`OAuth not supported for provider: ${provider}`);
|
|
205
|
+
}
|
|
206
|
+
const body = new URLSearchParams({
|
|
207
|
+
grant_type: "refresh_token",
|
|
208
|
+
client_id: config.clientId,
|
|
209
|
+
refresh_token: refreshToken
|
|
210
|
+
});
|
|
211
|
+
const response = await fetch(config.tokenEndpoint, {
|
|
212
|
+
method: "POST",
|
|
213
|
+
headers: {
|
|
214
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
215
|
+
},
|
|
216
|
+
body: body.toString()
|
|
217
|
+
});
|
|
218
|
+
if (!response.ok) {
|
|
219
|
+
const error = await response.text();
|
|
220
|
+
throw new Error(`Token refresh failed: ${error}`);
|
|
221
|
+
}
|
|
222
|
+
const data = await response.json();
|
|
223
|
+
return {
|
|
224
|
+
accessToken: data.access_token,
|
|
225
|
+
refreshToken: data.refresh_token || refreshToken,
|
|
226
|
+
expiresAt: data.expires_in ? Date.now() + data.expires_in * 1e3 : void 0,
|
|
227
|
+
tokenType: data.token_type
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function getTokenStoragePath(provider) {
|
|
231
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
232
|
+
return path17.join(home, ".coco", "tokens", `${provider}.json`);
|
|
233
|
+
}
|
|
234
|
+
async function saveTokens(provider, tokens) {
|
|
235
|
+
const filePath = getTokenStoragePath(provider);
|
|
236
|
+
const dir = path17.dirname(filePath);
|
|
237
|
+
await fs16.mkdir(dir, { recursive: true, mode: 448 });
|
|
238
|
+
await fs16.writeFile(filePath, JSON.stringify(tokens, null, 2), { mode: 384 });
|
|
239
|
+
}
|
|
240
|
+
async function loadTokens(provider) {
|
|
241
|
+
const filePath = getTokenStoragePath(provider);
|
|
242
|
+
try {
|
|
243
|
+
const content = await fs16.readFile(filePath, "utf-8");
|
|
244
|
+
return JSON.parse(content);
|
|
245
|
+
} catch {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function deleteTokens(provider) {
|
|
250
|
+
const filePath = getTokenStoragePath(provider);
|
|
251
|
+
try {
|
|
252
|
+
await fs16.unlink(filePath);
|
|
253
|
+
} catch {
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function isTokenExpired(tokens) {
|
|
257
|
+
if (!tokens.expiresAt) return false;
|
|
258
|
+
return Date.now() >= tokens.expiresAt - 5 * 60 * 1e3;
|
|
259
|
+
}
|
|
260
|
+
async function getValidAccessToken(provider) {
|
|
261
|
+
const config = OAUTH_CONFIGS[provider];
|
|
262
|
+
if (!config) return null;
|
|
263
|
+
const tokens = await loadTokens(provider);
|
|
264
|
+
if (!tokens) return null;
|
|
265
|
+
if (isTokenExpired(tokens)) {
|
|
266
|
+
if (tokens.refreshToken) {
|
|
267
|
+
try {
|
|
268
|
+
const newTokens = await refreshAccessToken(provider, tokens.refreshToken);
|
|
269
|
+
await saveTokens(provider, newTokens);
|
|
270
|
+
return { accessToken: newTokens.accessToken, isNew: true };
|
|
271
|
+
} catch {
|
|
272
|
+
await deleteTokens(provider);
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
await deleteTokens(provider);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
return { accessToken: tokens.accessToken, isNew: false };
|
|
280
|
+
}
|
|
281
|
+
var OAUTH_CONFIGS;
|
|
282
|
+
var init_oauth = __esm({
|
|
283
|
+
"src/auth/oauth.ts"() {
|
|
284
|
+
OAUTH_CONFIGS = {
|
|
285
|
+
/**
|
|
286
|
+
* OpenAI OAuth (ChatGPT Plus/Pro subscriptions)
|
|
287
|
+
* Uses the official Codex client ID (same as OpenCode, Codex CLI, etc.)
|
|
288
|
+
*/
|
|
289
|
+
openai: {
|
|
290
|
+
provider: "openai",
|
|
291
|
+
clientId: "app_EMoamEEZ73f0CkXaXp7hrann",
|
|
292
|
+
authorizationEndpoint: "https://auth.openai.com/oauth/authorize",
|
|
293
|
+
tokenEndpoint: "https://auth.openai.com/oauth/token",
|
|
294
|
+
deviceAuthEndpoint: "https://auth.openai.com/oauth/device/code",
|
|
295
|
+
verificationUri: "https://chatgpt.com/codex/device",
|
|
296
|
+
scopes: ["openid", "profile", "email", "offline_access"],
|
|
297
|
+
extraAuthParams: {
|
|
298
|
+
id_token_add_organizations: "true",
|
|
299
|
+
codex_cli_simplified_flow: "true",
|
|
300
|
+
originator: "opencode"
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// NOTE: Gemini OAuth removed - Google's client ID is restricted to official apps
|
|
304
|
+
// Use API Key (https://aistudio.google.com/apikey) or gcloud ADC instead
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
var init_pkce = __esm({
|
|
309
|
+
"src/auth/pkce.ts"() {
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
var init_callback_server = __esm({
|
|
313
|
+
"src/auth/callback-server.ts"() {
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
function detectWSL() {
|
|
317
|
+
if (process.env.WSL_DISTRO_NAME || process.env.WSLENV) return true;
|
|
318
|
+
try {
|
|
319
|
+
return /microsoft/i.test(readFileSync("/proc/version", "utf-8"));
|
|
320
|
+
} catch {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
var isWSL;
|
|
325
|
+
var init_platform = __esm({
|
|
326
|
+
"src/utils/platform.ts"() {
|
|
327
|
+
isWSL = detectWSL();
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
async function exchangeForCopilotToken(githubToken) {
|
|
331
|
+
const response = await fetch(COPILOT_TOKEN_URL, {
|
|
332
|
+
method: "GET",
|
|
333
|
+
headers: {
|
|
334
|
+
Authorization: `token ${githubToken}`,
|
|
335
|
+
Accept: "application/json",
|
|
336
|
+
"User-Agent": "Corbat-Coco/1.0"
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
if (!response.ok) {
|
|
340
|
+
const error = await response.text();
|
|
341
|
+
if (response.status === 401) {
|
|
342
|
+
throw new CopilotAuthError(
|
|
343
|
+
"GitHub token is invalid or expired. Please re-authenticate with /provider copilot.",
|
|
344
|
+
true
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
if (response.status === 403) {
|
|
348
|
+
throw new CopilotAuthError(
|
|
349
|
+
"GitHub Copilot is not enabled for this account.\n Please ensure you have an active Copilot subscription:\n https://github.com/settings/copilot",
|
|
350
|
+
true
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
throw new Error(`Copilot token exchange failed: ${response.status} - ${error}`);
|
|
354
|
+
}
|
|
355
|
+
return await response.json();
|
|
356
|
+
}
|
|
357
|
+
function getCopilotBaseUrl(accountType) {
|
|
358
|
+
if (accountType && accountType in COPILOT_BASE_URLS) {
|
|
359
|
+
return COPILOT_BASE_URLS[accountType];
|
|
360
|
+
}
|
|
361
|
+
return DEFAULT_COPILOT_BASE_URL;
|
|
362
|
+
}
|
|
363
|
+
function getCopilotCredentialsPath() {
|
|
364
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
365
|
+
return path17.join(home, ".coco", "tokens", "copilot.json");
|
|
366
|
+
}
|
|
367
|
+
async function saveCopilotCredentials(creds) {
|
|
368
|
+
const filePath = getCopilotCredentialsPath();
|
|
369
|
+
const dir = path17.dirname(filePath);
|
|
370
|
+
await fs16.mkdir(dir, { recursive: true, mode: 448 });
|
|
371
|
+
await fs16.writeFile(filePath, JSON.stringify(creds, null, 2), { mode: 384 });
|
|
372
|
+
}
|
|
373
|
+
async function loadCopilotCredentials() {
|
|
374
|
+
try {
|
|
375
|
+
const content = await fs16.readFile(getCopilotCredentialsPath(), "utf-8");
|
|
376
|
+
const parsed = CopilotCredentialsSchema.safeParse(JSON.parse(content));
|
|
377
|
+
return parsed.success ? parsed.data : null;
|
|
378
|
+
} catch {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async function deleteCopilotCredentials() {
|
|
383
|
+
try {
|
|
384
|
+
await fs16.unlink(getCopilotCredentialsPath());
|
|
385
|
+
} catch {
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function isCopilotTokenExpired(creds) {
|
|
389
|
+
if (!creds.copilotToken || !creds.copilotTokenExpiresAt) return true;
|
|
390
|
+
return Date.now() >= creds.copilotTokenExpiresAt - REFRESH_BUFFER_MS;
|
|
391
|
+
}
|
|
392
|
+
async function getValidCopilotToken() {
|
|
393
|
+
const creds = await loadCopilotCredentials();
|
|
394
|
+
if (!creds) return null;
|
|
395
|
+
const envToken = process.env["GITHUB_TOKEN"] || process.env["GH_TOKEN"];
|
|
396
|
+
const githubToken = envToken || creds.githubToken;
|
|
397
|
+
if (!isCopilotTokenExpired(creds) && creds.copilotToken) {
|
|
398
|
+
return {
|
|
399
|
+
token: creds.copilotToken,
|
|
400
|
+
baseUrl: getCopilotBaseUrl(creds.accountType),
|
|
401
|
+
isNew: false
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
try {
|
|
405
|
+
const copilotToken = await exchangeForCopilotToken(githubToken);
|
|
406
|
+
const updatedCreds = {
|
|
407
|
+
...creds,
|
|
408
|
+
githubToken: creds.githubToken,
|
|
409
|
+
copilotToken: copilotToken.token,
|
|
410
|
+
copilotTokenExpiresAt: copilotToken.expires_at * 1e3,
|
|
411
|
+
accountType: copilotToken.annotations?.copilot_plan ?? creds.accountType
|
|
412
|
+
};
|
|
413
|
+
await saveCopilotCredentials(updatedCreds);
|
|
414
|
+
return {
|
|
415
|
+
token: copilotToken.token,
|
|
416
|
+
baseUrl: getCopilotBaseUrl(updatedCreds.accountType),
|
|
417
|
+
isNew: true
|
|
418
|
+
};
|
|
419
|
+
} catch (error) {
|
|
420
|
+
if (error instanceof CopilotAuthError && error.permanent) {
|
|
421
|
+
await deleteCopilotCredentials();
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
throw error;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
var COPILOT_TOKEN_URL, COPILOT_BASE_URLS, DEFAULT_COPILOT_BASE_URL, REFRESH_BUFFER_MS, CopilotAuthError, CopilotCredentialsSchema;
|
|
428
|
+
var init_copilot = __esm({
|
|
429
|
+
"src/auth/copilot.ts"() {
|
|
430
|
+
COPILOT_TOKEN_URL = "https://api.github.com/copilot_internal/v2/token";
|
|
431
|
+
COPILOT_BASE_URLS = {
|
|
432
|
+
individual: "https://api.githubcopilot.com",
|
|
433
|
+
business: "https://api.business.githubcopilot.com",
|
|
434
|
+
enterprise: "https://api.enterprise.githubcopilot.com"
|
|
435
|
+
};
|
|
436
|
+
DEFAULT_COPILOT_BASE_URL = "https://api.githubcopilot.com";
|
|
437
|
+
REFRESH_BUFFER_MS = 6e4;
|
|
438
|
+
CopilotAuthError = class extends Error {
|
|
439
|
+
constructor(message, permanent) {
|
|
440
|
+
super(message);
|
|
441
|
+
this.permanent = permanent;
|
|
442
|
+
this.name = "CopilotAuthError";
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
CopilotCredentialsSchema = z.object({
|
|
446
|
+
githubToken: z.string().min(1),
|
|
447
|
+
copilotToken: z.string().optional(),
|
|
448
|
+
copilotTokenExpiresAt: z.number().optional(),
|
|
449
|
+
accountType: z.string().optional()
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
var init_flow = __esm({
|
|
454
|
+
"src/auth/flow.ts"() {
|
|
455
|
+
init_oauth();
|
|
456
|
+
init_pkce();
|
|
457
|
+
init_callback_server();
|
|
458
|
+
init_platform();
|
|
459
|
+
init_copilot();
|
|
460
|
+
promisify(execFile);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
async function getADCAccessToken() {
|
|
464
|
+
try {
|
|
465
|
+
const { stdout } = await execAsync2("gcloud auth application-default print-access-token", {
|
|
466
|
+
timeout: 1e4
|
|
467
|
+
});
|
|
468
|
+
const accessToken = stdout.trim();
|
|
469
|
+
if (!accessToken) return null;
|
|
470
|
+
const expiresAt = Date.now() + 55 * 60 * 1e3;
|
|
471
|
+
return {
|
|
472
|
+
accessToken,
|
|
473
|
+
expiresAt
|
|
474
|
+
};
|
|
475
|
+
} catch (error) {
|
|
476
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
477
|
+
if (message.includes("not logged in") || message.includes("no application default credentials")) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
async function getCachedADCToken() {
|
|
484
|
+
if (cachedToken && cachedToken.expiresAt && Date.now() < cachedToken.expiresAt) {
|
|
485
|
+
return cachedToken;
|
|
486
|
+
}
|
|
487
|
+
cachedToken = await getADCAccessToken();
|
|
488
|
+
return cachedToken;
|
|
489
|
+
}
|
|
490
|
+
var execAsync2, cachedToken;
|
|
491
|
+
var init_gcloud = __esm({
|
|
492
|
+
"src/auth/gcloud.ts"() {
|
|
493
|
+
execAsync2 = promisify(exec);
|
|
494
|
+
cachedToken = null;
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// src/auth/index.ts
|
|
499
|
+
var init_auth = __esm({
|
|
500
|
+
"src/auth/index.ts"() {
|
|
501
|
+
init_oauth();
|
|
502
|
+
init_pkce();
|
|
503
|
+
init_callback_server();
|
|
504
|
+
init_flow();
|
|
505
|
+
init_copilot();
|
|
506
|
+
init_gcloud();
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
function createDefaultConfigObject(projectName, language = "typescript") {
|
|
510
|
+
return {
|
|
511
|
+
project: {
|
|
512
|
+
name: projectName,
|
|
513
|
+
version: "0.1.0"
|
|
514
|
+
},
|
|
515
|
+
provider: {
|
|
516
|
+
type: "anthropic",
|
|
517
|
+
model: "claude-sonnet-4-6",
|
|
518
|
+
maxTokens: 8192,
|
|
519
|
+
temperature: 0,
|
|
520
|
+
timeout: 12e4
|
|
521
|
+
},
|
|
522
|
+
quality: {
|
|
523
|
+
minScore: 85,
|
|
524
|
+
minCoverage: 80,
|
|
525
|
+
maxIterations: 10,
|
|
526
|
+
minIterations: 2,
|
|
527
|
+
convergenceThreshold: 2,
|
|
528
|
+
securityThreshold: 100
|
|
529
|
+
},
|
|
530
|
+
persistence: {
|
|
531
|
+
checkpointInterval: 3e5,
|
|
532
|
+
maxCheckpoints: 50,
|
|
533
|
+
retentionDays: 7,
|
|
534
|
+
compressOldCheckpoints: true
|
|
535
|
+
},
|
|
536
|
+
stack: {
|
|
537
|
+
language
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
var ProviderConfigSchema, QualityConfigSchema, PersistenceConfigSchema, StackConfigSchema, ProjectConfigSchema2, GitHubConfigSchema, IntegrationsConfigSchema, MCPServerConfigEntrySchema, MCPConfigSchema, ToolsConfigSchema, ShipConfigSchema, SkillsConfigSchema, CocoConfigSchema;
|
|
542
|
+
var init_schema = __esm({
|
|
543
|
+
"src/config/schema.ts"() {
|
|
544
|
+
ProviderConfigSchema = z.object({
|
|
545
|
+
type: z.enum([
|
|
546
|
+
"anthropic",
|
|
547
|
+
"openai",
|
|
548
|
+
"codex",
|
|
549
|
+
"copilot",
|
|
550
|
+
"gemini",
|
|
551
|
+
"kimi",
|
|
552
|
+
"kimi-code",
|
|
553
|
+
"lmstudio",
|
|
554
|
+
"ollama",
|
|
555
|
+
"groq",
|
|
556
|
+
"openrouter",
|
|
557
|
+
"mistral",
|
|
558
|
+
"deepseek",
|
|
559
|
+
"together",
|
|
560
|
+
"huggingface",
|
|
561
|
+
"qwen"
|
|
562
|
+
]).default("anthropic"),
|
|
563
|
+
apiKey: z.string().optional(),
|
|
564
|
+
model: z.string().default("claude-sonnet-4-6"),
|
|
565
|
+
maxTokens: z.number().min(1).max(2e5).default(8192),
|
|
566
|
+
temperature: z.number().min(0).max(2).default(0),
|
|
567
|
+
timeout: z.number().min(1e3).default(12e4)
|
|
568
|
+
});
|
|
569
|
+
QualityConfigSchema = z.object({
|
|
570
|
+
minScore: z.number().min(0).max(100).default(85),
|
|
571
|
+
minCoverage: z.number().min(0).max(100).default(80),
|
|
572
|
+
maxIterations: z.number().min(1).max(20).default(10),
|
|
573
|
+
minIterations: z.number().min(1).max(10).default(2),
|
|
574
|
+
convergenceThreshold: z.number().min(0).max(10).default(2),
|
|
575
|
+
securityThreshold: z.number().min(0).max(100).default(100)
|
|
576
|
+
}).refine((data) => data.minIterations <= data.maxIterations, {
|
|
577
|
+
message: "minIterations must be <= maxIterations",
|
|
578
|
+
path: ["minIterations"]
|
|
579
|
+
});
|
|
580
|
+
PersistenceConfigSchema = z.object({
|
|
581
|
+
checkpointInterval: z.number().min(6e4).default(3e5),
|
|
582
|
+
// 5 min default
|
|
583
|
+
maxCheckpoints: z.number().min(1).max(100).default(50),
|
|
584
|
+
retentionDays: z.number().min(1).max(365).default(7),
|
|
585
|
+
compressOldCheckpoints: z.boolean().default(true)
|
|
586
|
+
});
|
|
587
|
+
StackConfigSchema = z.object({
|
|
588
|
+
language: z.enum(["typescript", "python", "go", "rust", "java"]),
|
|
589
|
+
framework: z.string().optional(),
|
|
590
|
+
profile: z.string().optional()
|
|
591
|
+
// Custom profile path
|
|
592
|
+
});
|
|
593
|
+
ProjectConfigSchema2 = z.object({
|
|
594
|
+
name: z.string().min(1),
|
|
595
|
+
version: z.string().default("0.1.0"),
|
|
596
|
+
description: z.string().optional()
|
|
597
|
+
});
|
|
598
|
+
GitHubConfigSchema = z.object({
|
|
599
|
+
enabled: z.boolean().default(false),
|
|
600
|
+
token: z.string().optional(),
|
|
601
|
+
repo: z.string().optional(),
|
|
602
|
+
createPRs: z.boolean().default(true),
|
|
603
|
+
createIssues: z.boolean().default(true)
|
|
604
|
+
});
|
|
605
|
+
IntegrationsConfigSchema = z.object({
|
|
606
|
+
github: GitHubConfigSchema.optional()
|
|
607
|
+
});
|
|
608
|
+
MCPServerConfigEntrySchema = z.object({
|
|
609
|
+
name: z.string(),
|
|
610
|
+
transport: z.enum(["stdio", "http", "sse"]),
|
|
611
|
+
command: z.string().optional(),
|
|
612
|
+
args: z.array(z.string()).optional(),
|
|
613
|
+
url: z.string().optional(),
|
|
614
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
615
|
+
auth: z.object({
|
|
616
|
+
type: z.enum(["oauth", "bearer", "apikey"]),
|
|
617
|
+
token: z.string().optional(),
|
|
618
|
+
tokenEnv: z.string().optional(),
|
|
619
|
+
headerName: z.string().optional()
|
|
620
|
+
}).optional(),
|
|
621
|
+
enabled: z.boolean().default(true),
|
|
622
|
+
description: z.string().optional()
|
|
623
|
+
});
|
|
624
|
+
MCPConfigSchema = z.object({
|
|
625
|
+
enabled: z.boolean().default(true),
|
|
626
|
+
configFile: z.string().optional(),
|
|
627
|
+
// Path to external MCP config file
|
|
628
|
+
servers: z.array(MCPServerConfigEntrySchema).default([])
|
|
629
|
+
});
|
|
630
|
+
ToolsConfigSchema = z.object({
|
|
631
|
+
webSearch: z.object({
|
|
632
|
+
engine: z.enum(["duckduckgo", "brave", "serpapi"]).default("duckduckgo"),
|
|
633
|
+
apiKey: z.string().optional(),
|
|
634
|
+
maxResults: z.number().min(1).max(20).default(5)
|
|
635
|
+
}).optional(),
|
|
636
|
+
memory: z.object({
|
|
637
|
+
maxMemories: z.number().min(1).max(1e4).default(1e3),
|
|
638
|
+
scope: z.enum(["global", "project", "both"]).default("project")
|
|
639
|
+
}).optional(),
|
|
640
|
+
checkpoint: z.object({
|
|
641
|
+
maxCheckpoints: z.number().min(1).max(200).default(50),
|
|
642
|
+
useGitStash: z.boolean().default(true)
|
|
643
|
+
}).optional(),
|
|
644
|
+
semanticSearch: z.object({
|
|
645
|
+
model: z.string().default("all-MiniLM-L6-v2"),
|
|
646
|
+
chunkSize: z.number().min(5).max(100).default(20),
|
|
647
|
+
threshold: z.number().min(0).max(1).default(0.3)
|
|
648
|
+
}).optional()
|
|
649
|
+
});
|
|
650
|
+
ShipConfigSchema = z.object({
|
|
651
|
+
/** Default base branch for PRs */
|
|
652
|
+
defaultBaseBranch: z.string().default("main"),
|
|
653
|
+
/** Auto-detect version bump from commit history */
|
|
654
|
+
autoDetectBump: z.boolean().default(true),
|
|
655
|
+
/** Use squash merge for PRs */
|
|
656
|
+
squashMerge: z.boolean().default(true),
|
|
657
|
+
/** Delete feature branch after merge */
|
|
658
|
+
deleteBranchAfterMerge: z.boolean().default(true),
|
|
659
|
+
/** Create PRs as draft by default */
|
|
660
|
+
draftPr: z.boolean().default(false),
|
|
661
|
+
/** CI check timeout in ms (default 10 minutes) */
|
|
662
|
+
ciCheckTimeoutMs: z.number().default(6e5),
|
|
663
|
+
/** CI check poll interval in ms (default 15 seconds) */
|
|
664
|
+
ciCheckPollMs: z.number().default(15e3)
|
|
665
|
+
});
|
|
666
|
+
SkillsConfigSchema = z.object({
|
|
667
|
+
/** Enable/disable skills system */
|
|
668
|
+
enabled: z.boolean().default(true),
|
|
669
|
+
/** Override global skills directory */
|
|
670
|
+
globalDir: z.string().optional(),
|
|
671
|
+
/** Override project skills directory */
|
|
672
|
+
projectDir: z.string().optional(),
|
|
673
|
+
/** Auto-activate skills based on user messages */
|
|
674
|
+
autoActivate: z.boolean().default(true),
|
|
675
|
+
/** Maximum concurrent active markdown skills */
|
|
676
|
+
maxActiveSkills: z.number().min(1).max(10).default(3),
|
|
677
|
+
/** List of skill IDs to disable */
|
|
678
|
+
disabled: z.array(z.string()).default([])
|
|
679
|
+
});
|
|
680
|
+
CocoConfigSchema = z.object({
|
|
681
|
+
project: ProjectConfigSchema2,
|
|
682
|
+
provider: ProviderConfigSchema.default({
|
|
683
|
+
type: "anthropic",
|
|
684
|
+
model: "claude-sonnet-4-6",
|
|
685
|
+
maxTokens: 8192,
|
|
686
|
+
temperature: 0,
|
|
687
|
+
timeout: 12e4
|
|
688
|
+
}),
|
|
689
|
+
quality: QualityConfigSchema.default({
|
|
690
|
+
minScore: 85,
|
|
691
|
+
minCoverage: 80,
|
|
692
|
+
maxIterations: 10,
|
|
693
|
+
minIterations: 2,
|
|
694
|
+
convergenceThreshold: 2,
|
|
695
|
+
securityThreshold: 100
|
|
696
|
+
}),
|
|
697
|
+
persistence: PersistenceConfigSchema.default({
|
|
698
|
+
checkpointInterval: 3e5,
|
|
699
|
+
maxCheckpoints: 50,
|
|
700
|
+
retentionDays: 7,
|
|
701
|
+
compressOldCheckpoints: true
|
|
702
|
+
}),
|
|
703
|
+
stack: StackConfigSchema.optional(),
|
|
704
|
+
integrations: IntegrationsConfigSchema.optional(),
|
|
705
|
+
mcp: MCPConfigSchema.optional(),
|
|
706
|
+
tools: ToolsConfigSchema.optional(),
|
|
707
|
+
ship: ShipConfigSchema.optional(),
|
|
708
|
+
skills: SkillsConfigSchema.optional()
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
});
|
|
53
712
|
var COCO_HOME, CONFIG_PATHS;
|
|
54
713
|
var init_paths = __esm({
|
|
55
714
|
"src/config/paths.ts"() {
|
|
@@ -88,6 +747,135 @@ var init_paths = __esm({
|
|
|
88
747
|
});
|
|
89
748
|
}
|
|
90
749
|
});
|
|
750
|
+
async function loadConfig(configPath) {
|
|
751
|
+
let config = createDefaultConfig("my-project");
|
|
752
|
+
const globalConfig = await loadConfigFile(CONFIG_PATHS.config, { strict: false });
|
|
753
|
+
if (globalConfig) {
|
|
754
|
+
config = deepMergeConfig(config, globalConfig);
|
|
755
|
+
}
|
|
756
|
+
const projectConfigPath = configPath || getProjectConfigPath2();
|
|
757
|
+
const projectConfig = await loadConfigFile(projectConfigPath);
|
|
758
|
+
if (projectConfig) {
|
|
759
|
+
config = deepMergeConfig(config, projectConfig);
|
|
760
|
+
}
|
|
761
|
+
return config;
|
|
762
|
+
}
|
|
763
|
+
async function loadConfigFile(configPath, options = {}) {
|
|
764
|
+
const { strict = true } = options;
|
|
765
|
+
try {
|
|
766
|
+
const content = await fs16__default.readFile(configPath, "utf-8");
|
|
767
|
+
const parsed = JSON5.parse(content);
|
|
768
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
769
|
+
if (!strict) {
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
throw new ConfigError("Invalid configuration: expected an object", {
|
|
773
|
+
configPath
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
const result = CocoConfigSchema.partial().safeParse(parsed);
|
|
777
|
+
if (!result.success && strict) {
|
|
778
|
+
const issues = result.error.issues.map((i) => ({
|
|
779
|
+
path: i.path.join("."),
|
|
780
|
+
message: i.message
|
|
781
|
+
}));
|
|
782
|
+
throw new ConfigError("Invalid configuration", {
|
|
783
|
+
issues,
|
|
784
|
+
configPath
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
return parsed;
|
|
788
|
+
} catch (error) {
|
|
789
|
+
if (error instanceof ConfigError) {
|
|
790
|
+
throw error;
|
|
791
|
+
}
|
|
792
|
+
if (error.code === "ENOENT") {
|
|
793
|
+
return null;
|
|
794
|
+
}
|
|
795
|
+
throw new ConfigError("Failed to load configuration", {
|
|
796
|
+
configPath,
|
|
797
|
+
cause: error instanceof Error ? error : void 0
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
function deepMergeConfig(base, override) {
|
|
802
|
+
return {
|
|
803
|
+
...base,
|
|
804
|
+
...override,
|
|
805
|
+
project: { ...base.project, ...override.project },
|
|
806
|
+
provider: { ...base.provider, ...override.provider },
|
|
807
|
+
quality: { ...base.quality, ...override.quality },
|
|
808
|
+
persistence: { ...base.persistence, ...override.persistence },
|
|
809
|
+
// Merge optional sections only if present in either base or override
|
|
810
|
+
...base.stack || override.stack ? { stack: { ...base.stack, ...override.stack } } : {},
|
|
811
|
+
...base.integrations || override.integrations ? {
|
|
812
|
+
integrations: {
|
|
813
|
+
...base.integrations,
|
|
814
|
+
...override.integrations
|
|
815
|
+
}
|
|
816
|
+
} : {},
|
|
817
|
+
...base.mcp || override.mcp ? { mcp: { ...base.mcp, ...override.mcp } } : {},
|
|
818
|
+
...base.tools || override.tools ? { tools: { ...base.tools, ...override.tools } } : {}
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
function getProjectConfigPath2() {
|
|
822
|
+
return path17__default.join(process.cwd(), ".coco", "config.json");
|
|
823
|
+
}
|
|
824
|
+
async function saveConfig(config, configPath, global = false) {
|
|
825
|
+
const result = CocoConfigSchema.safeParse(config);
|
|
826
|
+
if (!result.success) {
|
|
827
|
+
const issues = result.error.issues.map((i) => ({
|
|
828
|
+
path: i.path.join("."),
|
|
829
|
+
message: i.message
|
|
830
|
+
}));
|
|
831
|
+
throw new ConfigError("Cannot save invalid configuration", {
|
|
832
|
+
issues,
|
|
833
|
+
configPath: configPath || getProjectConfigPath2()
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
const resolvedPath = configPath || (global ? CONFIG_PATHS.config : getProjectConfigPath2());
|
|
837
|
+
const dir = path17__default.dirname(resolvedPath);
|
|
838
|
+
await fs16__default.mkdir(dir, { recursive: true });
|
|
839
|
+
const content = JSON.stringify(result.data, null, 2);
|
|
840
|
+
await fs16__default.writeFile(resolvedPath, content, "utf-8");
|
|
841
|
+
}
|
|
842
|
+
function createDefaultConfig(projectName, language = "typescript") {
|
|
843
|
+
return createDefaultConfigObject(projectName, language);
|
|
844
|
+
}
|
|
845
|
+
async function configExists(configPath, scope = "any") {
|
|
846
|
+
if (configPath) {
|
|
847
|
+
try {
|
|
848
|
+
await fs16__default.access(configPath);
|
|
849
|
+
return true;
|
|
850
|
+
} catch {
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
if (scope === "project" || scope === "any") {
|
|
855
|
+
try {
|
|
856
|
+
await fs16__default.access(getProjectConfigPath2());
|
|
857
|
+
return true;
|
|
858
|
+
} catch {
|
|
859
|
+
if (scope === "project") return false;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
if (scope === "global" || scope === "any") {
|
|
863
|
+
try {
|
|
864
|
+
await fs16__default.access(CONFIG_PATHS.config);
|
|
865
|
+
return true;
|
|
866
|
+
} catch {
|
|
867
|
+
return false;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
return false;
|
|
871
|
+
}
|
|
872
|
+
var init_loader = __esm({
|
|
873
|
+
"src/config/loader.ts"() {
|
|
874
|
+
init_schema();
|
|
875
|
+
init_errors();
|
|
876
|
+
init_paths();
|
|
877
|
+
}
|
|
878
|
+
});
|
|
91
879
|
function loadGlobalCocoEnv() {
|
|
92
880
|
try {
|
|
93
881
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
@@ -199,40 +987,40 @@ function getDefaultModel(provider) {
|
|
|
199
987
|
case "lmstudio":
|
|
200
988
|
return process.env["LMSTUDIO_MODEL"] ?? "local-model";
|
|
201
989
|
case "ollama":
|
|
202
|
-
return process.env["OLLAMA_MODEL"] ?? "llama3.
|
|
990
|
+
return process.env["OLLAMA_MODEL"] ?? "llama3.2";
|
|
203
991
|
case "codex":
|
|
204
|
-
return process.env["CODEX_MODEL"] ?? "
|
|
992
|
+
return process.env["CODEX_MODEL"] ?? "codex-mini-latest";
|
|
205
993
|
case "copilot":
|
|
206
|
-
return process.env["COPILOT_MODEL"] ?? "
|
|
994
|
+
return process.env["COPILOT_MODEL"] ?? "gpt-4o-copilot";
|
|
207
995
|
case "groq":
|
|
208
996
|
return process.env["GROQ_MODEL"] ?? "llama-3.3-70b-versatile";
|
|
209
997
|
case "openrouter":
|
|
210
|
-
return process.env["OPENROUTER_MODEL"] ?? "anthropic/claude-
|
|
998
|
+
return process.env["OPENROUTER_MODEL"] ?? "anthropic/claude-3.5-sonnet";
|
|
211
999
|
case "mistral":
|
|
212
|
-
return process.env["MISTRAL_MODEL"] ?? "
|
|
1000
|
+
return process.env["MISTRAL_MODEL"] ?? "mistral-large-latest";
|
|
213
1001
|
case "deepseek":
|
|
214
|
-
return process.env["DEEPSEEK_MODEL"] ?? "deepseek-
|
|
1002
|
+
return process.env["DEEPSEEK_MODEL"] ?? "deepseek-chat";
|
|
215
1003
|
case "together":
|
|
216
|
-
return process.env["TOGETHER_MODEL"] ?? "
|
|
1004
|
+
return process.env["TOGETHER_MODEL"] ?? "meta-llama/Llama-3.3-70B-Instruct-Turbo";
|
|
217
1005
|
case "huggingface":
|
|
218
|
-
return process.env["HF_MODEL"] ?? "
|
|
1006
|
+
return process.env["HF_MODEL"] ?? "meta-llama/Llama-3.1-70B-Instruct";
|
|
219
1007
|
case "qwen":
|
|
220
|
-
return process.env["QWEN_MODEL"] ?? "qwen-
|
|
1008
|
+
return process.env["QWEN_MODEL"] ?? "qwen-max";
|
|
221
1009
|
default:
|
|
222
|
-
return "
|
|
1010
|
+
return "claude-sonnet-4-6";
|
|
223
1011
|
}
|
|
224
1012
|
}
|
|
225
1013
|
function getDefaultProvider() {
|
|
226
|
-
const
|
|
227
|
-
if (
|
|
228
|
-
return
|
|
1014
|
+
const envProvider = process.env["COCO_PROVIDER"]?.toLowerCase();
|
|
1015
|
+
if (envProvider && VALID_PROVIDERS.includes(envProvider)) {
|
|
1016
|
+
return envProvider;
|
|
229
1017
|
}
|
|
230
1018
|
return "anthropic";
|
|
231
1019
|
}
|
|
232
1020
|
var VALID_PROVIDERS;
|
|
233
1021
|
var init_env = __esm({
|
|
234
1022
|
"src/config/env.ts"() {
|
|
235
|
-
|
|
1023
|
+
init_loader();
|
|
236
1024
|
loadGlobalCocoEnv();
|
|
237
1025
|
VALID_PROVIDERS = [
|
|
238
1026
|
"anthropic",
|
|
@@ -406,8 +1194,8 @@ __export(allow_path_prompt_exports, {
|
|
|
406
1194
|
async function promptAllowPath(dirPath) {
|
|
407
1195
|
const absolute = path17__default.resolve(dirPath);
|
|
408
1196
|
console.log();
|
|
409
|
-
console.log(
|
|
410
|
-
console.log(
|
|
1197
|
+
console.log(chalk5.yellow(" \u26A0 Access denied \u2014 path is outside the project directory"));
|
|
1198
|
+
console.log(chalk5.dim(` \u{1F4C1} ${absolute}`));
|
|
411
1199
|
console.log();
|
|
412
1200
|
const action = await p4.select({
|
|
413
1201
|
message: "Grant access to this directory?",
|
|
@@ -430,7 +1218,7 @@ async function promptAllowPath(dirPath) {
|
|
|
430
1218
|
}
|
|
431
1219
|
const levelLabel = level === "write" ? "write" : "read-only";
|
|
432
1220
|
const persistLabel = persist ? " (remembered)" : "";
|
|
433
|
-
console.log(
|
|
1221
|
+
console.log(chalk5.green(` \u2713 Access granted: ${levelLabel}${persistLabel}`));
|
|
434
1222
|
return true;
|
|
435
1223
|
}
|
|
436
1224
|
var init_allow_path_prompt = __esm({
|
|
@@ -694,148 +1482,8 @@ function fillPrompt(template, variables) {
|
|
|
694
1482
|
return result;
|
|
695
1483
|
}
|
|
696
1484
|
|
|
697
|
-
// src/
|
|
698
|
-
|
|
699
|
-
code;
|
|
700
|
-
context;
|
|
701
|
-
recoverable;
|
|
702
|
-
suggestion;
|
|
703
|
-
constructor(message, options) {
|
|
704
|
-
super(message, { cause: options.cause });
|
|
705
|
-
this.name = "CocoError";
|
|
706
|
-
this.code = options.code;
|
|
707
|
-
this.context = options.context ?? {};
|
|
708
|
-
this.recoverable = options.recoverable ?? false;
|
|
709
|
-
this.suggestion = options.suggestion;
|
|
710
|
-
Error.captureStackTrace(this, _CocoError);
|
|
711
|
-
}
|
|
712
|
-
/**
|
|
713
|
-
* Convert to JSON for logging
|
|
714
|
-
*/
|
|
715
|
-
toJSON() {
|
|
716
|
-
return {
|
|
717
|
-
name: this.name,
|
|
718
|
-
code: this.code,
|
|
719
|
-
message: this.message,
|
|
720
|
-
context: this.context,
|
|
721
|
-
recoverable: this.recoverable,
|
|
722
|
-
suggestion: this.suggestion,
|
|
723
|
-
stack: this.stack,
|
|
724
|
-
cause: this.cause instanceof Error ? this.cause.message : this.cause
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
};
|
|
728
|
-
var FileSystemError = class extends CocoError {
|
|
729
|
-
constructor(message, options) {
|
|
730
|
-
super(message, {
|
|
731
|
-
code: "FILESYSTEM_ERROR",
|
|
732
|
-
context: { path: options.path, operation: options.operation },
|
|
733
|
-
recoverable: false,
|
|
734
|
-
suggestion: `Check that the path exists and you have permissions: ${options.path}`,
|
|
735
|
-
cause: options.cause
|
|
736
|
-
});
|
|
737
|
-
this.name = "FileSystemError";
|
|
738
|
-
}
|
|
739
|
-
};
|
|
740
|
-
var ProviderError = class extends CocoError {
|
|
741
|
-
provider;
|
|
742
|
-
statusCode;
|
|
743
|
-
constructor(message, options) {
|
|
744
|
-
super(message, {
|
|
745
|
-
code: "PROVIDER_ERROR",
|
|
746
|
-
context: { provider: options.provider, statusCode: options.statusCode },
|
|
747
|
-
recoverable: options.retryable ?? false,
|
|
748
|
-
suggestion: options.retryable ? "The request can be retried" : "Check your API key and provider configuration",
|
|
749
|
-
cause: options.cause
|
|
750
|
-
});
|
|
751
|
-
this.name = "ProviderError";
|
|
752
|
-
this.provider = options.provider;
|
|
753
|
-
this.statusCode = options.statusCode;
|
|
754
|
-
}
|
|
755
|
-
};
|
|
756
|
-
var ConfigError = class extends CocoError {
|
|
757
|
-
issues;
|
|
758
|
-
constructor(message, options = {}) {
|
|
759
|
-
super(message, {
|
|
760
|
-
code: "CONFIG_ERROR",
|
|
761
|
-
context: { configPath: options.configPath, issues: options.issues },
|
|
762
|
-
recoverable: true,
|
|
763
|
-
suggestion: "Check your .coco/config.json for errors",
|
|
764
|
-
cause: options.cause
|
|
765
|
-
});
|
|
766
|
-
this.name = "ConfigError";
|
|
767
|
-
this.issues = options.issues ?? [];
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* Format issues as a readable string
|
|
771
|
-
*/
|
|
772
|
-
formatIssues() {
|
|
773
|
-
if (this.issues.length === 0) return "";
|
|
774
|
-
return this.issues.map((i) => ` - ${i.path}: ${i.message}`).join("\n");
|
|
775
|
-
}
|
|
776
|
-
};
|
|
777
|
-
var PhaseError = class extends CocoError {
|
|
778
|
-
phase;
|
|
779
|
-
constructor(message, options) {
|
|
780
|
-
super(message, {
|
|
781
|
-
code: "PHASE_ERROR",
|
|
782
|
-
context: { phase: options.phase },
|
|
783
|
-
recoverable: options.recoverable ?? true,
|
|
784
|
-
suggestion: `Phase '${options.phase}' failed. Try 'coco resume' to continue.`,
|
|
785
|
-
cause: options.cause
|
|
786
|
-
});
|
|
787
|
-
this.name = "PhaseError";
|
|
788
|
-
this.phase = options.phase;
|
|
789
|
-
}
|
|
790
|
-
};
|
|
791
|
-
var TaskError = class extends CocoError {
|
|
792
|
-
taskId;
|
|
793
|
-
iteration;
|
|
794
|
-
constructor(message, options) {
|
|
795
|
-
super(message, {
|
|
796
|
-
code: "TASK_ERROR",
|
|
797
|
-
context: { taskId: options.taskId, iteration: options.iteration },
|
|
798
|
-
recoverable: options.recoverable ?? true,
|
|
799
|
-
suggestion: "The task can be retried from the last checkpoint",
|
|
800
|
-
cause: options.cause
|
|
801
|
-
});
|
|
802
|
-
this.name = "TaskError";
|
|
803
|
-
this.taskId = options.taskId;
|
|
804
|
-
this.iteration = options.iteration;
|
|
805
|
-
}
|
|
806
|
-
};
|
|
807
|
-
var ToolError = class extends CocoError {
|
|
808
|
-
tool;
|
|
809
|
-
constructor(message, options) {
|
|
810
|
-
super(message, {
|
|
811
|
-
code: "TOOL_ERROR",
|
|
812
|
-
context: { tool: options.tool },
|
|
813
|
-
recoverable: true,
|
|
814
|
-
suggestion: `Tool '${options.tool}' failed. Check the logs for details.`,
|
|
815
|
-
cause: options.cause
|
|
816
|
-
});
|
|
817
|
-
this.name = "ToolError";
|
|
818
|
-
this.tool = options.tool;
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
var TimeoutError = class extends CocoError {
|
|
822
|
-
timeoutMs;
|
|
823
|
-
operation;
|
|
824
|
-
constructor(message, options) {
|
|
825
|
-
super(message, {
|
|
826
|
-
code: "TIMEOUT_ERROR",
|
|
827
|
-
context: { timeoutMs: options.timeoutMs, operation: options.operation },
|
|
828
|
-
recoverable: true,
|
|
829
|
-
suggestion: "Try increasing the timeout or simplifying the operation"
|
|
830
|
-
});
|
|
831
|
-
this.name = "TimeoutError";
|
|
832
|
-
this.timeoutMs = options.timeoutMs;
|
|
833
|
-
this.operation = options.operation;
|
|
834
|
-
}
|
|
835
|
-
};
|
|
836
|
-
function isCocoError(error) {
|
|
837
|
-
return error instanceof CocoError;
|
|
838
|
-
}
|
|
1485
|
+
// src/phases/converge/discovery.ts
|
|
1486
|
+
init_errors();
|
|
839
1487
|
function normalizeComplexity(value) {
|
|
840
1488
|
const normalized = value?.toLowerCase();
|
|
841
1489
|
if (normalized === "simple") return "simple";
|
|
@@ -1281,6 +1929,9 @@ function createDiscoveryEngine(llm, config) {
|
|
|
1281
1929
|
return new DiscoveryEngine(llm, config);
|
|
1282
1930
|
}
|
|
1283
1931
|
|
|
1932
|
+
// src/phases/converge/specification.ts
|
|
1933
|
+
init_errors();
|
|
1934
|
+
|
|
1284
1935
|
// src/phases/converge/specification-types.ts
|
|
1285
1936
|
var DEFAULT_SPEC_CONFIG = {
|
|
1286
1937
|
includeDiagrams: true,
|
|
@@ -1784,6 +2435,9 @@ ${parsed.dataFlow}
|
|
|
1784
2435
|
function createSpecificationGenerator(llm, config) {
|
|
1785
2436
|
return new SpecificationGenerator(llm, config);
|
|
1786
2437
|
}
|
|
2438
|
+
|
|
2439
|
+
// src/phases/converge/persistence.ts
|
|
2440
|
+
init_errors();
|
|
1787
2441
|
function getPersistencePaths(projectPath) {
|
|
1788
2442
|
const baseDir = path17__default.join(projectPath, ".coco", "spec");
|
|
1789
2443
|
return {
|
|
@@ -2066,6 +2720,7 @@ function createSessionManager(projectPath) {
|
|
|
2066
2720
|
}
|
|
2067
2721
|
|
|
2068
2722
|
// src/phases/converge/executor.ts
|
|
2723
|
+
init_errors();
|
|
2069
2724
|
var DEFAULT_CONVERGE_CONFIG = {
|
|
2070
2725
|
maxQuestionRounds: 3,
|
|
2071
2726
|
maxQuestionsPerRound: 3,
|
|
@@ -2756,6 +3411,9 @@ function fillPrompt2(template, variables) {
|
|
|
2756
3411
|
}
|
|
2757
3412
|
return result;
|
|
2758
3413
|
}
|
|
3414
|
+
|
|
3415
|
+
// src/phases/orchestrate/architecture.ts
|
|
3416
|
+
init_errors();
|
|
2759
3417
|
function parseOverview(data) {
|
|
2760
3418
|
return {
|
|
2761
3419
|
pattern: data?.pattern || "layered",
|
|
@@ -3094,6 +3752,7 @@ var ArchitectureGenerator = class {
|
|
|
3094
3752
|
function createArchitectureGenerator(llm, config) {
|
|
3095
3753
|
return new ArchitectureGenerator(llm, config);
|
|
3096
3754
|
}
|
|
3755
|
+
init_errors();
|
|
3097
3756
|
var ADRGenerator = class {
|
|
3098
3757
|
llm;
|
|
3099
3758
|
config;
|
|
@@ -3279,6 +3938,7 @@ function slugify(str) {
|
|
|
3279
3938
|
function createADRGenerator(llm, config) {
|
|
3280
3939
|
return new ADRGenerator(llm, config);
|
|
3281
3940
|
}
|
|
3941
|
+
init_errors();
|
|
3282
3942
|
var BacklogGenerator = class {
|
|
3283
3943
|
llm;
|
|
3284
3944
|
config;
|
|
@@ -8296,6 +8956,9 @@ function buildFeedbackSection(feedback, issues) {
|
|
|
8296
8956
|
}
|
|
8297
8957
|
return section;
|
|
8298
8958
|
}
|
|
8959
|
+
|
|
8960
|
+
// src/phases/complete/generator.ts
|
|
8961
|
+
init_errors();
|
|
8299
8962
|
var DEFAULT_CONFIG = {
|
|
8300
8963
|
name: "coco",
|
|
8301
8964
|
level: "info",
|
|
@@ -8492,6 +9155,21 @@ function humanizeError(message, toolName) {
|
|
|
8492
9155
|
return msg;
|
|
8493
9156
|
}
|
|
8494
9157
|
|
|
9158
|
+
// src/tools/registry.ts
|
|
9159
|
+
init_errors();
|
|
9160
|
+
|
|
9161
|
+
// src/cli/repl/error-resilience.ts
|
|
9162
|
+
init_errors();
|
|
9163
|
+
function isAbortError(error, signal) {
|
|
9164
|
+
if (signal?.aborted) return true;
|
|
9165
|
+
if (!(error instanceof Error)) return false;
|
|
9166
|
+
if (error.name === "AbortError") return true;
|
|
9167
|
+
if (error.name === "APIUserAbortError") return true;
|
|
9168
|
+
if (error.message === "Request was aborted.") return true;
|
|
9169
|
+
if (error.message.endsWith("Request was aborted.")) return true;
|
|
9170
|
+
return false;
|
|
9171
|
+
}
|
|
9172
|
+
|
|
8495
9173
|
// src/tools/registry.ts
|
|
8496
9174
|
var ToolRegistry = class {
|
|
8497
9175
|
tools = /* @__PURE__ */ new Map();
|
|
@@ -8604,6 +9282,8 @@ var ToolRegistry = class {
|
|
|
8604
9282
|
errorMessage += `
|
|
8605
9283
|
Suggestion: ${error.suggestion}`;
|
|
8606
9284
|
}
|
|
9285
|
+
} else if (isAbortError(error, options?.signal)) {
|
|
9286
|
+
errorMessage = "Operation cancelled by user or provider";
|
|
8607
9287
|
} else {
|
|
8608
9288
|
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
8609
9289
|
errorMessage = humanizeError(rawMessage, name);
|
|
@@ -9653,6 +10333,9 @@ function createTaskIterator(llm, config, projectPath) {
|
|
|
9653
10333
|
return new TaskIterator(llm, config, projectPath);
|
|
9654
10334
|
}
|
|
9655
10335
|
|
|
10336
|
+
// src/phases/complete/executor.ts
|
|
10337
|
+
init_errors();
|
|
10338
|
+
|
|
9656
10339
|
// src/phases/complete/llm-adapter.ts
|
|
9657
10340
|
function createLLMAdapter2(context) {
|
|
9658
10341
|
const llmContext = context.llm;
|
|
@@ -11770,7 +12453,11 @@ function createOutputExecutor(config) {
|
|
|
11770
12453
|
return new OutputExecutor(config);
|
|
11771
12454
|
}
|
|
11772
12455
|
|
|
12456
|
+
// src/providers/anthropic.ts
|
|
12457
|
+
init_errors();
|
|
12458
|
+
|
|
11773
12459
|
// src/providers/retry.ts
|
|
12460
|
+
init_errors();
|
|
11774
12461
|
var DEFAULT_RETRY_CONFIG = {
|
|
11775
12462
|
maxRetries: 3,
|
|
11776
12463
|
initialDelayMs: 1e3,
|
|
@@ -12310,7 +12997,14 @@ var AnthropicProvider = class {
|
|
|
12310
12997
|
*/
|
|
12311
12998
|
handleError(error) {
|
|
12312
12999
|
if (error instanceof Anthropic.APIError) {
|
|
12313
|
-
const
|
|
13000
|
+
const msg = error.message.toLowerCase();
|
|
13001
|
+
let retryable = error.status === 429 || error.status >= 500;
|
|
13002
|
+
if (msg.includes("usage limit") || msg.includes("quota") || msg.includes("billing") || msg.includes("insufficient funds")) {
|
|
13003
|
+
retryable = false;
|
|
13004
|
+
}
|
|
13005
|
+
if (error.status === 401 || error.status === 403) {
|
|
13006
|
+
retryable = false;
|
|
13007
|
+
}
|
|
12314
13008
|
throw new ProviderError(error.message, {
|
|
12315
13009
|
provider: this.id,
|
|
12316
13010
|
statusCode: error.status,
|
|
@@ -12318,9 +13012,17 @@ var AnthropicProvider = class {
|
|
|
12318
13012
|
cause: error
|
|
12319
13013
|
});
|
|
12320
13014
|
}
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
13015
|
+
if (error instanceof Error) {
|
|
13016
|
+
const msg = error.message.toLowerCase();
|
|
13017
|
+
const isQuotaError = msg.includes("usage limit") || msg.includes("quota") || msg.includes("billing");
|
|
13018
|
+
throw new ProviderError(error.message, {
|
|
13019
|
+
provider: this.id,
|
|
13020
|
+
retryable: !isQuotaError,
|
|
13021
|
+
cause: error
|
|
13022
|
+
});
|
|
13023
|
+
}
|
|
13024
|
+
throw new ProviderError(String(error), {
|
|
13025
|
+
provider: this.id
|
|
12324
13026
|
});
|
|
12325
13027
|
}
|
|
12326
13028
|
};
|
|
@@ -12346,6 +13048,9 @@ function createKimiCodeProvider(config) {
|
|
|
12346
13048
|
}
|
|
12347
13049
|
return provider;
|
|
12348
13050
|
}
|
|
13051
|
+
|
|
13052
|
+
// src/providers/openai.ts
|
|
13053
|
+
init_errors();
|
|
12349
13054
|
var DEFAULT_MODEL2 = "gpt-5.4-codex";
|
|
12350
13055
|
var CONTEXT_WINDOWS2 = {
|
|
12351
13056
|
// OpenAI models
|
|
@@ -13131,7 +13836,14 @@ var OpenAIProvider = class {
|
|
|
13131
13836
|
*/
|
|
13132
13837
|
handleError(error) {
|
|
13133
13838
|
if (error instanceof OpenAI.APIError) {
|
|
13134
|
-
const
|
|
13839
|
+
const msg = error.message.toLowerCase();
|
|
13840
|
+
let retryable = error.status === 429 || (error.status ?? 0) >= 500;
|
|
13841
|
+
if (msg.includes("exceeded your current quota") || msg.includes("insufficient_quota") || msg.includes("billing") || msg.includes("usage limit") || msg.includes("you have exceeded")) {
|
|
13842
|
+
retryable = false;
|
|
13843
|
+
}
|
|
13844
|
+
if (error.status === 401 || error.status === 403) {
|
|
13845
|
+
retryable = false;
|
|
13846
|
+
}
|
|
13135
13847
|
throw new ProviderError(error.message, {
|
|
13136
13848
|
provider: this.id,
|
|
13137
13849
|
statusCode: error.status,
|
|
@@ -13139,9 +13851,17 @@ var OpenAIProvider = class {
|
|
|
13139
13851
|
cause: error
|
|
13140
13852
|
});
|
|
13141
13853
|
}
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13854
|
+
if (error instanceof Error) {
|
|
13855
|
+
const msg = error.message.toLowerCase();
|
|
13856
|
+
const isQuotaError = msg.includes("exceeded your current quota") || msg.includes("insufficient_quota") || msg.includes("usage limit") || msg.includes("you have exceeded");
|
|
13857
|
+
throw new ProviderError(error.message, {
|
|
13858
|
+
provider: this.id,
|
|
13859
|
+
retryable: !isQuotaError,
|
|
13860
|
+
cause: error
|
|
13861
|
+
});
|
|
13862
|
+
}
|
|
13863
|
+
throw new ProviderError(String(error), {
|
|
13864
|
+
provider: this.id
|
|
13145
13865
|
});
|
|
13146
13866
|
}
|
|
13147
13867
|
// --- Responses API support (GPT-5+, Codex, o3, o4 models) ---
|
|
@@ -13517,280 +14237,21 @@ var OpenAIProvider = class {
|
|
|
13517
14237
|
function createKimiProvider(config) {
|
|
13518
14238
|
const provider = new OpenAIProvider("kimi", "Kimi (Moonshot)");
|
|
13519
14239
|
const kimiConfig = {
|
|
13520
|
-
...config,
|
|
13521
|
-
baseUrl: config?.baseUrl ?? process.env["KIMI_BASE_URL"] ?? "https://api.moonshot.ai/v1",
|
|
13522
|
-
apiKey: config?.apiKey ?? process.env["KIMI_API_KEY"] ?? process.env["MOONSHOT_API_KEY"],
|
|
13523
|
-
model: config?.model ?? "kimi-k2.5"
|
|
13524
|
-
};
|
|
13525
|
-
if (kimiConfig.apiKey) {
|
|
13526
|
-
provider.initialize(kimiConfig).catch(() => {
|
|
13527
|
-
});
|
|
13528
|
-
}
|
|
13529
|
-
return provider;
|
|
13530
|
-
}
|
|
13531
|
-
var OAUTH_CONFIGS = {
|
|
13532
|
-
/**
|
|
13533
|
-
* OpenAI OAuth (ChatGPT Plus/Pro subscriptions)
|
|
13534
|
-
* Uses the official Codex client ID (same as OpenCode, Codex CLI, etc.)
|
|
13535
|
-
*/
|
|
13536
|
-
openai: {
|
|
13537
|
-
provider: "openai",
|
|
13538
|
-
clientId: "app_EMoamEEZ73f0CkXaXp7hrann",
|
|
13539
|
-
authorizationEndpoint: "https://auth.openai.com/oauth/authorize",
|
|
13540
|
-
tokenEndpoint: "https://auth.openai.com/oauth/token",
|
|
13541
|
-
deviceAuthEndpoint: "https://auth.openai.com/oauth/device/code",
|
|
13542
|
-
verificationUri: "https://chatgpt.com/codex/device",
|
|
13543
|
-
scopes: ["openid", "profile", "email", "offline_access"],
|
|
13544
|
-
extraAuthParams: {
|
|
13545
|
-
id_token_add_organizations: "true",
|
|
13546
|
-
codex_cli_simplified_flow: "true",
|
|
13547
|
-
originator: "opencode"
|
|
13548
|
-
}
|
|
13549
|
-
}
|
|
13550
|
-
// NOTE: Gemini OAuth removed - Google's client ID is restricted to official apps
|
|
13551
|
-
// Use API Key (https://aistudio.google.com/apikey) or gcloud ADC instead
|
|
13552
|
-
};
|
|
13553
|
-
async function refreshAccessToken(provider, refreshToken) {
|
|
13554
|
-
const config = OAUTH_CONFIGS[provider];
|
|
13555
|
-
if (!config) {
|
|
13556
|
-
throw new Error(`OAuth not supported for provider: ${provider}`);
|
|
13557
|
-
}
|
|
13558
|
-
const body = new URLSearchParams({
|
|
13559
|
-
grant_type: "refresh_token",
|
|
13560
|
-
client_id: config.clientId,
|
|
13561
|
-
refresh_token: refreshToken
|
|
13562
|
-
});
|
|
13563
|
-
const response = await fetch(config.tokenEndpoint, {
|
|
13564
|
-
method: "POST",
|
|
13565
|
-
headers: {
|
|
13566
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
13567
|
-
},
|
|
13568
|
-
body: body.toString()
|
|
13569
|
-
});
|
|
13570
|
-
if (!response.ok) {
|
|
13571
|
-
const error = await response.text();
|
|
13572
|
-
throw new Error(`Token refresh failed: ${error}`);
|
|
13573
|
-
}
|
|
13574
|
-
const data = await response.json();
|
|
13575
|
-
return {
|
|
13576
|
-
accessToken: data.access_token,
|
|
13577
|
-
refreshToken: data.refresh_token || refreshToken,
|
|
13578
|
-
expiresAt: data.expires_in ? Date.now() + data.expires_in * 1e3 : void 0,
|
|
13579
|
-
tokenType: data.token_type
|
|
13580
|
-
};
|
|
13581
|
-
}
|
|
13582
|
-
function getTokenStoragePath(provider) {
|
|
13583
|
-
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
13584
|
-
return path17.join(home, ".coco", "tokens", `${provider}.json`);
|
|
13585
|
-
}
|
|
13586
|
-
async function saveTokens(provider, tokens) {
|
|
13587
|
-
const filePath = getTokenStoragePath(provider);
|
|
13588
|
-
const dir = path17.dirname(filePath);
|
|
13589
|
-
await fs16.mkdir(dir, { recursive: true, mode: 448 });
|
|
13590
|
-
await fs16.writeFile(filePath, JSON.stringify(tokens, null, 2), { mode: 384 });
|
|
13591
|
-
}
|
|
13592
|
-
async function loadTokens(provider) {
|
|
13593
|
-
const filePath = getTokenStoragePath(provider);
|
|
13594
|
-
try {
|
|
13595
|
-
const content = await fs16.readFile(filePath, "utf-8");
|
|
13596
|
-
return JSON.parse(content);
|
|
13597
|
-
} catch {
|
|
13598
|
-
return null;
|
|
13599
|
-
}
|
|
13600
|
-
}
|
|
13601
|
-
async function deleteTokens(provider) {
|
|
13602
|
-
const filePath = getTokenStoragePath(provider);
|
|
13603
|
-
try {
|
|
13604
|
-
await fs16.unlink(filePath);
|
|
13605
|
-
} catch {
|
|
13606
|
-
}
|
|
13607
|
-
}
|
|
13608
|
-
function isTokenExpired(tokens) {
|
|
13609
|
-
if (!tokens.expiresAt) return false;
|
|
13610
|
-
return Date.now() >= tokens.expiresAt - 5 * 60 * 1e3;
|
|
13611
|
-
}
|
|
13612
|
-
async function getValidAccessToken(provider) {
|
|
13613
|
-
const config = OAUTH_CONFIGS[provider];
|
|
13614
|
-
if (!config) return null;
|
|
13615
|
-
const tokens = await loadTokens(provider);
|
|
13616
|
-
if (!tokens) return null;
|
|
13617
|
-
if (isTokenExpired(tokens)) {
|
|
13618
|
-
if (tokens.refreshToken) {
|
|
13619
|
-
try {
|
|
13620
|
-
const newTokens = await refreshAccessToken(provider, tokens.refreshToken);
|
|
13621
|
-
await saveTokens(provider, newTokens);
|
|
13622
|
-
return { accessToken: newTokens.accessToken, isNew: true };
|
|
13623
|
-
} catch {
|
|
13624
|
-
await deleteTokens(provider);
|
|
13625
|
-
return null;
|
|
13626
|
-
}
|
|
13627
|
-
}
|
|
13628
|
-
await deleteTokens(provider);
|
|
13629
|
-
return null;
|
|
13630
|
-
}
|
|
13631
|
-
return { accessToken: tokens.accessToken, isNew: false };
|
|
13632
|
-
}
|
|
13633
|
-
function detectWSL() {
|
|
13634
|
-
if (process.env.WSL_DISTRO_NAME || process.env.WSLENV) return true;
|
|
13635
|
-
try {
|
|
13636
|
-
return /microsoft/i.test(readFileSync("/proc/version", "utf-8"));
|
|
13637
|
-
} catch {
|
|
13638
|
-
return false;
|
|
13639
|
-
}
|
|
13640
|
-
}
|
|
13641
|
-
var isWSL = detectWSL();
|
|
13642
|
-
var COPILOT_TOKEN_URL = "https://api.github.com/copilot_internal/v2/token";
|
|
13643
|
-
var COPILOT_BASE_URLS = {
|
|
13644
|
-
individual: "https://api.githubcopilot.com",
|
|
13645
|
-
business: "https://api.business.githubcopilot.com",
|
|
13646
|
-
enterprise: "https://api.enterprise.githubcopilot.com"
|
|
13647
|
-
};
|
|
13648
|
-
var DEFAULT_COPILOT_BASE_URL = "https://api.githubcopilot.com";
|
|
13649
|
-
var REFRESH_BUFFER_MS = 6e4;
|
|
13650
|
-
var CopilotAuthError = class extends Error {
|
|
13651
|
-
constructor(message, permanent) {
|
|
13652
|
-
super(message);
|
|
13653
|
-
this.permanent = permanent;
|
|
13654
|
-
this.name = "CopilotAuthError";
|
|
13655
|
-
}
|
|
13656
|
-
};
|
|
13657
|
-
async function exchangeForCopilotToken(githubToken) {
|
|
13658
|
-
const response = await fetch(COPILOT_TOKEN_URL, {
|
|
13659
|
-
method: "GET",
|
|
13660
|
-
headers: {
|
|
13661
|
-
Authorization: `token ${githubToken}`,
|
|
13662
|
-
Accept: "application/json",
|
|
13663
|
-
"User-Agent": "Corbat-Coco/1.0"
|
|
13664
|
-
}
|
|
13665
|
-
});
|
|
13666
|
-
if (!response.ok) {
|
|
13667
|
-
const error = await response.text();
|
|
13668
|
-
if (response.status === 401) {
|
|
13669
|
-
throw new CopilotAuthError(
|
|
13670
|
-
"GitHub token is invalid or expired. Please re-authenticate with /provider copilot.",
|
|
13671
|
-
true
|
|
13672
|
-
);
|
|
13673
|
-
}
|
|
13674
|
-
if (response.status === 403) {
|
|
13675
|
-
throw new CopilotAuthError(
|
|
13676
|
-
"GitHub Copilot is not enabled for this account.\n Please ensure you have an active Copilot subscription:\n https://github.com/settings/copilot",
|
|
13677
|
-
true
|
|
13678
|
-
);
|
|
13679
|
-
}
|
|
13680
|
-
throw new Error(`Copilot token exchange failed: ${response.status} - ${error}`);
|
|
13681
|
-
}
|
|
13682
|
-
return await response.json();
|
|
13683
|
-
}
|
|
13684
|
-
function getCopilotBaseUrl(accountType) {
|
|
13685
|
-
if (accountType && accountType in COPILOT_BASE_URLS) {
|
|
13686
|
-
return COPILOT_BASE_URLS[accountType];
|
|
13687
|
-
}
|
|
13688
|
-
return DEFAULT_COPILOT_BASE_URL;
|
|
13689
|
-
}
|
|
13690
|
-
function getCopilotCredentialsPath() {
|
|
13691
|
-
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
13692
|
-
return path17.join(home, ".coco", "tokens", "copilot.json");
|
|
13693
|
-
}
|
|
13694
|
-
async function saveCopilotCredentials(creds) {
|
|
13695
|
-
const filePath = getCopilotCredentialsPath();
|
|
13696
|
-
const dir = path17.dirname(filePath);
|
|
13697
|
-
await fs16.mkdir(dir, { recursive: true, mode: 448 });
|
|
13698
|
-
await fs16.writeFile(filePath, JSON.stringify(creds, null, 2), { mode: 384 });
|
|
13699
|
-
}
|
|
13700
|
-
var CopilotCredentialsSchema = z.object({
|
|
13701
|
-
githubToken: z.string().min(1),
|
|
13702
|
-
copilotToken: z.string().optional(),
|
|
13703
|
-
copilotTokenExpiresAt: z.number().optional(),
|
|
13704
|
-
accountType: z.string().optional()
|
|
13705
|
-
});
|
|
13706
|
-
async function loadCopilotCredentials() {
|
|
13707
|
-
try {
|
|
13708
|
-
const content = await fs16.readFile(getCopilotCredentialsPath(), "utf-8");
|
|
13709
|
-
const parsed = CopilotCredentialsSchema.safeParse(JSON.parse(content));
|
|
13710
|
-
return parsed.success ? parsed.data : null;
|
|
13711
|
-
} catch {
|
|
13712
|
-
return null;
|
|
13713
|
-
}
|
|
13714
|
-
}
|
|
13715
|
-
async function deleteCopilotCredentials() {
|
|
13716
|
-
try {
|
|
13717
|
-
await fs16.unlink(getCopilotCredentialsPath());
|
|
13718
|
-
} catch {
|
|
13719
|
-
}
|
|
13720
|
-
}
|
|
13721
|
-
function isCopilotTokenExpired(creds) {
|
|
13722
|
-
if (!creds.copilotToken || !creds.copilotTokenExpiresAt) return true;
|
|
13723
|
-
return Date.now() >= creds.copilotTokenExpiresAt - REFRESH_BUFFER_MS;
|
|
13724
|
-
}
|
|
13725
|
-
async function getValidCopilotToken() {
|
|
13726
|
-
const creds = await loadCopilotCredentials();
|
|
13727
|
-
if (!creds) return null;
|
|
13728
|
-
const envToken = process.env["GITHUB_TOKEN"] || process.env["GH_TOKEN"];
|
|
13729
|
-
const githubToken = envToken || creds.githubToken;
|
|
13730
|
-
if (!isCopilotTokenExpired(creds) && creds.copilotToken) {
|
|
13731
|
-
return {
|
|
13732
|
-
token: creds.copilotToken,
|
|
13733
|
-
baseUrl: getCopilotBaseUrl(creds.accountType),
|
|
13734
|
-
isNew: false
|
|
13735
|
-
};
|
|
13736
|
-
}
|
|
13737
|
-
try {
|
|
13738
|
-
const copilotToken = await exchangeForCopilotToken(githubToken);
|
|
13739
|
-
const updatedCreds = {
|
|
13740
|
-
...creds,
|
|
13741
|
-
githubToken: creds.githubToken,
|
|
13742
|
-
copilotToken: copilotToken.token,
|
|
13743
|
-
copilotTokenExpiresAt: copilotToken.expires_at * 1e3,
|
|
13744
|
-
accountType: copilotToken.annotations?.copilot_plan ?? creds.accountType
|
|
13745
|
-
};
|
|
13746
|
-
await saveCopilotCredentials(updatedCreds);
|
|
13747
|
-
return {
|
|
13748
|
-
token: copilotToken.token,
|
|
13749
|
-
baseUrl: getCopilotBaseUrl(updatedCreds.accountType),
|
|
13750
|
-
isNew: true
|
|
13751
|
-
};
|
|
13752
|
-
} catch (error) {
|
|
13753
|
-
if (error instanceof CopilotAuthError && error.permanent) {
|
|
13754
|
-
await deleteCopilotCredentials();
|
|
13755
|
-
return null;
|
|
13756
|
-
}
|
|
13757
|
-
throw error;
|
|
13758
|
-
}
|
|
13759
|
-
}
|
|
13760
|
-
|
|
13761
|
-
// src/auth/flow.ts
|
|
13762
|
-
promisify(execFile);
|
|
13763
|
-
var execAsync2 = promisify(exec);
|
|
13764
|
-
async function getADCAccessToken() {
|
|
13765
|
-
try {
|
|
13766
|
-
const { stdout } = await execAsync2("gcloud auth application-default print-access-token", {
|
|
13767
|
-
timeout: 1e4
|
|
13768
|
-
});
|
|
13769
|
-
const accessToken = stdout.trim();
|
|
13770
|
-
if (!accessToken) return null;
|
|
13771
|
-
const expiresAt = Date.now() + 55 * 60 * 1e3;
|
|
13772
|
-
return {
|
|
13773
|
-
accessToken,
|
|
13774
|
-
expiresAt
|
|
13775
|
-
};
|
|
13776
|
-
} catch (error) {
|
|
13777
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
13778
|
-
if (message.includes("not logged in") || message.includes("no application default credentials")) {
|
|
13779
|
-
return null;
|
|
13780
|
-
}
|
|
13781
|
-
return null;
|
|
13782
|
-
}
|
|
13783
|
-
}
|
|
13784
|
-
var cachedToken = null;
|
|
13785
|
-
async function getCachedADCToken() {
|
|
13786
|
-
if (cachedToken && cachedToken.expiresAt && Date.now() < cachedToken.expiresAt) {
|
|
13787
|
-
return cachedToken;
|
|
14240
|
+
...config,
|
|
14241
|
+
baseUrl: config?.baseUrl ?? process.env["KIMI_BASE_URL"] ?? "https://api.moonshot.ai/v1",
|
|
14242
|
+
apiKey: config?.apiKey ?? process.env["KIMI_API_KEY"] ?? process.env["MOONSHOT_API_KEY"],
|
|
14243
|
+
model: config?.model ?? "kimi-k2.5"
|
|
14244
|
+
};
|
|
14245
|
+
if (kimiConfig.apiKey) {
|
|
14246
|
+
provider.initialize(kimiConfig).catch(() => {
|
|
14247
|
+
});
|
|
13788
14248
|
}
|
|
13789
|
-
|
|
13790
|
-
return cachedToken;
|
|
14249
|
+
return provider;
|
|
13791
14250
|
}
|
|
13792
14251
|
|
|
13793
14252
|
// src/providers/codex.ts
|
|
14253
|
+
init_errors();
|
|
14254
|
+
init_auth();
|
|
13794
14255
|
var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
13795
14256
|
var DEFAULT_MODEL3 = "gpt-5.4-codex";
|
|
13796
14257
|
var CONTEXT_WINDOWS3 = {
|
|
@@ -14016,7 +14477,7 @@ var CodexProvider = class {
|
|
|
14016
14477
|
model,
|
|
14017
14478
|
input,
|
|
14018
14479
|
instructions: instructions ?? "You are a helpful coding assistant.",
|
|
14019
|
-
|
|
14480
|
+
max_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
|
|
14020
14481
|
temperature: options?.temperature ?? this.config.temperature ?? 0,
|
|
14021
14482
|
store: false,
|
|
14022
14483
|
stream: true
|
|
@@ -14387,6 +14848,10 @@ var CodexProvider = class {
|
|
|
14387
14848
|
}
|
|
14388
14849
|
}
|
|
14389
14850
|
};
|
|
14851
|
+
|
|
14852
|
+
// src/providers/copilot.ts
|
|
14853
|
+
init_errors();
|
|
14854
|
+
init_copilot();
|
|
14390
14855
|
var CONTEXT_WINDOWS4 = {
|
|
14391
14856
|
// Claude models — Copilot API caps these at 168 000 (not 200 000 like Anthropic direct)
|
|
14392
14857
|
"claude-sonnet-4.6": 168e3,
|
|
@@ -14528,6 +14993,10 @@ var CopilotProvider = class extends OpenAIProvider {
|
|
|
14528
14993
|
}
|
|
14529
14994
|
}
|
|
14530
14995
|
};
|
|
14996
|
+
|
|
14997
|
+
// src/providers/gemini.ts
|
|
14998
|
+
init_errors();
|
|
14999
|
+
init_gcloud();
|
|
14531
15000
|
var DEFAULT_MODEL5 = "gemini-3.1-pro-preview";
|
|
14532
15001
|
var CONTEXT_WINDOWS5 = {
|
|
14533
15002
|
// Gemini 3.1 series (latest)
|
|
@@ -14983,7 +15452,14 @@ var GeminiProvider = class {
|
|
|
14983
15452
|
*/
|
|
14984
15453
|
handleError(error) {
|
|
14985
15454
|
const message = error instanceof Error ? error.message : String(error);
|
|
14986
|
-
const
|
|
15455
|
+
const msg = message.toLowerCase();
|
|
15456
|
+
let retryable = message.includes("429") || message.includes("500");
|
|
15457
|
+
if (msg.includes("quota") || msg.includes("billing") || msg.includes("usage limit") || msg.includes("insufficient quota")) {
|
|
15458
|
+
retryable = false;
|
|
15459
|
+
}
|
|
15460
|
+
if (message.includes("401") || message.includes("403")) {
|
|
15461
|
+
retryable = false;
|
|
15462
|
+
}
|
|
14987
15463
|
throw new ProviderError(message, {
|
|
14988
15464
|
provider: this.id,
|
|
14989
15465
|
retryable,
|
|
@@ -14991,6 +15467,16 @@ var GeminiProvider = class {
|
|
|
14991
15467
|
});
|
|
14992
15468
|
}
|
|
14993
15469
|
};
|
|
15470
|
+
|
|
15471
|
+
// src/providers/circuit-breaker.ts
|
|
15472
|
+
init_errors();
|
|
15473
|
+
|
|
15474
|
+
// src/providers/fallback.ts
|
|
15475
|
+
init_errors();
|
|
15476
|
+
|
|
15477
|
+
// src/providers/index.ts
|
|
15478
|
+
init_copilot();
|
|
15479
|
+
init_errors();
|
|
14994
15480
|
init_env();
|
|
14995
15481
|
async function createProvider(type, config = {}) {
|
|
14996
15482
|
let provider;
|
|
@@ -15554,331 +16040,18 @@ function calculateProgress(state) {
|
|
|
15554
16040
|
function generateId() {
|
|
15555
16041
|
return `proj_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`;
|
|
15556
16042
|
}
|
|
15557
|
-
var ProviderConfigSchema = z.object({
|
|
15558
|
-
type: z.enum([
|
|
15559
|
-
"anthropic",
|
|
15560
|
-
"openai",
|
|
15561
|
-
"codex",
|
|
15562
|
-
"gemini",
|
|
15563
|
-
"kimi",
|
|
15564
|
-
"kimi-code",
|
|
15565
|
-
"lmstudio",
|
|
15566
|
-
"ollama",
|
|
15567
|
-
"groq",
|
|
15568
|
-
"openrouter",
|
|
15569
|
-
"mistral",
|
|
15570
|
-
"deepseek",
|
|
15571
|
-
"together",
|
|
15572
|
-
"huggingface"
|
|
15573
|
-
]).default("anthropic"),
|
|
15574
|
-
apiKey: z.string().optional(),
|
|
15575
|
-
model: z.string().default("claude-sonnet-4-6"),
|
|
15576
|
-
maxTokens: z.number().min(1).max(2e5).default(8192),
|
|
15577
|
-
temperature: z.number().min(0).max(2).default(0),
|
|
15578
|
-
timeout: z.number().min(1e3).default(12e4)
|
|
15579
|
-
});
|
|
15580
|
-
var QualityConfigSchema = z.object({
|
|
15581
|
-
minScore: z.number().min(0).max(100).default(85),
|
|
15582
|
-
minCoverage: z.number().min(0).max(100).default(80),
|
|
15583
|
-
maxIterations: z.number().min(1).max(20).default(10),
|
|
15584
|
-
minIterations: z.number().min(1).max(10).default(2),
|
|
15585
|
-
convergenceThreshold: z.number().min(0).max(10).default(2),
|
|
15586
|
-
securityThreshold: z.number().min(0).max(100).default(100)
|
|
15587
|
-
}).refine((data) => data.minIterations <= data.maxIterations, {
|
|
15588
|
-
message: "minIterations must be <= maxIterations",
|
|
15589
|
-
path: ["minIterations"]
|
|
15590
|
-
});
|
|
15591
|
-
var PersistenceConfigSchema = z.object({
|
|
15592
|
-
checkpointInterval: z.number().min(6e4).default(3e5),
|
|
15593
|
-
// 5 min default
|
|
15594
|
-
maxCheckpoints: z.number().min(1).max(100).default(50),
|
|
15595
|
-
retentionDays: z.number().min(1).max(365).default(7),
|
|
15596
|
-
compressOldCheckpoints: z.boolean().default(true)
|
|
15597
|
-
});
|
|
15598
|
-
var StackConfigSchema = z.object({
|
|
15599
|
-
language: z.enum(["typescript", "python", "go", "rust", "java"]),
|
|
15600
|
-
framework: z.string().optional(),
|
|
15601
|
-
profile: z.string().optional()
|
|
15602
|
-
// Custom profile path
|
|
15603
|
-
});
|
|
15604
|
-
var ProjectConfigSchema2 = z.object({
|
|
15605
|
-
name: z.string().min(1),
|
|
15606
|
-
version: z.string().default("0.1.0"),
|
|
15607
|
-
description: z.string().optional()
|
|
15608
|
-
});
|
|
15609
|
-
var GitHubConfigSchema = z.object({
|
|
15610
|
-
enabled: z.boolean().default(false),
|
|
15611
|
-
token: z.string().optional(),
|
|
15612
|
-
repo: z.string().optional(),
|
|
15613
|
-
createPRs: z.boolean().default(true),
|
|
15614
|
-
createIssues: z.boolean().default(true)
|
|
15615
|
-
});
|
|
15616
|
-
var IntegrationsConfigSchema = z.object({
|
|
15617
|
-
github: GitHubConfigSchema.optional()
|
|
15618
|
-
});
|
|
15619
|
-
var MCPServerConfigEntrySchema = z.object({
|
|
15620
|
-
name: z.string(),
|
|
15621
|
-
transport: z.enum(["stdio", "http", "sse"]),
|
|
15622
|
-
command: z.string().optional(),
|
|
15623
|
-
args: z.array(z.string()).optional(),
|
|
15624
|
-
url: z.string().optional(),
|
|
15625
|
-
env: z.record(z.string(), z.string()).optional(),
|
|
15626
|
-
auth: z.object({
|
|
15627
|
-
type: z.enum(["oauth", "bearer", "apikey"]),
|
|
15628
|
-
token: z.string().optional(),
|
|
15629
|
-
tokenEnv: z.string().optional(),
|
|
15630
|
-
headerName: z.string().optional()
|
|
15631
|
-
}).optional(),
|
|
15632
|
-
enabled: z.boolean().default(true),
|
|
15633
|
-
description: z.string().optional()
|
|
15634
|
-
});
|
|
15635
|
-
var MCPConfigSchema = z.object({
|
|
15636
|
-
enabled: z.boolean().default(true),
|
|
15637
|
-
configFile: z.string().optional(),
|
|
15638
|
-
// Path to external MCP config file
|
|
15639
|
-
servers: z.array(MCPServerConfigEntrySchema).default([])
|
|
15640
|
-
});
|
|
15641
|
-
var ToolsConfigSchema = z.object({
|
|
15642
|
-
webSearch: z.object({
|
|
15643
|
-
engine: z.enum(["duckduckgo", "brave", "serpapi"]).default("duckduckgo"),
|
|
15644
|
-
apiKey: z.string().optional(),
|
|
15645
|
-
maxResults: z.number().min(1).max(20).default(5)
|
|
15646
|
-
}).optional(),
|
|
15647
|
-
memory: z.object({
|
|
15648
|
-
maxMemories: z.number().min(1).max(1e4).default(1e3),
|
|
15649
|
-
scope: z.enum(["global", "project", "both"]).default("project")
|
|
15650
|
-
}).optional(),
|
|
15651
|
-
checkpoint: z.object({
|
|
15652
|
-
maxCheckpoints: z.number().min(1).max(200).default(50),
|
|
15653
|
-
useGitStash: z.boolean().default(true)
|
|
15654
|
-
}).optional(),
|
|
15655
|
-
semanticSearch: z.object({
|
|
15656
|
-
model: z.string().default("all-MiniLM-L6-v2"),
|
|
15657
|
-
chunkSize: z.number().min(5).max(100).default(20),
|
|
15658
|
-
threshold: z.number().min(0).max(1).default(0.3)
|
|
15659
|
-
}).optional()
|
|
15660
|
-
});
|
|
15661
|
-
var ShipConfigSchema = z.object({
|
|
15662
|
-
/** Default base branch for PRs */
|
|
15663
|
-
defaultBaseBranch: z.string().default("main"),
|
|
15664
|
-
/** Auto-detect version bump from commit history */
|
|
15665
|
-
autoDetectBump: z.boolean().default(true),
|
|
15666
|
-
/** Use squash merge for PRs */
|
|
15667
|
-
squashMerge: z.boolean().default(true),
|
|
15668
|
-
/** Delete feature branch after merge */
|
|
15669
|
-
deleteBranchAfterMerge: z.boolean().default(true),
|
|
15670
|
-
/** Create PRs as draft by default */
|
|
15671
|
-
draftPr: z.boolean().default(false),
|
|
15672
|
-
/** CI check timeout in ms (default 10 minutes) */
|
|
15673
|
-
ciCheckTimeoutMs: z.number().default(6e5),
|
|
15674
|
-
/** CI check poll interval in ms (default 15 seconds) */
|
|
15675
|
-
ciCheckPollMs: z.number().default(15e3)
|
|
15676
|
-
});
|
|
15677
|
-
var SkillsConfigSchema = z.object({
|
|
15678
|
-
/** Enable/disable skills system */
|
|
15679
|
-
enabled: z.boolean().default(true),
|
|
15680
|
-
/** Override global skills directory */
|
|
15681
|
-
globalDir: z.string().optional(),
|
|
15682
|
-
/** Override project skills directory */
|
|
15683
|
-
projectDir: z.string().optional(),
|
|
15684
|
-
/** Auto-activate skills based on user messages */
|
|
15685
|
-
autoActivate: z.boolean().default(true),
|
|
15686
|
-
/** Maximum concurrent active markdown skills */
|
|
15687
|
-
maxActiveSkills: z.number().min(1).max(10).default(3),
|
|
15688
|
-
/** List of skill IDs to disable */
|
|
15689
|
-
disabled: z.array(z.string()).default([])
|
|
15690
|
-
});
|
|
15691
|
-
var CocoConfigSchema = z.object({
|
|
15692
|
-
project: ProjectConfigSchema2,
|
|
15693
|
-
provider: ProviderConfigSchema.default({
|
|
15694
|
-
type: "anthropic",
|
|
15695
|
-
model: "claude-sonnet-4-6",
|
|
15696
|
-
maxTokens: 8192,
|
|
15697
|
-
temperature: 0,
|
|
15698
|
-
timeout: 12e4
|
|
15699
|
-
}),
|
|
15700
|
-
quality: QualityConfigSchema.default({
|
|
15701
|
-
minScore: 85,
|
|
15702
|
-
minCoverage: 80,
|
|
15703
|
-
maxIterations: 10,
|
|
15704
|
-
minIterations: 2,
|
|
15705
|
-
convergenceThreshold: 2,
|
|
15706
|
-
securityThreshold: 100
|
|
15707
|
-
}),
|
|
15708
|
-
persistence: PersistenceConfigSchema.default({
|
|
15709
|
-
checkpointInterval: 3e5,
|
|
15710
|
-
maxCheckpoints: 50,
|
|
15711
|
-
retentionDays: 7,
|
|
15712
|
-
compressOldCheckpoints: true
|
|
15713
|
-
}),
|
|
15714
|
-
stack: StackConfigSchema.optional(),
|
|
15715
|
-
integrations: IntegrationsConfigSchema.optional(),
|
|
15716
|
-
mcp: MCPConfigSchema.optional(),
|
|
15717
|
-
tools: ToolsConfigSchema.optional(),
|
|
15718
|
-
ship: ShipConfigSchema.optional(),
|
|
15719
|
-
skills: SkillsConfigSchema.optional()
|
|
15720
|
-
});
|
|
15721
|
-
function createDefaultConfigObject(projectName, language = "typescript") {
|
|
15722
|
-
return {
|
|
15723
|
-
project: {
|
|
15724
|
-
name: projectName,
|
|
15725
|
-
version: "0.1.0"
|
|
15726
|
-
},
|
|
15727
|
-
provider: {
|
|
15728
|
-
type: "anthropic",
|
|
15729
|
-
model: "claude-sonnet-4-6",
|
|
15730
|
-
maxTokens: 8192,
|
|
15731
|
-
temperature: 0,
|
|
15732
|
-
timeout: 12e4
|
|
15733
|
-
},
|
|
15734
|
-
quality: {
|
|
15735
|
-
minScore: 85,
|
|
15736
|
-
minCoverage: 80,
|
|
15737
|
-
maxIterations: 10,
|
|
15738
|
-
minIterations: 2,
|
|
15739
|
-
convergenceThreshold: 2,
|
|
15740
|
-
securityThreshold: 100
|
|
15741
|
-
},
|
|
15742
|
-
persistence: {
|
|
15743
|
-
checkpointInterval: 3e5,
|
|
15744
|
-
maxCheckpoints: 50,
|
|
15745
|
-
retentionDays: 7,
|
|
15746
|
-
compressOldCheckpoints: true
|
|
15747
|
-
},
|
|
15748
|
-
stack: {
|
|
15749
|
-
language
|
|
15750
|
-
}
|
|
15751
|
-
};
|
|
15752
|
-
}
|
|
15753
16043
|
|
|
15754
|
-
// src/config/
|
|
15755
|
-
|
|
15756
|
-
|
|
15757
|
-
|
|
15758
|
-
|
|
15759
|
-
|
|
15760
|
-
config = deepMergeConfig(config, globalConfig);
|
|
15761
|
-
}
|
|
15762
|
-
const projectConfigPath = configPath || getProjectConfigPath2();
|
|
15763
|
-
const projectConfig = await loadConfigFile(projectConfigPath);
|
|
15764
|
-
if (projectConfig) {
|
|
15765
|
-
config = deepMergeConfig(config, projectConfig);
|
|
15766
|
-
}
|
|
15767
|
-
return config;
|
|
15768
|
-
}
|
|
15769
|
-
async function loadConfigFile(configPath, options = {}) {
|
|
15770
|
-
const { strict = true } = options;
|
|
15771
|
-
try {
|
|
15772
|
-
const content = await fs16__default.readFile(configPath, "utf-8");
|
|
15773
|
-
const parsed = JSON5.parse(content);
|
|
15774
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
15775
|
-
if (!strict) {
|
|
15776
|
-
return null;
|
|
15777
|
-
}
|
|
15778
|
-
throw new ConfigError("Invalid configuration: expected an object", {
|
|
15779
|
-
configPath
|
|
15780
|
-
});
|
|
15781
|
-
}
|
|
15782
|
-
const result = CocoConfigSchema.partial().safeParse(parsed);
|
|
15783
|
-
if (!result.success && strict) {
|
|
15784
|
-
const issues = result.error.issues.map((i) => ({
|
|
15785
|
-
path: i.path.join("."),
|
|
15786
|
-
message: i.message
|
|
15787
|
-
}));
|
|
15788
|
-
throw new ConfigError("Invalid configuration", {
|
|
15789
|
-
issues,
|
|
15790
|
-
configPath
|
|
15791
|
-
});
|
|
15792
|
-
}
|
|
15793
|
-
return parsed;
|
|
15794
|
-
} catch (error) {
|
|
15795
|
-
if (error instanceof ConfigError) {
|
|
15796
|
-
throw error;
|
|
15797
|
-
}
|
|
15798
|
-
if (error.code === "ENOENT") {
|
|
15799
|
-
return null;
|
|
15800
|
-
}
|
|
15801
|
-
throw new ConfigError("Failed to load configuration", {
|
|
15802
|
-
configPath,
|
|
15803
|
-
cause: error instanceof Error ? error : void 0
|
|
15804
|
-
});
|
|
15805
|
-
}
|
|
15806
|
-
}
|
|
15807
|
-
function deepMergeConfig(base, override) {
|
|
15808
|
-
return {
|
|
15809
|
-
...base,
|
|
15810
|
-
...override,
|
|
15811
|
-
project: { ...base.project, ...override.project },
|
|
15812
|
-
provider: { ...base.provider, ...override.provider },
|
|
15813
|
-
quality: { ...base.quality, ...override.quality },
|
|
15814
|
-
persistence: { ...base.persistence, ...override.persistence },
|
|
15815
|
-
// Merge optional sections only if present in either base or override
|
|
15816
|
-
...base.stack || override.stack ? { stack: { ...base.stack, ...override.stack } } : {},
|
|
15817
|
-
...base.integrations || override.integrations ? {
|
|
15818
|
-
integrations: {
|
|
15819
|
-
...base.integrations,
|
|
15820
|
-
...override.integrations
|
|
15821
|
-
}
|
|
15822
|
-
} : {},
|
|
15823
|
-
...base.mcp || override.mcp ? { mcp: { ...base.mcp, ...override.mcp } } : {},
|
|
15824
|
-
...base.tools || override.tools ? { tools: { ...base.tools, ...override.tools } } : {}
|
|
15825
|
-
};
|
|
15826
|
-
}
|
|
15827
|
-
function getProjectConfigPath2() {
|
|
15828
|
-
return path17__default.join(process.cwd(), ".coco", "config.json");
|
|
15829
|
-
}
|
|
15830
|
-
async function saveConfig(config, configPath, global = false) {
|
|
15831
|
-
const result = CocoConfigSchema.safeParse(config);
|
|
15832
|
-
if (!result.success) {
|
|
15833
|
-
const issues = result.error.issues.map((i) => ({
|
|
15834
|
-
path: i.path.join("."),
|
|
15835
|
-
message: i.message
|
|
15836
|
-
}));
|
|
15837
|
-
throw new ConfigError("Cannot save invalid configuration", {
|
|
15838
|
-
issues,
|
|
15839
|
-
configPath: configPath || getProjectConfigPath2()
|
|
15840
|
-
});
|
|
15841
|
-
}
|
|
15842
|
-
const resolvedPath = configPath || (global ? CONFIG_PATHS.config : getProjectConfigPath2());
|
|
15843
|
-
const dir = path17__default.dirname(resolvedPath);
|
|
15844
|
-
await fs16__default.mkdir(dir, { recursive: true });
|
|
15845
|
-
const content = JSON.stringify(result.data, null, 2);
|
|
15846
|
-
await fs16__default.writeFile(resolvedPath, content, "utf-8");
|
|
15847
|
-
}
|
|
15848
|
-
function createDefaultConfig(projectName, language = "typescript") {
|
|
15849
|
-
return createDefaultConfigObject(projectName, language);
|
|
15850
|
-
}
|
|
15851
|
-
async function configExists(configPath, scope = "any") {
|
|
15852
|
-
if (configPath) {
|
|
15853
|
-
try {
|
|
15854
|
-
await fs16__default.access(configPath);
|
|
15855
|
-
return true;
|
|
15856
|
-
} catch {
|
|
15857
|
-
return false;
|
|
15858
|
-
}
|
|
15859
|
-
}
|
|
15860
|
-
if (scope === "project" || scope === "any") {
|
|
15861
|
-
try {
|
|
15862
|
-
await fs16__default.access(getProjectConfigPath2());
|
|
15863
|
-
return true;
|
|
15864
|
-
} catch {
|
|
15865
|
-
if (scope === "project") return false;
|
|
15866
|
-
}
|
|
15867
|
-
}
|
|
15868
|
-
if (scope === "global" || scope === "any") {
|
|
15869
|
-
try {
|
|
15870
|
-
await fs16__default.access(CONFIG_PATHS.config);
|
|
15871
|
-
return true;
|
|
15872
|
-
} catch {
|
|
15873
|
-
return false;
|
|
15874
|
-
}
|
|
15875
|
-
}
|
|
15876
|
-
return false;
|
|
15877
|
-
}
|
|
16044
|
+
// src/config/index.ts
|
|
16045
|
+
init_loader();
|
|
16046
|
+
init_loader();
|
|
16047
|
+
|
|
16048
|
+
// src/config/watcher.ts
|
|
16049
|
+
init_loader();
|
|
15878
16050
|
z.string().regex(
|
|
15879
16051
|
/^\d+\.\d+\.\d+$/,
|
|
15880
16052
|
"Version must be in semver format (e.g., 1.0.0)"
|
|
15881
16053
|
);
|
|
16054
|
+
init_errors();
|
|
15882
16055
|
init_allowed_paths();
|
|
15883
16056
|
function levenshtein(a, b) {
|
|
15884
16057
|
if (a === b) return 0;
|
|
@@ -15908,11 +16081,113 @@ function levenshtein(a, b) {
|
|
|
15908
16081
|
// src/utils/file-suggestions.ts
|
|
15909
16082
|
var MAX_DIR_ENTRIES = 200;
|
|
15910
16083
|
var MAX_SUGGESTIONS = 5;
|
|
16084
|
+
var DEFAULT_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
16085
|
+
"node_modules",
|
|
16086
|
+
".git",
|
|
16087
|
+
"dist",
|
|
16088
|
+
"build",
|
|
16089
|
+
"coverage",
|
|
16090
|
+
".next",
|
|
16091
|
+
"vendor",
|
|
16092
|
+
"__pycache__",
|
|
16093
|
+
".venv",
|
|
16094
|
+
"venv",
|
|
16095
|
+
".tox",
|
|
16096
|
+
".pytest_cache",
|
|
16097
|
+
".mypy_cache",
|
|
16098
|
+
".ruff_cache",
|
|
16099
|
+
".idea",
|
|
16100
|
+
".vscode",
|
|
16101
|
+
".DS_Store"
|
|
16102
|
+
]);
|
|
16103
|
+
var DEFAULT_FIND_OPTIONS = {
|
|
16104
|
+
maxDepth: 8,
|
|
16105
|
+
timeoutMs: 3e3,
|
|
16106
|
+
includeHidden: true,
|
|
16107
|
+
excludeDirs: DEFAULT_EXCLUDE_DIRS,
|
|
16108
|
+
maxResults: 5,
|
|
16109
|
+
type: "file"
|
|
16110
|
+
};
|
|
16111
|
+
async function findFileRecursive(rootDir, target, options = {}) {
|
|
16112
|
+
const opts = { ...DEFAULT_FIND_OPTIONS, ...options };
|
|
16113
|
+
const targetLower = target.toLowerCase();
|
|
16114
|
+
const results = [];
|
|
16115
|
+
const startTime = Date.now();
|
|
16116
|
+
const isTimedOut = () => Date.now() - startTime > opts.timeoutMs;
|
|
16117
|
+
const queue = [[path17__default.resolve(rootDir), 0]];
|
|
16118
|
+
const visited = /* @__PURE__ */ new Set();
|
|
16119
|
+
while (queue.length > 0 && results.length < opts.maxResults) {
|
|
16120
|
+
if (isTimedOut()) break;
|
|
16121
|
+
const [currentDir, depth] = queue.shift();
|
|
16122
|
+
if (visited.has(currentDir)) continue;
|
|
16123
|
+
visited.add(currentDir);
|
|
16124
|
+
if (depth > opts.maxDepth) continue;
|
|
16125
|
+
try {
|
|
16126
|
+
const entries = await fs16__default.readdir(currentDir, { withFileTypes: true });
|
|
16127
|
+
for (const entry of entries) {
|
|
16128
|
+
if (isTimedOut()) break;
|
|
16129
|
+
const entryName = entry.name;
|
|
16130
|
+
const entryPath = path17__default.join(currentDir, entryName);
|
|
16131
|
+
if (!opts.includeHidden && entryName.startsWith(".")) continue;
|
|
16132
|
+
if (entry.isDirectory() && opts.excludeDirs.has(entryName)) continue;
|
|
16133
|
+
const isMatch = opts.type === "file" && entry.isFile() || opts.type === "directory" && entry.isDirectory() || opts.type === "both";
|
|
16134
|
+
if (isMatch) {
|
|
16135
|
+
const entryNameLower = entryName.toLowerCase();
|
|
16136
|
+
let distance;
|
|
16137
|
+
if (entryNameLower === targetLower) {
|
|
16138
|
+
distance = 0;
|
|
16139
|
+
} else {
|
|
16140
|
+
distance = levenshtein(targetLower, entryNameLower);
|
|
16141
|
+
}
|
|
16142
|
+
const maxDistance = Math.max(target.length * 0.6, 3);
|
|
16143
|
+
if (distance <= maxDistance) {
|
|
16144
|
+
results.push({ path: entryPath, distance });
|
|
16145
|
+
}
|
|
16146
|
+
}
|
|
16147
|
+
if (entry.isDirectory() && !opts.excludeDirs.has(entryName)) {
|
|
16148
|
+
queue.push([entryPath, depth + 1]);
|
|
16149
|
+
}
|
|
16150
|
+
}
|
|
16151
|
+
} catch {
|
|
16152
|
+
continue;
|
|
16153
|
+
}
|
|
16154
|
+
}
|
|
16155
|
+
return results.sort((a, b) => a.distance - b.distance).slice(0, opts.maxResults);
|
|
16156
|
+
}
|
|
16157
|
+
async function suggestSimilarFilesDeep(missingPath, rootDir = process.cwd(), options) {
|
|
16158
|
+
const fastResults = await suggestSimilarFiles(missingPath, {
|
|
16159
|
+
maxResults: MAX_SUGGESTIONS
|
|
16160
|
+
});
|
|
16161
|
+
if (fastResults.length > 0) {
|
|
16162
|
+
return fastResults;
|
|
16163
|
+
}
|
|
16164
|
+
const absPath = path17__default.resolve(missingPath);
|
|
16165
|
+
const target = path17__default.basename(absPath);
|
|
16166
|
+
return findFileRecursive(rootDir, target, options);
|
|
16167
|
+
}
|
|
16168
|
+
async function suggestSimilarDirsDeep(missingPath, rootDir = process.cwd(), options) {
|
|
16169
|
+
const absPath = path17__default.resolve(missingPath);
|
|
16170
|
+
const target = path17__default.basename(absPath);
|
|
16171
|
+
const parentDir = path17__default.dirname(absPath);
|
|
16172
|
+
try {
|
|
16173
|
+
const entries = await fs16__default.readdir(parentDir, { withFileTypes: true });
|
|
16174
|
+
const dirs = entries.filter((e) => e.isDirectory());
|
|
16175
|
+
const scored = dirs.map((d) => ({
|
|
16176
|
+
path: path17__default.join(parentDir, d.name),
|
|
16177
|
+
distance: levenshtein(target.toLowerCase(), d.name.toLowerCase())
|
|
16178
|
+
})).filter((s) => s.distance <= Math.max(target.length * 0.6, 3)).sort((a, b) => a.distance - b.distance).slice(0, options?.maxResults ?? MAX_SUGGESTIONS);
|
|
16179
|
+
if (scored.length > 0) {
|
|
16180
|
+
return scored;
|
|
16181
|
+
}
|
|
16182
|
+
} catch {
|
|
16183
|
+
}
|
|
16184
|
+
return findFileRecursive(rootDir, target, { ...options, type: "directory" });
|
|
16185
|
+
}
|
|
15911
16186
|
async function suggestSimilarFiles(missingPath, options) {
|
|
15912
16187
|
const absPath = path17__default.resolve(missingPath);
|
|
15913
16188
|
const dir = path17__default.dirname(absPath);
|
|
15914
16189
|
const target = path17__default.basename(absPath);
|
|
15915
|
-
const maxResults =
|
|
16190
|
+
const maxResults = options?.maxResults;
|
|
15916
16191
|
try {
|
|
15917
16192
|
const entries = await fs16__default.readdir(dir);
|
|
15918
16193
|
const limited = entries.slice(0, MAX_DIR_ENTRIES);
|
|
@@ -15925,25 +16200,6 @@ async function suggestSimilarFiles(missingPath, options) {
|
|
|
15925
16200
|
return [];
|
|
15926
16201
|
}
|
|
15927
16202
|
}
|
|
15928
|
-
async function suggestSimilarPaths(missingPath, options) {
|
|
15929
|
-
const fileSuggestions = await suggestSimilarFiles(missingPath);
|
|
15930
|
-
if (fileSuggestions.length > 0) return fileSuggestions;
|
|
15931
|
-
const absPath = path17__default.resolve(missingPath);
|
|
15932
|
-
const grandparent = path17__default.dirname(path17__default.dirname(absPath));
|
|
15933
|
-
const parentBasename = path17__default.basename(path17__default.dirname(absPath));
|
|
15934
|
-
const maxResults = MAX_SUGGESTIONS;
|
|
15935
|
-
try {
|
|
15936
|
-
const entries = await fs16__default.readdir(grandparent, { withFileTypes: true });
|
|
15937
|
-
const dirs = entries.filter((e) => e.isDirectory()).slice(0, MAX_DIR_ENTRIES);
|
|
15938
|
-
const scored = dirs.map((d) => ({
|
|
15939
|
-
path: path17__default.join(grandparent, d.name),
|
|
15940
|
-
distance: levenshtein(parentBasename.toLowerCase(), d.name.toLowerCase())
|
|
15941
|
-
})).filter((s) => s.distance <= Math.max(parentBasename.length * 0.6, 3)).sort((a, b) => a.distance - b.distance);
|
|
15942
|
-
return scored.slice(0, maxResults);
|
|
15943
|
-
} catch {
|
|
15944
|
-
return [];
|
|
15945
|
-
}
|
|
15946
|
-
}
|
|
15947
16203
|
function formatSuggestions(suggestions, baseDir) {
|
|
15948
16204
|
if (suggestions.length === 0) return "";
|
|
15949
16205
|
const base = baseDir ?? process.cwd();
|
|
@@ -16046,7 +16302,7 @@ function isENOENT(error) {
|
|
|
16046
16302
|
}
|
|
16047
16303
|
async function enrichENOENT(filePath, operation) {
|
|
16048
16304
|
const absPath = path17__default.resolve(filePath);
|
|
16049
|
-
const suggestions = await
|
|
16305
|
+
const suggestions = await suggestSimilarFilesDeep(absPath, process.cwd());
|
|
16050
16306
|
const hint = formatSuggestions(suggestions, path17__default.dirname(absPath));
|
|
16051
16307
|
const action = operation === "read" ? "Use glob or list_dir to find the correct path." : "Check that the parent directory exists.";
|
|
16052
16308
|
return `File not found: ${filePath}${hint}
|
|
@@ -16054,7 +16310,7 @@ ${action}`;
|
|
|
16054
16310
|
}
|
|
16055
16311
|
async function enrichDirENOENT(dirPath) {
|
|
16056
16312
|
const absPath = path17__default.resolve(dirPath);
|
|
16057
|
-
const suggestions = await
|
|
16313
|
+
const suggestions = await suggestSimilarDirsDeep(absPath, process.cwd());
|
|
16058
16314
|
const hint = formatSuggestions(suggestions, path17__default.dirname(absPath));
|
|
16059
16315
|
return `Directory not found: ${dirPath}${hint}
|
|
16060
16316
|
Use list_dir or glob to find the correct path.`;
|
|
@@ -16686,6 +16942,7 @@ var fileTools = [
|
|
|
16686
16942
|
function escapeRegex(str) {
|
|
16687
16943
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
16688
16944
|
}
|
|
16945
|
+
init_errors();
|
|
16689
16946
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
16690
16947
|
var MAX_OUTPUT_SIZE = 1024 * 1024;
|
|
16691
16948
|
var DANGEROUS_PATTERNS_FULL = [
|
|
@@ -17018,6 +17275,7 @@ function truncateOutput(output, maxLength = 5e4) {
|
|
|
17018
17275
|
|
|
17019
17276
|
[Output truncated - ${output.length - maxLength} more characters]`;
|
|
17020
17277
|
}
|
|
17278
|
+
init_errors();
|
|
17021
17279
|
function enrichGitError(operation, error) {
|
|
17022
17280
|
const msg = error instanceof Error ? error.message : String(error);
|
|
17023
17281
|
if (/not a git repository/i.test(msg))
|
|
@@ -17695,6 +17953,7 @@ var checkAgentCapabilityTool = defineTool({
|
|
|
17695
17953
|
}
|
|
17696
17954
|
});
|
|
17697
17955
|
var simpleAgentTools = [spawnSimpleAgentTool, checkAgentCapabilityTool];
|
|
17956
|
+
init_errors();
|
|
17698
17957
|
async function detectTestFramework2(cwd) {
|
|
17699
17958
|
try {
|
|
17700
17959
|
await fs16__default.access(path17__default.join(cwd, "pom.xml"));
|
|
@@ -18058,6 +18317,7 @@ Examples:
|
|
|
18058
18317
|
}
|
|
18059
18318
|
});
|
|
18060
18319
|
var testTools = [runTestsTool, getCoverageTool, runTestFileTool];
|
|
18320
|
+
init_errors();
|
|
18061
18321
|
async function detectLinter2(cwd) {
|
|
18062
18322
|
try {
|
|
18063
18323
|
await fs16__default.access(path17__default.join(cwd, "pom.xml"));
|
|
@@ -18442,6 +18702,7 @@ Examples:
|
|
|
18442
18702
|
}
|
|
18443
18703
|
});
|
|
18444
18704
|
var qualityTools = [runLinterTool, analyzeComplexityTool, calculateQualityTool];
|
|
18705
|
+
init_errors();
|
|
18445
18706
|
var grepTool = defineTool({
|
|
18446
18707
|
name: "grep",
|
|
18447
18708
|
description: `Search for text patterns in files using regex.
|
|
@@ -18609,7 +18870,10 @@ Examples:
|
|
|
18609
18870
|
return { matches, count: matches.length };
|
|
18610
18871
|
} catch (error) {
|
|
18611
18872
|
if (error.code === "ENOENT") {
|
|
18612
|
-
|
|
18873
|
+
const suggestions = await suggestSimilarFilesDeep(file, process.cwd());
|
|
18874
|
+
const hint = formatSuggestions(suggestions, path17__default.dirname(file));
|
|
18875
|
+
throw new ToolError(`File not found: ${file}${hint}
|
|
18876
|
+
Use glob to find the correct path.`, {
|
|
18613
18877
|
tool: "find_in_file"
|
|
18614
18878
|
});
|
|
18615
18879
|
}
|
|
@@ -18621,6 +18885,7 @@ Examples:
|
|
|
18621
18885
|
}
|
|
18622
18886
|
});
|
|
18623
18887
|
var searchTools = [grepTool, findInFileTool];
|
|
18888
|
+
init_errors();
|
|
18624
18889
|
var DEFAULT_TIMEOUT_MS3 = 3e4;
|
|
18625
18890
|
var MAX_RESPONSE_SIZE = 5 * 1024 * 1024;
|
|
18626
18891
|
var httpFetchTool = defineTool({
|
|
@@ -18762,6 +19027,7 @@ Examples:
|
|
|
18762
19027
|
}
|
|
18763
19028
|
});
|
|
18764
19029
|
var httpTools = [httpFetchTool, httpJsonTool];
|
|
19030
|
+
init_errors();
|
|
18765
19031
|
var DEFAULT_TIMEOUT_MS4 = 6e5;
|
|
18766
19032
|
var MAX_OUTPUT_SIZE2 = 2 * 1024 * 1024;
|
|
18767
19033
|
function getBuildHint(stderr, tool) {
|
|
@@ -19887,6 +20153,7 @@ Examples:
|
|
|
19887
20153
|
}
|
|
19888
20154
|
});
|
|
19889
20155
|
var permissionsTools = [managePermissionsTool];
|
|
20156
|
+
init_errors();
|
|
19890
20157
|
var DEFAULT_SEARCH_TIMEOUT_MS = 15e3;
|
|
19891
20158
|
var MAX_QUERY_LENGTH = 500;
|
|
19892
20159
|
var MIN_REQUEST_INTERVAL_MS = 1e3;
|
|
@@ -20127,6 +20394,7 @@ Examples:
|
|
|
20127
20394
|
}
|
|
20128
20395
|
}
|
|
20129
20396
|
});
|
|
20397
|
+
init_errors();
|
|
20130
20398
|
var DEFAULT_TIMEOUT_MS5 = 3e4;
|
|
20131
20399
|
var DEFAULT_MAX_LENGTH = 8e3;
|
|
20132
20400
|
var MAX_DOWNLOAD_SIZE = 10 * 1024 * 1024;
|
|
@@ -20462,6 +20730,7 @@ Examples:
|
|
|
20462
20730
|
|
|
20463
20731
|
// src/tools/web.ts
|
|
20464
20732
|
var webTools = [webSearchTool, webFetchTool];
|
|
20733
|
+
init_errors();
|
|
20465
20734
|
hljs.registerLanguage("bash", bash);
|
|
20466
20735
|
hljs.registerLanguage("css", css);
|
|
20467
20736
|
hljs.registerLanguage("dockerfile", dockerfile);
|
|
@@ -20492,63 +20761,63 @@ var LANG_ALIASES = {
|
|
|
20492
20761
|
};
|
|
20493
20762
|
var TOKEN_COLORS = {
|
|
20494
20763
|
// Keywords & control flow
|
|
20495
|
-
keyword: (t) =>
|
|
20496
|
-
"keyword.control": (t) =>
|
|
20764
|
+
keyword: (t) => chalk5.blue(t),
|
|
20765
|
+
"keyword.control": (t) => chalk5.blue(t),
|
|
20497
20766
|
// Built-in types and literals
|
|
20498
|
-
built_in: (t) =>
|
|
20499
|
-
type: (t) =>
|
|
20500
|
-
class: (t) =>
|
|
20501
|
-
"title.class": (t) =>
|
|
20502
|
-
"title.class.inherited": (t) =>
|
|
20767
|
+
built_in: (t) => chalk5.cyan(t),
|
|
20768
|
+
type: (t) => chalk5.cyan(t),
|
|
20769
|
+
class: (t) => chalk5.cyan(t),
|
|
20770
|
+
"title.class": (t) => chalk5.cyan(t),
|
|
20771
|
+
"title.class.inherited": (t) => chalk5.cyan(t),
|
|
20503
20772
|
// Functions
|
|
20504
|
-
"title.function": (t) =>
|
|
20505
|
-
"title.function.invoke": (t) =>
|
|
20506
|
-
title: (t) =>
|
|
20773
|
+
"title.function": (t) => chalk5.green(t),
|
|
20774
|
+
"title.function.invoke": (t) => chalk5.green(t),
|
|
20775
|
+
title: (t) => chalk5.green(t),
|
|
20507
20776
|
// Strings
|
|
20508
|
-
string: (t) =>
|
|
20509
|
-
"template-tag": (t) =>
|
|
20510
|
-
"template-variable": (t) =>
|
|
20777
|
+
string: (t) => chalk5.yellow(t),
|
|
20778
|
+
"template-tag": (t) => chalk5.yellow(t),
|
|
20779
|
+
"template-variable": (t) => chalk5.green(t),
|
|
20511
20780
|
// Numbers
|
|
20512
|
-
number: (t) =>
|
|
20781
|
+
number: (t) => chalk5.magenta(t),
|
|
20513
20782
|
// Literals (true, false, null)
|
|
20514
|
-
literal: (t) =>
|
|
20783
|
+
literal: (t) => chalk5.magenta(t),
|
|
20515
20784
|
// Comments
|
|
20516
|
-
comment: (t) =>
|
|
20517
|
-
doctag: (t) =>
|
|
20785
|
+
comment: (t) => chalk5.dim(t),
|
|
20786
|
+
doctag: (t) => chalk5.dim.bold(t),
|
|
20518
20787
|
// Regular expressions
|
|
20519
|
-
regexp: (t) =>
|
|
20788
|
+
regexp: (t) => chalk5.red(t),
|
|
20520
20789
|
// Attributes & properties
|
|
20521
|
-
attr: (t) =>
|
|
20522
|
-
attribute: (t) =>
|
|
20523
|
-
property: (t) =>
|
|
20790
|
+
attr: (t) => chalk5.cyan(t),
|
|
20791
|
+
attribute: (t) => chalk5.cyan(t),
|
|
20792
|
+
property: (t) => chalk5.white(t),
|
|
20524
20793
|
// Operators & punctuation
|
|
20525
|
-
operator: (t) =>
|
|
20526
|
-
punctuation: (t) =>
|
|
20794
|
+
operator: (t) => chalk5.dim.white(t),
|
|
20795
|
+
punctuation: (t) => chalk5.dim.white(t),
|
|
20527
20796
|
// Meta / preprocessor
|
|
20528
|
-
meta: (t) =>
|
|
20529
|
-
"meta keyword": (t) =>
|
|
20530
|
-
"meta string": (t) =>
|
|
20797
|
+
meta: (t) => chalk5.dim(t),
|
|
20798
|
+
"meta keyword": (t) => chalk5.blue(t),
|
|
20799
|
+
"meta string": (t) => chalk5.yellow(t),
|
|
20531
20800
|
// Variables & params
|
|
20532
|
-
variable: (t) =>
|
|
20533
|
-
"variable.language": (t) =>
|
|
20534
|
-
params: (t) =>
|
|
20801
|
+
variable: (t) => chalk5.white(t),
|
|
20802
|
+
"variable.language": (t) => chalk5.blue(t),
|
|
20803
|
+
params: (t) => chalk5.white(t),
|
|
20535
20804
|
// Tags (HTML/XML)
|
|
20536
|
-
tag: (t) =>
|
|
20537
|
-
name: (t) =>
|
|
20805
|
+
tag: (t) => chalk5.blue(t),
|
|
20806
|
+
name: (t) => chalk5.blue(t),
|
|
20538
20807
|
// Symbols & selectors (CSS, Ruby)
|
|
20539
|
-
symbol: (t) =>
|
|
20540
|
-
selector: (t) =>
|
|
20541
|
-
"selector-tag": (t) =>
|
|
20542
|
-
"selector-class": (t) =>
|
|
20543
|
-
"selector-id": (t) =>
|
|
20808
|
+
symbol: (t) => chalk5.magenta(t),
|
|
20809
|
+
selector: (t) => chalk5.green(t),
|
|
20810
|
+
"selector-tag": (t) => chalk5.blue(t),
|
|
20811
|
+
"selector-class": (t) => chalk5.green(t),
|
|
20812
|
+
"selector-id": (t) => chalk5.cyan(t),
|
|
20544
20813
|
// Additions/deletions (diffs)
|
|
20545
|
-
addition: (t) =>
|
|
20546
|
-
deletion: (t) =>
|
|
20814
|
+
addition: (t) => chalk5.green(t),
|
|
20815
|
+
deletion: (t) => chalk5.red(t),
|
|
20547
20816
|
// Section headers
|
|
20548
|
-
section: (t) =>
|
|
20817
|
+
section: (t) => chalk5.bold(t),
|
|
20549
20818
|
// Emphasis
|
|
20550
|
-
emphasis: (t) =>
|
|
20551
|
-
strong: (t) =>
|
|
20819
|
+
emphasis: (t) => chalk5.italic(t),
|
|
20820
|
+
strong: (t) => chalk5.bold(t)
|
|
20552
20821
|
};
|
|
20553
20822
|
function hljsToChalk(html) {
|
|
20554
20823
|
const safeSpans = [];
|
|
@@ -20603,10 +20872,10 @@ function highlightLine(line, lang) {
|
|
|
20603
20872
|
}
|
|
20604
20873
|
|
|
20605
20874
|
// src/cli/repl/output/diff-renderer.ts
|
|
20606
|
-
var bgDeleteLine =
|
|
20607
|
-
var bgAddLine =
|
|
20608
|
-
var bgDeleteWord =
|
|
20609
|
-
var bgAddWord =
|
|
20875
|
+
var bgDeleteLine = chalk5.bgRgb(80, 20, 20);
|
|
20876
|
+
var bgAddLine = chalk5.bgRgb(20, 60, 20);
|
|
20877
|
+
var bgDeleteWord = chalk5.bgRgb(160, 40, 40);
|
|
20878
|
+
var bgAddWord = chalk5.bgRgb(40, 120, 40);
|
|
20610
20879
|
function parseDiff(raw) {
|
|
20611
20880
|
const files = [];
|
|
20612
20881
|
const lines = raw.split("\n");
|
|
@@ -20772,9 +21041,6 @@ function highlightWordChanges(deletedContent, addedContent) {
|
|
|
20772
21041
|
return { styledDelete, styledAdd };
|
|
20773
21042
|
}
|
|
20774
21043
|
var getTerminalWidth = () => process.stdout.columns || 80;
|
|
20775
|
-
function stripAnsi(str) {
|
|
20776
|
-
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
20777
|
-
}
|
|
20778
21044
|
function detectLanguage2(filePath) {
|
|
20779
21045
|
const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
20780
21046
|
const extMap = {
|
|
@@ -20800,43 +21066,37 @@ function detectLanguage2(filePath) {
|
|
|
20800
21066
|
}
|
|
20801
21067
|
function renderDiff(diff, options) {
|
|
20802
21068
|
const showLineNumbers = options?.showLineNumbers ?? true;
|
|
20803
|
-
|
|
21069
|
+
options?.maxWidth ?? Math.min(getTerminalWidth() - 2, 120);
|
|
20804
21070
|
const compact = options?.compact ?? false;
|
|
20805
21071
|
if (diff.files.length === 0) {
|
|
20806
|
-
console.log(
|
|
21072
|
+
console.log(chalk5.dim("\n No changes\n"));
|
|
20807
21073
|
return;
|
|
20808
21074
|
}
|
|
20809
21075
|
for (const file of diff.files) {
|
|
20810
|
-
renderFileBlock(file, { showLineNumbers,
|
|
21076
|
+
renderFileBlock(file, { showLineNumbers, compact });
|
|
20811
21077
|
}
|
|
20812
21078
|
const { stats } = diff;
|
|
20813
21079
|
const parts = [];
|
|
20814
21080
|
parts.push(`${stats.filesChanged} file${stats.filesChanged !== 1 ? "s" : ""}`);
|
|
20815
|
-
if (stats.additions > 0) parts.push(
|
|
20816
|
-
if (stats.deletions > 0) parts.push(
|
|
20817
|
-
console.log(
|
|
21081
|
+
if (stats.additions > 0) parts.push(chalk5.green(`+${stats.additions}`));
|
|
21082
|
+
if (stats.deletions > 0) parts.push(chalk5.red(`-${stats.deletions}`));
|
|
21083
|
+
console.log(chalk5.dim(`
|
|
20818
21084
|
${parts.join(", ")}
|
|
20819
21085
|
`));
|
|
20820
21086
|
}
|
|
20821
21087
|
function renderFileBlock(file, opts) {
|
|
20822
|
-
const {
|
|
21088
|
+
const { showLineNumbers, compact } = opts;
|
|
20823
21089
|
const lang = detectLanguage2(file.path);
|
|
20824
|
-
const contentWidth = Math.max(1, maxWidth - 4);
|
|
20825
21090
|
const typeLabel = file.type === "modified" ? "modified" : file.type === "added" ? "new file" : file.type === "deleted" ? "deleted" : `renamed from ${file.oldPath}`;
|
|
20826
21091
|
const statsLabel = ` +${file.additions} -${file.deletions}`;
|
|
20827
|
-
const title =
|
|
20828
|
-
|
|
20829
|
-
console.log(
|
|
20830
|
-
chalk4.magenta("\u256D\u2500\u2500") + chalk4.cyan.bold(title) + chalk4.magenta("\u2500".repeat(topFill) + "\u256E")
|
|
20831
|
-
);
|
|
21092
|
+
const title = `${file.path} (${typeLabel}${statsLabel})`;
|
|
21093
|
+
console.log(chalk5.cyan.bold(title));
|
|
20832
21094
|
for (let h = 0; h < file.hunks.length; h++) {
|
|
20833
21095
|
const hunk = file.hunks[h];
|
|
20834
21096
|
if (!compact || h > 0) {
|
|
20835
|
-
const hunkLabel = hunk.heading ? ` ${
|
|
21097
|
+
const hunkLabel = hunk.heading ? ` ${chalk5.dim(hunk.heading)}` : "";
|
|
20836
21098
|
console.log(
|
|
20837
|
-
|
|
20838
|
-
`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`
|
|
20839
|
-
) + hunkLabel
|
|
21099
|
+
chalk5.cyan(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`) + hunkLabel
|
|
20840
21100
|
);
|
|
20841
21101
|
}
|
|
20842
21102
|
const pairs = pairAdjacentLines(hunk.lines);
|
|
@@ -20862,12 +21122,11 @@ function renderFileBlock(file, opts) {
|
|
|
20862
21122
|
} else {
|
|
20863
21123
|
content = line.content;
|
|
20864
21124
|
}
|
|
20865
|
-
|
|
20866
|
-
|
|
20867
|
-
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
);
|
|
21125
|
+
if (lang) {
|
|
21126
|
+
content = highlightLine(content, lang);
|
|
21127
|
+
}
|
|
21128
|
+
const lineStr = `${lineNo}${prefix} ${content}`;
|
|
21129
|
+
console.log(bgAddLine(lineStr));
|
|
20871
21130
|
} else if (line.type === "delete") {
|
|
20872
21131
|
const isPaired = pairedDeleteIndices.has(li);
|
|
20873
21132
|
let content;
|
|
@@ -20876,32 +21135,27 @@ function renderFileBlock(file, opts) {
|
|
|
20876
21135
|
} else {
|
|
20877
21136
|
content = line.content;
|
|
20878
21137
|
}
|
|
20879
|
-
|
|
20880
|
-
|
|
20881
|
-
|
|
20882
|
-
|
|
20883
|
-
|
|
20884
|
-
);
|
|
21138
|
+
if (lang) {
|
|
21139
|
+
content = highlightLine(content, lang);
|
|
21140
|
+
}
|
|
21141
|
+
const lineStr = `${lineNo}${prefix} ${content}`;
|
|
21142
|
+
console.log(bgDeleteLine(lineStr));
|
|
20885
21143
|
} else {
|
|
20886
21144
|
let content = line.content;
|
|
20887
21145
|
if (lang) {
|
|
20888
21146
|
content = highlightLine(content, lang);
|
|
20889
21147
|
}
|
|
20890
21148
|
const lineStr = `${lineNo}${prefix} ${content}`;
|
|
20891
|
-
|
|
20892
|
-
const pad = Math.max(0, contentWidth - plainLen);
|
|
20893
|
-
console.log(
|
|
20894
|
-
chalk4.magenta("\u2502") + chalk4.dim(` ${lineStr}`) + " ".repeat(pad) + " " + chalk4.magenta("\u2502")
|
|
20895
|
-
);
|
|
21149
|
+
console.log(chalk5.dim(lineStr));
|
|
20896
21150
|
}
|
|
20897
21151
|
}
|
|
20898
21152
|
}
|
|
20899
|
-
console.log(
|
|
21153
|
+
console.log();
|
|
20900
21154
|
}
|
|
20901
21155
|
function formatLineNo(line, show) {
|
|
20902
21156
|
if (!show) return "";
|
|
20903
21157
|
const lineNo = line.type === "delete" ? line.oldLineNo : line.newLineNo;
|
|
20904
|
-
return
|
|
21158
|
+
return chalk5.dim(`${String(lineNo ?? "").padStart(5)} `);
|
|
20905
21159
|
}
|
|
20906
21160
|
function getChangedLines(diff) {
|
|
20907
21161
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -20998,6 +21252,10 @@ Examples:
|
|
|
20998
21252
|
}
|
|
20999
21253
|
});
|
|
21000
21254
|
var diffTools = [showDiffTool];
|
|
21255
|
+
init_errors();
|
|
21256
|
+
|
|
21257
|
+
// src/utils/files.ts
|
|
21258
|
+
init_errors();
|
|
21001
21259
|
async function fileExists(filePath) {
|
|
21002
21260
|
try {
|
|
21003
21261
|
await fs16__default.access(filePath);
|
|
@@ -21509,6 +21767,7 @@ Examples:
|
|
|
21509
21767
|
}
|
|
21510
21768
|
});
|
|
21511
21769
|
var reviewTools = [reviewCodeTool];
|
|
21770
|
+
init_errors();
|
|
21512
21771
|
var fs25 = await import('fs/promises');
|
|
21513
21772
|
var path27 = await import('path');
|
|
21514
21773
|
var { glob: glob14 } = await import('glob');
|
|
@@ -22023,6 +22282,7 @@ Examples:
|
|
|
22023
22282
|
}
|
|
22024
22283
|
});
|
|
22025
22284
|
var codebaseMapTools = [codebaseMapTool];
|
|
22285
|
+
init_errors();
|
|
22026
22286
|
init_paths();
|
|
22027
22287
|
var fs26 = await import('fs/promises');
|
|
22028
22288
|
var path28 = await import('path');
|
|
@@ -22218,6 +22478,7 @@ Examples:
|
|
|
22218
22478
|
}
|
|
22219
22479
|
});
|
|
22220
22480
|
var memoryTools = [createMemoryTool, recallMemoryTool, listMemoriesTool];
|
|
22481
|
+
init_errors();
|
|
22221
22482
|
var fs27 = await import('fs/promises');
|
|
22222
22483
|
var crypto3 = await import('crypto');
|
|
22223
22484
|
var CHECKPOINT_FILE = ".coco/checkpoints.json";
|
|
@@ -22661,6 +22922,7 @@ Examples:
|
|
|
22661
22922
|
}
|
|
22662
22923
|
});
|
|
22663
22924
|
var semanticSearchTools = [semanticSearchTool];
|
|
22925
|
+
init_errors();
|
|
22664
22926
|
var fs29 = await import('fs/promises');
|
|
22665
22927
|
var path30 = await import('path');
|
|
22666
22928
|
var { glob: glob16 } = await import('glob');
|
|
@@ -22995,6 +23257,7 @@ Examples:
|
|
|
22995
23257
|
}
|
|
22996
23258
|
});
|
|
22997
23259
|
var diagramTools = [generateDiagramTool];
|
|
23260
|
+
init_errors();
|
|
22998
23261
|
var fs30 = await import('fs/promises');
|
|
22999
23262
|
var path31 = await import('path');
|
|
23000
23263
|
var DEFAULT_MAX_PAGES = 20;
|
|
@@ -23111,6 +23374,7 @@ Examples:
|
|
|
23111
23374
|
}
|
|
23112
23375
|
});
|
|
23113
23376
|
var pdfTools = [readPdfTool];
|
|
23377
|
+
init_errors();
|
|
23114
23378
|
var fs31 = await import('fs/promises');
|
|
23115
23379
|
var path32 = await import('path');
|
|
23116
23380
|
var SUPPORTED_FORMATS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp"]);
|
|
@@ -23295,6 +23559,7 @@ Examples:
|
|
|
23295
23559
|
}
|
|
23296
23560
|
});
|
|
23297
23561
|
var imageTools = [readImageTool];
|
|
23562
|
+
init_errors();
|
|
23298
23563
|
var path33 = await import('path');
|
|
23299
23564
|
var DANGEROUS_PATTERNS = [
|
|
23300
23565
|
/\bDROP\s+(?:TABLE|DATABASE|INDEX|VIEW)\b/i,
|
|
@@ -24668,6 +24933,7 @@ var recommendBranchTool = defineTool({
|
|
|
24668
24933
|
}
|
|
24669
24934
|
});
|
|
24670
24935
|
var gitEnhancedTools = [analyzeRepoHealthTool, getCommitStatsTool, recommendBranchTool];
|
|
24936
|
+
init_errors();
|
|
24671
24937
|
async function ghExec(args, cwd) {
|
|
24672
24938
|
try {
|
|
24673
24939
|
const result = await execa("gh", args, {
|
|
@@ -24852,6 +25118,8 @@ var githubTools = [
|
|
|
24852
25118
|
ghPrListTool,
|
|
24853
25119
|
ghReleaseCreateTool
|
|
24854
25120
|
];
|
|
25121
|
+
init_errors();
|
|
25122
|
+
init_platform();
|
|
24855
25123
|
var INTERPRETER_MAP = {
|
|
24856
25124
|
".py": ["python3"],
|
|
24857
25125
|
".sh": ["bash"],
|
|
@@ -25160,6 +25428,9 @@ function createFullToolRegistry() {
|
|
|
25160
25428
|
return registry;
|
|
25161
25429
|
}
|
|
25162
25430
|
|
|
25431
|
+
// src/index.ts
|
|
25432
|
+
init_errors();
|
|
25433
|
+
|
|
25163
25434
|
export { ADRGenerator, AnthropicProvider, ArchitectureGenerator, BacklogGenerator, CICDGenerator, CocoError, CodeGenerator, CodeReviewer, CompleteExecutor, ConfigError, ConvergeExecutor, DiscoveryEngine, DockerGenerator, DocsGenerator, OrchestrateExecutor, OutputExecutor, PhaseError, SessionManager, SpecificationGenerator, TaskError, TaskIterator, ToolRegistry, VERSION, configExists, createADRGenerator, createAnthropicProvider, createArchitectureGenerator, createBacklogGenerator, createCICDGenerator, createCodeGenerator, createCodeReviewer, createCompleteExecutor, createConvergeExecutor, createDefaultConfig, createDiscoveryEngine, createDockerGenerator, createDocsGenerator, createFullToolRegistry, createLogger, createOrchestrateExecutor, createOrchestrator, createOutputExecutor, createProvider, createSessionManager, createSpecificationGenerator, createTaskIterator, createToolRegistry, loadConfig, registerAllTools, saveConfig };
|
|
25164
25435
|
//# sourceMappingURL=index.js.map
|
|
25165
25436
|
//# sourceMappingURL=index.js.map
|