@corbat-tech/coco 2.29.0 → 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/index.d.ts CHANGED
@@ -3252,12 +3252,17 @@ interface LoggerConfig {
3252
3252
  */
3253
3253
  declare function createLogger(config?: Partial<LoggerConfig>): Logger<ILogObj>;
3254
3254
 
3255
+ interface SystemProxyConfig {
3256
+ proxyUrl: string;
3257
+ noProxy?: string;
3258
+ }
3255
3259
  /**
3256
- * Install an undici EnvHttpProxyAgent as the global dispatcher when any
3257
- * proxy env var is set. Safe to call multiple times (idempotent).
3260
+ * Install an undici EnvHttpProxyAgent as the global dispatcher. Resolves
3261
+ * the proxy from env vars first, then from OS-level config as a fallback.
3262
+ * Safe to call multiple times (idempotent).
3258
3263
  *
3259
3264
  * Returns a masked proxy URL when a proxy is installed, or null otherwise.
3260
3265
  */
3261
- declare function installProxyDispatcher(): string | null;
3266
+ declare function installProxyDispatcher(resolveSystem?: () => SystemProxyConfig | null): string | null;
3262
3267
 
3263
3268
  export { ADRGenerator, AnthropicProvider, ArchitectureGenerator, type Backlog, BacklogGenerator, CICDGenerator, type ChatOptions, type ChatResponse, type CocoConfig, CocoError, CodeGenerator, CodeReviewer, CompleteExecutor, ConfigError, ConvergeExecutor, DiscoveryEngine, DockerGenerator, DocsGenerator, type Epic, type LLMProvider, type Message, OrchestrateExecutor, type Orchestrator, type OrchestratorConfig, OutputExecutor, type Phase, type PhaseContext, PhaseError, type PhaseExecutor, type PhaseResult, type Progress, type ProjectState, type QualityDimensions, type QualityScores, type QualityThresholds, SessionManager, SpecificationGenerator, type Sprint, type Story, type Task, TaskError, type TaskHistory, TaskIterator, type TaskVersion, 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, installProxyDispatcher, loadConfig, registerAllTools, saveConfig };
package/dist/index.js CHANGED
@@ -8,8 +8,8 @@ import fs16__default, { access, readFile, readdir, writeFile, mkdir } from 'fs/p
8
8
  import { randomUUID, randomBytes, createHash } from 'crypto';
9
9
  import * as http from 'http';
10
10
  import { fileURLToPath, URL as URL$1 } from 'url';
11
+ import { exec, execFile, execSync, execFileSync, spawn } from 'child_process';
11
12
  import { setGlobalDispatcher, EnvHttpProxyAgent } from 'undici';
12
- import { exec, execFile, execSync, spawn } from 'child_process';
13
13
  import { promisify } from 'util';
14
14
  import { z } from 'zod';
15
15
  import * as p4 from '@clack/prompts';
@@ -670,23 +670,121 @@ function maskProxyUrl(url) {
670
670
  return "[invalid proxy URL]";
671
671
  }
672
672
  }
