@corbat-tech/coco 2.28.5 → 2.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +201 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +142 -2
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { execFile, execFileSync, execSync, spawn, exec } from 'child_process';
|
|
3
|
+
import { setGlobalDispatcher, EnvHttpProxyAgent } from 'undici';
|
|
2
4
|
import * as fs5 from 'fs';
|
|
3
5
|
import fs5__default, { accessSync, readFileSync, constants as constants$1 } from 'fs';
|
|
4
6
|
import * as path39 from 'path';
|
|
@@ -13,7 +15,6 @@ import JSON5 from 'json5';
|
|
|
13
15
|
import * as crypto from 'crypto';
|
|
14
16
|
import { randomUUID, randomBytes, createHash } from 'crypto';
|
|
15
17
|
import * as http from 'http';
|
|
16
|
-
import { execFile, execSync, spawn, execFileSync, exec } from 'child_process';
|
|
17
18
|
import { promisify } from 'util';
|
|
18
19
|
import * as p26 from '@clack/prompts';
|
|
19
20
|
import chalk from 'chalk';
|
|
@@ -62,6 +63,167 @@ var __export = (target, all) => {
|
|
|
62
63
|
for (var name in all)
|
|
63
64
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
64
65
|
};
|
|
66
|
+
function getProxyFromEnv() {
|
|
67
|
+
for (const key of PROXY_ENV_VARS) {
|
|
68
|
+
const value = process.env[key];
|
|
69
|
+
if (value && value.trim().length > 0) {
|
|
70
|
+
return value.trim();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
function maskProxyUrl(url) {
|
|
76
|
+
try {
|
|
77
|
+
const parsed = new URL(url);
|
|
78
|
+
if (parsed.password) {
|
|
79
|
+
parsed.password = "***";
|
|
80
|
+
}
|
|
81
|
+
return parsed.toString();
|
|
82
|
+
} catch {
|
|
83
|
+
return "[invalid proxy URL]";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function defaultRunner(cmd, args) {
|
|
87
|
+
try {
|
|
88
|
+
return execFileSync(cmd, args, {
|
|
89
|
+
encoding: "utf-8",
|
|
90
|
+
timeout: 2e3,
|
|
91
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
92
|
+
});
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function parseMacOsProxy(output) {
|
|
98
|
+
const getField = (name) => {
|
|
99
|
+
const re = new RegExp(`^\\s*${name}\\s*:\\s*(.+?)\\s*$`, "m");
|
|
100
|
+
return output.match(re)?.[1];
|
|
101
|
+
};
|
|
102
|
+
if (getField("ProxyAutoConfigEnable") === "1") {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const pick = (prefix) => {
|
|
106
|
+
if (getField(`${prefix}Enable`) !== "1") return null;
|
|
107
|
+
const host = getField(`${prefix}Proxy`);
|
|
108
|
+
const port = getField(`${prefix}Port`);
|
|
109
|
+
if (!host) return null;
|
|
110
|
+
return `http://${host}${port ? `:${port}` : ""}`;
|
|
111
|
+
};
|
|
112
|
+
const proxyUrl = pick("HTTPS") ?? pick("HTTP");
|
|
113
|
+
if (!proxyUrl) return null;
|
|
114
|
+
const exceptionsMatch = output.match(/ExceptionsList\s*:\s*<array>\s*\{([\s\S]*?)\}/);
|
|
115
|
+
const exceptions = [];
|
|
116
|
+
const exceptionsBody = exceptionsMatch?.[1];
|
|
117
|
+
if (exceptionsBody) {
|
|
118
|
+
for (const line of exceptionsBody.split("\n")) {
|
|
119
|
+
const entry = line.match(/^\s*\d+\s*:\s*(.+?)\s*$/)?.[1];
|
|
120
|
+
if (entry) exceptions.push(entry);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
proxyUrl,
|
|
125
|
+
noProxy: exceptions.length > 0 ? exceptions.join(",") : void 0
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function parseWindowsProxy(output) {
|
|
129
|
+
if (/Direct access/i.test(output)) return null;
|
|
130
|
+
const raw = output.match(/Proxy\s+Server\(s\)\s*:\s*(\S.*?)\s*$/m)?.[1]?.trim();
|
|
131
|
+
if (!raw) return null;
|
|
132
|
+
let hostPort = raw;
|
|
133
|
+
if (raw.includes("=")) {
|
|
134
|
+
const parts = raw.split(";").map((p47) => p47.trim());
|
|
135
|
+
const httpsEntry = parts.find((p47) => p47.toLowerCase().startsWith("https="));
|
|
136
|
+
const httpEntry = parts.find((p47) => p47.toLowerCase().startsWith("http="));
|
|
137
|
+
const chosen = httpsEntry ?? httpEntry;
|
|
138
|
+
if (!chosen) return null;
|
|
139
|
+
hostPort = chosen.split("=", 2)[1]?.trim() ?? "";
|
|
140
|
+
if (!hostPort) return null;
|
|
141
|
+
}
|
|
142
|
+
const proxyUrl = /^https?:\/\//i.test(hostPort) ? hostPort : `http://${hostPort}`;
|
|
143
|
+
let noProxy;
|
|
144
|
+
const bypass = output.match(/Bypass\s+List\s*:\s*(\S.*?)\s*$/m)?.[1]?.trim();
|
|
145
|
+
if (bypass && !/\(none\)/i.test(bypass)) {
|
|
146
|
+
noProxy = bypass.replace(/;/g, ",");
|
|
147
|
+
}
|
|
148
|
+
return { proxyUrl, noProxy };
|
|
149
|
+
}
|
|
150
|
+
function getProxyFromSystem(platform = process.platform, run = defaultRunner) {
|
|
151
|
+
if (platform === "darwin") {
|
|
152
|
+
const out = run("scutil", ["--proxy"]);
|
|
153
|
+
return out ? parseMacOsProxy(out) : null;
|
|
154
|
+
}
|
|
155
|
+
if (platform === "win32") {
|
|
156
|
+
const out = run("netsh", ["winhttp", "show", "proxy"]);
|
|
157
|
+
return out ? parseWindowsProxy(out) : null;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
function installProxyDispatcher(resolveSystem = () => getProxyFromSystem()) {
|
|
162
|
+
if (installed) {
|
|
163
|
+
const existing = getProxyFromEnv();
|
|
164
|
+
return existing ? maskProxyUrl(existing) : null;
|
|
165
|
+
}
|
|
166
|
+
const envProxy = getProxyFromEnv();
|
|
167
|
+
if (envProxy) {
|
|
168
|
+
return applyDispatcher(envProxy);
|
|
169
|
+
}
|
|
170
|
+
const sys = resolveSystem();
|
|
171
|
+
if (sys) {
|
|
172
|
+
seedEnv("HTTPS_PROXY", sys.proxyUrl);
|
|
173
|
+
seedEnv("HTTP_PROXY", sys.proxyUrl);
|
|
174
|
+
if (sys.noProxy && !process.env.NO_PROXY && !process.env.no_proxy) {
|
|
175
|
+
seedEnv("NO_PROXY", sys.noProxy);
|
|
176
|
+
}
|
|
177
|
+
return applyDispatcher(sys.proxyUrl);
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
function seedEnv(key, value) {
|
|
182
|
+
if (process.env[key] !== void 0) return;
|
|
183
|
+
process.env[key] = value;
|
|
184
|
+
seededEnvKeys.push(key);
|
|
185
|
+
}
|
|
186
|
+
function applyDispatcher(proxyUrl) {
|
|
187
|
+
try {
|
|
188
|
+
setGlobalDispatcher(new EnvHttpProxyAgent());
|
|
189
|
+
installed = true;
|
|
190
|
+
return maskProxyUrl(proxyUrl);
|
|
191
|
+
} catch {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function describeFetchError(error) {
|
|
196
|
+
if (!(error instanceof Error)) {
|
|
197
|
+
return {};
|
|
198
|
+
}
|
|
199
|
+
const cause = unwrapCause(error);
|
|
200
|
+
return {
|
|
201
|
+
code: cause?.code,
|
|
202
|
+
hostname: cause?.hostname
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function unwrapCause(error) {
|
|
206
|
+
let current = error;
|
|
207
|
+
let depth = 0;
|
|
208
|
+
while (current && depth < 5) {
|
|
209
|
+
const next = current.cause;
|
|
210
|
+
if (!next) break;
|
|
211
|
+
current = next;
|
|
212
|
+
depth++;
|
|
213
|
+
}
|
|
214
|
+
if (current && typeof current === "object") {
|
|
215
|
+
return current;
|
|
216
|
+
}
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
var PROXY_ENV_VARS, installed, seededEnvKeys;
|
|
220
|
+
var init_proxy = __esm({
|
|
221
|
+
"src/utils/proxy.ts"() {
|
|
222
|
+
PROXY_ENV_VARS = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"];
|
|
223
|
+
installed = false;
|
|
224
|
+
seededEnvKeys = [];
|
|
225
|
+
}
|
|
226
|
+
});
|
|
65
227
|
function findPackageJson() {
|
|
66
228
|
let dir = dirname(fileURLToPath(import.meta.url));
|
|
67
229
|
for (let i = 0; i < 10; i++) {
|
|
@@ -1944,8 +2106,15 @@ async function runBrowserOAuthFlow(provider) {
|
|
|
1944
2106
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1945
2107
|
console.log();
|
|
1946
2108
|
console.log(chalk.yellow(" \u26A0 Browser authentication failed"));
|
|
1947
|
-
const
|
|
1948
|
-
|
|
2109
|
+
const isNetwork = errorMsg.includes("fetch failed") || errorMsg.toLowerCase().includes("network error") || errorMsg.includes("ECONNREFUSED") || errorMsg.includes("ENOTFOUND") || errorMsg.includes("ETIMEDOUT");
|
|
2110
|
+
if (isNetwork) {
|
|
2111
|
+
const { code } = describeFetchError(error);
|
|
2112
|
+
console.log(chalk.dim(" Error: Network error"));
|
|
2113
|
+
printNetworkTroubleshooting(code);
|
|
2114
|
+
} else {
|
|
2115
|
+
const errorCategory = errorMsg.includes("timeout") || errorMsg.includes("Timeout") ? "Request timed out" : errorMsg.includes("401") || errorMsg.includes("403") ? "Authorization denied" : errorMsg.includes("invalid_grant") || errorMsg.includes("invalid_client") ? "Invalid credentials" : "Authentication error (see debug logs for details)";
|
|
2116
|
+
console.log(chalk.dim(` Error: ${errorCategory}`));
|
|
2117
|
+
}
|
|
1949
2118
|
console.log();
|
|
1950
2119
|
const fallbackOptions = [];
|
|
1951
2120
|
if (config?.deviceAuthEndpoint) {
|
|
@@ -2235,14 +2404,38 @@ async function runCopilotDeviceFlow() {
|
|
|
2235
2404
|
console.log(chalk.yellow(" \u26A0 Authentication timed out. Please try again."));
|
|
2236
2405
|
} else if (errorMsg.includes("denied")) {
|
|
2237
2406
|
console.log(chalk.yellow(" \u26A0 Access was denied."));
|
|
2407
|
+
} else if (errorMsg.includes("fetch failed") || errorMsg.toLowerCase().includes("network")) {
|
|
2408
|
+
const { code } = describeFetchError(error);
|
|
2409
|
+
console.log(chalk.red(" \u2717 Network error reaching GitHub"));
|
|
2410
|
+
printNetworkTroubleshooting(code);
|
|
2238
2411
|
} else {
|
|
2239
|
-
|
|
2240
|
-
console.log(chalk.red(` \u2717 ${category}`));
|
|
2412
|
+
console.log(chalk.red(" \u2717 Authentication error \u2014 see debug logs for details"));
|
|
2241
2413
|
}
|
|
2242
2414
|
console.log();
|
|
2243
2415
|
return null;
|
|
2244
2416
|
}
|
|
2245
2417
|
}
|
|
2418
|
+
function printNetworkTroubleshooting(code) {
|
|
2419
|
+
const proxy = getProxyFromEnv();
|
|
2420
|
+
if (proxy) {
|
|
2421
|
+
console.log(chalk.dim(` Proxy in use: ${maskProxyUrl(proxy)}`));
|
|
2422
|
+
console.log(chalk.dim(" \u2192 Verify the proxy allows github.com and api.github.com."));
|
|
2423
|
+
} else {
|
|
2424
|
+
console.log(chalk.dim(" No HTTPS_PROXY / HTTP_PROXY env vars detected."));
|
|
2425
|
+
console.log(chalk.dim(" \u2192 If you're behind a corporate proxy, set HTTPS_PROXY and retry."));
|
|
2426
|
+
}
|
|
2427
|
+
if (code === "SELF_SIGNED_CERT_IN_CHAIN" || code === "UNABLE_TO_VERIFY_LEAF_SIGNATURE") {
|
|
2428
|
+
console.log(
|
|
2429
|
+
chalk.dim(
|
|
2430
|
+
" \u2192 A TLS interceptor is rewriting certificates. Add your corp root CA to NODE_EXTRA_CA_CERTS."
|
|
2431
|
+
)
|
|
2432
|
+
);
|
|
2433
|
+
} else if (code === "ENOTFOUND") {
|
|
2434
|
+
console.log(chalk.dim(" \u2192 Check DNS: `nslookup github.com`"));
|
|
2435
|
+
} else if (code === "ETIMEDOUT" || code === "UND_ERR_CONNECT_TIMEOUT") {
|
|
2436
|
+
console.log(chalk.dim(" \u2192 A firewall may be dropping the connection silently."));
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2246
2439
|
async function getOrRefreshOAuthToken(provider) {
|
|
2247
2440
|
if (provider === "copilot") {
|
|
2248
2441
|
const tokenResult = await getValidCopilotToken();
|
|
@@ -2273,6 +2466,7 @@ var init_flow = __esm({
|
|
|
2273
2466
|
init_pkce();
|
|
2274
2467
|
init_callback_server();
|
|
2275
2468
|
init_platform();
|
|
2469
|
+
init_proxy();
|
|
2276
2470
|
init_copilot();
|
|
2277
2471
|
execFileAsync2 = promisify(execFile);
|
|
2278
2472
|
}
|
|
@@ -24937,6 +25131,7 @@ var init_input_echo = __esm({
|
|
|
24937
25131
|
});
|
|
24938
25132
|
|
|
24939
25133
|
// src/cli/index.ts
|
|
25134
|
+
init_proxy();
|
|
24940
25135
|
init_version();
|
|
24941
25136
|
|
|
24942
25137
|
// src/orchestrator/project.ts
|
|
@@ -56258,6 +56453,7 @@ ${stdinContent}
|
|
|
56258
56453
|
// src/cli/index.ts
|
|
56259
56454
|
init_env();
|
|
56260
56455
|
init_errors();
|
|
56456
|
+
installProxyDispatcher();
|
|
56261
56457
|
var program = new Command();
|
|
56262
56458
|
program.name("coco").description("Corbat-Coco: Autonomous Coding Agent with Self-Review and Quality Convergence").version(VERSION, "-v, --version", "Output the current version");
|
|
56263
56459
|
registerInitCommand(program);
|