673
- function installProxyDispatcher() {
674
- if (installed) return getProxyFromEnv() ? maskProxyUrl(getProxyFromEnv()) : null;
675
- const proxy = getProxyFromEnv();
676
- if (!proxy) return null;
673
+ function defaultRunner(cmd, args) {
674
+ try {
675
+ return execFileSync(cmd, args, {
676
+ encoding: "utf-8",
677
+ timeout: 2e3,
678
+ stdio: ["ignore", "pipe", "ignore"]
679
+ });
680
+ } catch {
681
+ return null;
682
+ }
683
+ }
684
+ function parseMacOsProxy(output) {
685
+ const getField = (name) => {
686
+ const re = new RegExp(`^\\s*${name}\\s*:\\s*(.+?)\\s*$`, "m");
687
+ return output.match(re)?.[1];
688
+ };
689
+ if (getField("ProxyAutoConfigEnable") === "1") {
690
+ return null;
691
+ }
692
+ const pick = (prefix) => {
693
+ if (getField(`${prefix}Enable`) !== "1") return null;
694
+ const host = getField(`${prefix}Proxy`);
695
+ const port = getField(`${prefix}Port`);
696
+ if (!host) return null;
697
+ return `http://${host}${port ? `:${port}` : ""}`;
698
+ };
699
+ const proxyUrl = pick("HTTPS") ?? pick("HTTP");
700
+ if (!proxyUrl) return null;
701
+ const exceptionsMatch = output.match(/ExceptionsList\s*:\s*<array>\s*\{([\s\S]*?)\}/);
702
+ const exceptions = [];
703
+ const exceptionsBody = exceptionsMatch?.[1];
704
+ if (exceptionsBody) {
705
+ for (const line of exceptionsBody.split("\n")) {
706
+ const entry = line.match(/^\s*\d+\s*:\s*(.+?)\s*$/)?.[1];
707
+ if (entry) exceptions.push(entry);
708
+ }
709
+ }
710
+ return {
711
+ proxyUrl,
712
+ noProxy: exceptions.length > 0 ? exceptions.join(",") : void 0
713
+ };
714
+ }
715
+ function parseWindowsProxy(output) {
716
+ if (/Direct access/i.test(output)) return null;
717
+ const raw = output.match(/Proxy\s+Server\(s\)\s*:\s*(\S.*?)\s*$/m)?.[1]?.trim();
718
+ if (!raw) return null;
719
+ let hostPort = raw;
720
+ if (raw.includes("=")) {
721
+ const parts = raw.split(";").map((p5) => p5.trim());
722
+ const httpsEntry = parts.find((p5) => p5.toLowerCase().startsWith("https="));
723
+ const httpEntry = parts.find((p5) => p5.toLowerCase().startsWith("http="));
724
+ const chosen = httpsEntry ?? httpEntry;
725
+ if (!chosen) return null;
726
+ hostPort = chosen.split("=", 2)[1]?.trim() ?? "";
727
+ if (!hostPort) return null;
728
+ }
729
+ const proxyUrl = /^https?:\/\//i.test(hostPort) ? hostPort : `http://${hostPort}`;
730
+ let noProxy;
731
+ const bypass = output.match(/Bypass\s+List\s*:\s*(\S.*?)\s*$/m)?.[1]?.trim();
732
+ if (bypass && !/\(none\)/i.test(bypass)) {
733
+ noProxy = bypass.replace(/;/g, ",");
734
+ }
735
+ return { proxyUrl, noProxy };
736
+ }
737
+ function getProxyFromSystem(platform = process.platform, run = defaultRunner) {
738
+ if (platform === "darwin") {
739
+ const out = run("scutil", ["--proxy"]);
740
+ return out ? parseMacOsProxy(out) : null;
741
+ }
742
+ if (platform === "win32") {
743
+ const out = run("netsh", ["winhttp", "show", "proxy"]);
744
+ return out ? parseWindowsProxy(out) : null;
745
+ }
746
+ return null;
747
+ }
748
+ function installProxyDispatcher(resolveSystem = () => getProxyFromSystem()) {
749
+ if (installed) {
750
+ const existing = getProxyFromEnv();
751
+ return existing ? maskProxyUrl(existing) : null;
752
+ }
753
+ const envProxy = getProxyFromEnv();
754
+ if (envProxy) {
755
+ return applyDispatcher(envProxy);
756
+ }
757
+ const sys = resolveSystem();
758
+ if (sys) {
759
+ seedEnv("HTTPS_PROXY", sys.proxyUrl);
760
+ seedEnv("HTTP_PROXY", sys.proxyUrl);
761
+ if (sys.noProxy && !process.env.NO_PROXY && !process.env.no_proxy) {
762
+ seedEnv("NO_PROXY", sys.noProxy);
763
+ }
764
+ return applyDispatcher(sys.proxyUrl);
765
+ }
766
+ return null;
767
+ }
768
+ function seedEnv(key, value) {
769
+ if (process.env[key] !== void 0) return;
770
+ process.env[key] = value;
771
+ seededEnvKeys.push(key);
772
+ }
773
+ function applyDispatcher(proxyUrl) {
677
774
  try {
678
775
  setGlobalDispatcher(new EnvHttpProxyAgent());
679
776
  installed = true;
680
- return maskProxyUrl(proxy);
777
+ return maskProxyUrl(proxyUrl);
681
778
  } catch {
682
779
  return null;
683
780
  }
684
781
  }
685
- var PROXY_ENV_VARS, installed;
782
+ var PROXY_ENV_VARS, installed, seededEnvKeys;
686
783
  var init_proxy = __esm({
687
784
  "src/utils/proxy.ts"() {
688
785
  PROXY_ENV_VARS = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"];
689
786
  installed = false;
787
+ seededEnvKeys = [];
690
788
  }
691
789
  });
692
790
  async function exchangeForCopilotToken(githubToken) {