@corbat-tech/coco 2.9.0 → 2.11.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.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { homedir } from 'os';
2
- import * as path16 from 'path';
3
- import path16__default, { dirname, join, basename, resolve } from 'path';
2
+ import * as path17 from 'path';
3
+ import path17__default, { dirname, join, basename, resolve } from 'path';
4
4
  import * as fs4 from 'fs';
5
5
  import fs4__default, { readFileSync, constants } from 'fs';
6
- import * as fs15 from 'fs/promises';
7
- import fs15__default, { readFile, access, readdir } from 'fs/promises';
8
- import chalk3 from 'chalk';
9
- import * as p3 from '@clack/prompts';
6
+ import * as fs16 from 'fs/promises';
7
+ import fs16__default, { readFile, access, readdir } from 'fs/promises';
8
+ import chalk4 from 'chalk';
9
+ import * as p4 from '@clack/prompts';
10
10
  import { fileURLToPath } from 'url';
11
11
  import { randomUUID } from 'crypto';
12
12
  import { execa } from 'execa';
@@ -92,7 +92,7 @@ function loadGlobalCocoEnv() {
92
92
  try {
93
93
  const home = process.env.HOME || process.env.USERPROFILE || "";
94
94
  if (!home) return;
95
- const globalEnvPath = path16.join(home, ".coco", ".env");
95
+ const globalEnvPath = path17.join(home, ".coco", ".env");
96
96
  const content = fs4.readFileSync(globalEnvPath, "utf-8");
97
97
  for (const line of content.split("\n")) {
98
98
  const trimmed = line.trim();
@@ -128,6 +128,8 @@ function getApiKey(provider) {
128
128
  return process.env["OLLAMA_API_KEY"] ?? "ollama";
129
129
  case "codex":
130
130
  return void 0;
131
+ case "copilot":
132
+ return process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"];
131
133
  case "groq":
132
134
  return process.env["GROQ_API_KEY"];
133
135
  case "openrouter":
@@ -162,6 +164,8 @@ function getBaseUrl(provider) {
162
164
  return process.env["OLLAMA_BASE_URL"] ?? "http://localhost:11434/v1";
163
165
  case "codex":
164
166
  return "https://chatgpt.com/backend-api/codex/responses";
167
+ case "copilot":
168
+ return process.env["COPILOT_BASE_URL"] ?? "https://api.githubcopilot.com";
165
169
  case "groq":
166
170
  return process.env["GROQ_BASE_URL"] ?? "https://api.groq.com/openai/v1";
167
171
  case "openrouter":
@@ -183,11 +187,11 @@ function getBaseUrl(provider) {
183
187
  function getDefaultModel(provider) {
184
188
  switch (provider) {
185
189
  case "anthropic":
186
- return process.env["ANTHROPIC_MODEL"] ?? "claude-opus-4-6-20260115";
190
+ return process.env["ANTHROPIC_MODEL"] ?? "claude-opus-4-6";
187
191
  case "openai":
188
192
  return process.env["OPENAI_MODEL"] ?? "gpt-5.3-codex";
189
193
  case "gemini":
190
- return process.env["GEMINI_MODEL"] ?? "gemini-3-flash-preview";
194
+ return process.env["GEMINI_MODEL"] ?? "gemini-3.1-pro-preview";
191
195
  case "kimi":
192
196
  return process.env["KIMI_MODEL"] ?? "kimi-k2.5";
193
197
  case "kimi-code":
@@ -198,6 +202,8 @@ function getDefaultModel(provider) {
198
202
  return process.env["OLLAMA_MODEL"] ?? "llama3.1";
199
203
  case "codex":
200
204
  return process.env["CODEX_MODEL"] ?? "gpt-5.3-codex";
205
+ case "copilot":
206
+ return process.env["COPILOT_MODEL"] ?? "claude-sonnet-4.6";
201
207
  case "groq":
202
208
  return process.env["GROQ_MODEL"] ?? "llama-3.3-70b-versatile";
203
209
  case "openrouter":
@@ -232,6 +238,7 @@ var init_env = __esm({
232
238
  "anthropic",
233
239
  "openai",
234
240
  "codex",
241
+ "copilot",
235
242
  "gemini",
236
243
  "kimi",
237
244
  "kimi-code",
@@ -257,10 +264,10 @@ function getAllowedPaths() {
257
264
  return [...sessionAllowedPaths];
258
265
  }
259
266
  function isWithinAllowedPath(absolutePath, operation) {
260
- const normalizedTarget = path16__default.normalize(absolutePath);
267
+ const normalizedTarget = path17__default.normalize(absolutePath);
261
268
  for (const entry of sessionAllowedPaths) {
262
- const normalizedAllowed = path16__default.normalize(entry.path);
263
- if (normalizedTarget === normalizedAllowed || normalizedTarget.startsWith(normalizedAllowed + path16__default.sep)) {
269
+ const normalizedAllowed = path17__default.normalize(entry.path);
270
+ if (normalizedTarget === normalizedAllowed || normalizedTarget.startsWith(normalizedAllowed + path17__default.sep)) {
264
271
  if (operation === "read") return true;
265
272
  if (entry.level === "write") return true;
266
273
  }
@@ -268,8 +275,8 @@ function isWithinAllowedPath(absolutePath, operation) {
268
275
  return false;
269
276
  }
270
277
  function addAllowedPathToSession(dirPath, level) {
271
- const absolute = path16__default.resolve(dirPath);
272
- if (sessionAllowedPaths.some((e) => path16__default.normalize(e.path) === path16__default.normalize(absolute))) {
278
+ const absolute = path17__default.resolve(dirPath);
279
+ if (sessionAllowedPaths.some((e) => path17__default.normalize(e.path) === path17__default.normalize(absolute))) {
273
280
  return;
274
281
  }
275
282
  sessionAllowedPaths.push({
@@ -280,14 +287,14 @@ function addAllowedPathToSession(dirPath, level) {
280
287
  }
281
288
  async function persistAllowedPath(dirPath, level) {
282
289
  if (!currentProjectPath) return;
283
- const absolute = path16__default.resolve(dirPath);
290
+ const absolute = path17__default.resolve(dirPath);
284
291
  const store = await loadStore();
285
292
  if (!store.projects[currentProjectPath]) {
286
293
  store.projects[currentProjectPath] = [];
287
294
  }
288
295
  const entries = store.projects[currentProjectPath];
289
- const normalized = path16__default.normalize(absolute);
290
- if (entries.some((e) => path16__default.normalize(e.path) === normalized)) {
296
+ const normalized = path17__default.normalize(absolute);
297
+ if (entries.some((e) => path17__default.normalize(e.path) === normalized)) {
291
298
  return;
292
299
  }
293
300
  entries.push({
@@ -299,7 +306,7 @@ async function persistAllowedPath(dirPath, level) {
299
306
  }
300
307
  async function loadStore() {
301
308
  try {
302
- const content = await fs15__default.readFile(STORE_FILE, "utf-8");
309
+ const content = await fs16__default.readFile(STORE_FILE, "utf-8");
303
310
  return { ...DEFAULT_STORE, ...JSON.parse(content) };
304
311
  } catch {
305
312
  return { ...DEFAULT_STORE };
@@ -307,8 +314,8 @@ async function loadStore() {
307
314
  }
308
315
  async function saveStore(store) {
309
316
  try {
310
- await fs15__default.mkdir(path16__default.dirname(STORE_FILE), { recursive: true });
311
- await fs15__default.writeFile(STORE_FILE, JSON.stringify(store, null, 2), "utf-8");
317
+ await fs16__default.mkdir(path17__default.dirname(STORE_FILE), { recursive: true });
318
+ await fs16__default.writeFile(STORE_FILE, JSON.stringify(store, null, 2), "utf-8");
312
319
  } catch {
313
320
  }
314
321
  }
@@ -316,7 +323,7 @@ var STORE_FILE, DEFAULT_STORE, sessionAllowedPaths, currentProjectPath;
316
323
  var init_allowed_paths = __esm({
317
324
  "src/tools/allowed-paths.ts"() {
318
325
  init_paths();
319
- STORE_FILE = path16__default.join(CONFIG_PATHS.home, "allowed-paths.json");
326
+ STORE_FILE = path17__default.join(CONFIG_PATHS.home, "allowed-paths.json");
320
327
  DEFAULT_STORE = {
321
328
  version: 1,
322
329
  projects: {}
@@ -397,12 +404,12 @@ __export(allow_path_prompt_exports, {
397
404
  promptAllowPath: () => promptAllowPath
398
405
  });
399
406
  async function promptAllowPath(dirPath) {
400
- const absolute = path16__default.resolve(dirPath);
407
+ const absolute = path17__default.resolve(dirPath);
401
408
  console.log();
402
- console.log(chalk3.yellow(" \u26A0 Access denied \u2014 path is outside the project directory"));
403
- console.log(chalk3.dim(` \u{1F4C1} ${absolute}`));
409
+ console.log(chalk4.yellow(" \u26A0 Access denied \u2014 path is outside the project directory"));
410
+ console.log(chalk4.dim(` \u{1F4C1} ${absolute}`));
404
411
  console.log();
405
- const action = await p3.select({
412
+ const action = await p4.select({
406
413
  message: "Grant access to this directory?",
407
414
  options: [
408
415
  { value: "session-write", label: "\u2713 Allow write (this session)" },
@@ -412,7 +419,7 @@ async function promptAllowPath(dirPath) {
412
419
  { value: "no", label: "\u2717 Deny" }
413
420
  ]
414
421
  });
415
- if (p3.isCancel(action) || action === "no") {
422
+ if (p4.isCancel(action) || action === "no") {
416
423
  return false;
417
424
  }
418
425
  const level = action.includes("read") ? "read" : "write";
@@ -423,7 +430,7 @@ async function promptAllowPath(dirPath) {
423
430
  }
424
431
  const levelLabel = level === "write" ? "write" : "read-only";
425
432
  const persistLabel = persist ? " (remembered)" : "";
426
- console.log(chalk3.green(` \u2713 Access granted: ${levelLabel}${persistLabel}`));
433
+ console.log(chalk4.green(` \u2713 Access granted: ${levelLabel}${persistLabel}`));
427
434
  return true;
428
435
  }
429
436
  var init_allow_path_prompt = __esm({
@@ -1778,13 +1785,13 @@ function createSpecificationGenerator(llm, config) {
1778
1785
  return new SpecificationGenerator(llm, config);
1779
1786
  }
1780
1787
  function getPersistencePaths(projectPath) {
1781
- const baseDir = path16__default.join(projectPath, ".coco", "spec");
1788
+ const baseDir = path17__default.join(projectPath, ".coco", "spec");
1782
1789
  return {
1783
1790
  baseDir,
1784
- sessionFile: path16__default.join(baseDir, "discovery-session.json"),
1785
- specFile: path16__default.join(baseDir, "spec.md"),
1786
- conversationLog: path16__default.join(baseDir, "conversation.jsonl"),
1787
- checkpointFile: path16__default.join(baseDir, "checkpoint.json")
1791
+ sessionFile: path17__default.join(baseDir, "discovery-session.json"),
1792
+ specFile: path17__default.join(baseDir, "spec.md"),
1793
+ conversationLog: path17__default.join(baseDir, "conversation.jsonl"),
1794
+ checkpointFile: path17__default.join(baseDir, "checkpoint.json")
1788
1795
  };
1789
1796
  }
1790
1797
  var SessionPersistence = class {
@@ -1797,7 +1804,7 @@ var SessionPersistence = class {
1797
1804
  */
1798
1805
  async ensureDir() {
1799
1806
  try {
1800
- await fs15__default.mkdir(this.paths.baseDir, { recursive: true });
1807
+ await fs16__default.mkdir(this.paths.baseDir, { recursive: true });
1801
1808
  } catch {
1802
1809
  throw new FileSystemError(`Failed to create persistence directory: ${this.paths.baseDir}`, {
1803
1810
  path: this.paths.baseDir,
@@ -1812,7 +1819,7 @@ var SessionPersistence = class {
1812
1819
  await this.ensureDir();
1813
1820
  try {
1814
1821
  const data = JSON.stringify(session, null, 2);
1815
- await fs15__default.writeFile(this.paths.sessionFile, data, "utf-8");
1822
+ await fs16__default.writeFile(this.paths.sessionFile, data, "utf-8");
1816
1823
  } catch {
1817
1824
  throw new FileSystemError("Failed to save discovery session", {
1818
1825
  path: this.paths.sessionFile,
@@ -1825,7 +1832,7 @@ var SessionPersistence = class {
1825
1832
  */
1826
1833
  async loadSession() {
1827
1834
  try {
1828
- const data = await fs15__default.readFile(this.paths.sessionFile, "utf-8");
1835
+ const data = await fs16__default.readFile(this.paths.sessionFile, "utf-8");
1829
1836
  const parsed = JSON.parse(data);
1830
1837
  parsed.startedAt = new Date(parsed.startedAt);
1831
1838
  parsed.updatedAt = new Date(parsed.updatedAt);
@@ -1851,7 +1858,7 @@ var SessionPersistence = class {
1851
1858
  */
1852
1859
  async hasSession() {
1853
1860
  try {
1854
- await fs15__default.access(this.paths.sessionFile);
1861
+ await fs16__default.access(this.paths.sessionFile);
1855
1862
  return true;
1856
1863
  } catch {
1857
1864
  return false;
@@ -1862,7 +1869,7 @@ var SessionPersistence = class {
1862
1869
  */
1863
1870
  async deleteSession() {
1864
1871
  try {
1865
- await fs15__default.unlink(this.paths.sessionFile);
1872
+ await fs16__default.unlink(this.paths.sessionFile);
1866
1873
  } catch (error) {
1867
1874
  if (error.code !== "ENOENT") {
1868
1875
  throw new FileSystemError("Failed to delete discovery session", {
@@ -1878,7 +1885,7 @@ var SessionPersistence = class {
1878
1885
  async saveSpecification(content) {
1879
1886
  await this.ensureDir();
1880
1887
  try {
1881
- await fs15__default.writeFile(this.paths.specFile, content, "utf-8");
1888
+ await fs16__default.writeFile(this.paths.specFile, content, "utf-8");
1882
1889
  } catch {
1883
1890
  throw new FileSystemError("Failed to save specification", {
1884
1891
  path: this.paths.specFile,
@@ -1891,7 +1898,7 @@ var SessionPersistence = class {
1891
1898
  */
1892
1899
  async loadSpecification() {
1893
1900
  try {
1894
- return await fs15__default.readFile(this.paths.specFile, "utf-8");
1901
+ return await fs16__default.readFile(this.paths.specFile, "utf-8");
1895
1902
  } catch {
1896
1903
  return null;
1897
1904
  }
@@ -1907,7 +1914,7 @@ var SessionPersistence = class {
1907
1914
  content
1908
1915
  };
1909
1916
  try {
1910
- await fs15__default.appendFile(this.paths.conversationLog, JSON.stringify(entry) + "\n", "utf-8");
1917
+ await fs16__default.appendFile(this.paths.conversationLog, JSON.stringify(entry) + "\n", "utf-8");
1911
1918
  } catch {
1912
1919
  throw new FileSystemError("Failed to append to conversation log", {
1913
1920
  path: this.paths.conversationLog,
@@ -1920,7 +1927,7 @@ var SessionPersistence = class {
1920
1927
  */
1921
1928
  async loadConversationLog() {
1922
1929
  try {
1923
- const data = await fs15__default.readFile(this.paths.conversationLog, "utf-8");
1930
+ const data = await fs16__default.readFile(this.paths.conversationLog, "utf-8");
1924
1931
  const lines = data.trim().split("\n");
1925
1932
  return lines.filter((line) => line.trim()).map((line) => JSON.parse(line));
1926
1933
  } catch {
@@ -1934,7 +1941,7 @@ var SessionPersistence = class {
1934
1941
  await this.ensureDir();
1935
1942
  try {
1936
1943
  const data = JSON.stringify(checkpoint, null, 2);
1937
- await fs15__default.writeFile(this.paths.checkpointFile, data, "utf-8");
1944
+ await fs16__default.writeFile(this.paths.checkpointFile, data, "utf-8");
1938
1945
  } catch {
1939
1946
  throw new FileSystemError("Failed to save checkpoint", {
1940
1947
  path: this.paths.checkpointFile,
@@ -1947,7 +1954,7 @@ var SessionPersistence = class {
1947
1954
  */
1948
1955
  async loadCheckpoint() {
1949
1956
  try {
1950
- const data = await fs15__default.readFile(this.paths.checkpointFile, "utf-8");
1957
+ const data = await fs16__default.readFile(this.paths.checkpointFile, "utf-8");
1951
1958
  const parsed = JSON.parse(data);
1952
1959
  parsed.timestamp = new Date(parsed.timestamp);
1953
1960
  return parsed;
@@ -1960,7 +1967,7 @@ var SessionPersistence = class {
1960
1967
  */
1961
1968
  async clearAll() {
1962
1969
  try {
1963
- await fs15__default.rm(this.paths.baseDir, { recursive: true, force: true });
1970
+ await fs16__default.rm(this.paths.baseDir, { recursive: true, force: true });
1964
1971
  } catch (error) {
1965
1972
  if (error.code !== "ENOENT") {
1966
1973
  throw new FileSystemError("Failed to clear persistence data", {
@@ -3814,8 +3821,8 @@ var OrchestrateExecutor = class {
3814
3821
  }
3815
3822
  async loadSpecification(projectPath) {
3816
3823
  try {
3817
- const jsonPath = path16__default.join(projectPath, ".coco", "spec", "spec.json");
3818
- const jsonContent = await fs15__default.readFile(jsonPath, "utf-8");
3824
+ const jsonPath = path17__default.join(projectPath, ".coco", "spec", "spec.json");
3825
+ const jsonContent = await fs16__default.readFile(jsonPath, "utf-8");
3819
3826
  return JSON.parse(jsonContent);
3820
3827
  } catch {
3821
3828
  return this.createMinimalSpec(projectPath);
@@ -3826,7 +3833,7 @@ var OrchestrateExecutor = class {
3826
3833
  version: "1.0.0",
3827
3834
  generatedAt: /* @__PURE__ */ new Date(),
3828
3835
  overview: {
3829
- name: path16__default.basename(projectPath),
3836
+ name: path17__default.basename(projectPath),
3830
3837
  description: "Project specification",
3831
3838
  goals: [],
3832
3839
  targetUsers: ["developers"],
@@ -3853,53 +3860,53 @@ var OrchestrateExecutor = class {
3853
3860
  };
3854
3861
  }
3855
3862
  async saveArchitecture(projectPath, architecture) {
3856
- const dir = path16__default.join(projectPath, ".coco", "architecture");
3857
- await fs15__default.mkdir(dir, { recursive: true });
3858
- const mdPath = path16__default.join(dir, "ARCHITECTURE.md");
3859
- await fs15__default.writeFile(mdPath, generateArchitectureMarkdown(architecture), "utf-8");
3860
- const jsonPath = path16__default.join(dir, "architecture.json");
3861
- await fs15__default.writeFile(jsonPath, JSON.stringify(architecture, null, 2), "utf-8");
3863
+ const dir = path17__default.join(projectPath, ".coco", "architecture");
3864
+ await fs16__default.mkdir(dir, { recursive: true });
3865
+ const mdPath = path17__default.join(dir, "ARCHITECTURE.md");
3866
+ await fs16__default.writeFile(mdPath, generateArchitectureMarkdown(architecture), "utf-8");
3867
+ const jsonPath = path17__default.join(dir, "architecture.json");
3868
+ await fs16__default.writeFile(jsonPath, JSON.stringify(architecture, null, 2), "utf-8");
3862
3869
  return mdPath;
3863
3870
  }
3864
3871
  async saveADRs(projectPath, adrs) {
3865
- const dir = path16__default.join(projectPath, ".coco", "architecture", "adrs");
3866
- await fs15__default.mkdir(dir, { recursive: true });
3872
+ const dir = path17__default.join(projectPath, ".coco", "architecture", "adrs");
3873
+ await fs16__default.mkdir(dir, { recursive: true });
3867
3874
  const paths = [];
3868
- const indexPath = path16__default.join(dir, "README.md");
3869
- await fs15__default.writeFile(indexPath, generateADRIndexMarkdown(adrs), "utf-8");
3875
+ const indexPath = path17__default.join(dir, "README.md");
3876
+ await fs16__default.writeFile(indexPath, generateADRIndexMarkdown(adrs), "utf-8");
3870
3877
  paths.push(indexPath);
3871
3878
  for (const adr of adrs) {
3872
3879
  const filename = getADRFilename(adr);
3873
- const adrPath = path16__default.join(dir, filename);
3874
- await fs15__default.writeFile(adrPath, generateADRMarkdown(adr), "utf-8");
3880
+ const adrPath = path17__default.join(dir, filename);
3881
+ await fs16__default.writeFile(adrPath, generateADRMarkdown(adr), "utf-8");
3875
3882
  paths.push(adrPath);
3876
3883
  }
3877
3884
  return paths;
3878
3885
  }
3879
3886
  async saveBacklog(projectPath, backlogResult) {
3880
- const dir = path16__default.join(projectPath, ".coco", "planning");
3881
- await fs15__default.mkdir(dir, { recursive: true });
3882
- const mdPath = path16__default.join(dir, "BACKLOG.md");
3883
- await fs15__default.writeFile(mdPath, generateBacklogMarkdown(backlogResult.backlog), "utf-8");
3884
- const jsonPath = path16__default.join(dir, "backlog.json");
3885
- await fs15__default.writeFile(jsonPath, JSON.stringify(backlogResult, null, 2), "utf-8");
3887
+ const dir = path17__default.join(projectPath, ".coco", "planning");
3888
+ await fs16__default.mkdir(dir, { recursive: true });
3889
+ const mdPath = path17__default.join(dir, "BACKLOG.md");
3890
+ await fs16__default.writeFile(mdPath, generateBacklogMarkdown(backlogResult.backlog), "utf-8");
3891
+ const jsonPath = path17__default.join(dir, "backlog.json");
3892
+ await fs16__default.writeFile(jsonPath, JSON.stringify(backlogResult, null, 2), "utf-8");
3886
3893
  return mdPath;
3887
3894
  }
3888
3895
  async saveSprint(projectPath, sprint, backlogResult) {
3889
- const dir = path16__default.join(projectPath, ".coco", "planning", "sprints");
3890
- await fs15__default.mkdir(dir, { recursive: true });
3896
+ const dir = path17__default.join(projectPath, ".coco", "planning", "sprints");
3897
+ await fs16__default.mkdir(dir, { recursive: true });
3891
3898
  const filename = `${sprint.id}.md`;
3892
- const sprintPath = path16__default.join(dir, filename);
3893
- await fs15__default.writeFile(sprintPath, generateSprintMarkdown(sprint, backlogResult.backlog), "utf-8");
3894
- const jsonPath = path16__default.join(dir, `${sprint.id}.json`);
3895
- await fs15__default.writeFile(jsonPath, JSON.stringify(sprint, null, 2), "utf-8");
3899
+ const sprintPath = path17__default.join(dir, filename);
3900
+ await fs16__default.writeFile(sprintPath, generateSprintMarkdown(sprint, backlogResult.backlog), "utf-8");
3901
+ const jsonPath = path17__default.join(dir, `${sprint.id}.json`);
3902
+ await fs16__default.writeFile(jsonPath, JSON.stringify(sprint, null, 2), "utf-8");
3896
3903
  return sprintPath;
3897
3904
  }
3898
3905
  async saveDiagram(projectPath, id, mermaid) {
3899
- const dir = path16__default.join(projectPath, ".coco", "architecture", "diagrams");
3900
- await fs15__default.mkdir(dir, { recursive: true });
3901
- const diagramPath = path16__default.join(dir, `${id}.mmd`);
3902
- await fs15__default.writeFile(diagramPath, mermaid, "utf-8");
3906
+ const dir = path17__default.join(projectPath, ".coco", "architecture", "diagrams");
3907
+ await fs16__default.mkdir(dir, { recursive: true });
3908
+ const diagramPath = path17__default.join(dir, `${id}.mmd`);
3909
+ await fs16__default.writeFile(diagramPath, mermaid, "utf-8");
3903
3910
  return diagramPath;
3904
3911
  }
3905
3912
  };
@@ -4054,10 +4061,10 @@ var CoverageAnalyzer = class {
4054
4061
  join(this.projectPath, ".coverage", "coverage-summary.json"),
4055
4062
  join(this.projectPath, "coverage", "lcov-report", "coverage-summary.json")
4056
4063
  ];
4057
- for (const path39 of possiblePaths) {
4064
+ for (const path40 of possiblePaths) {
4058
4065
  try {
4059
- await access(path39, constants.R_OK);
4060
- const content = await readFile(path39, "utf-8");
4066
+ await access(path40, constants.R_OK);
4067
+ const content = await readFile(path40, "utf-8");
4061
4068
  const report = JSON.parse(content);
4062
4069
  return parseCoverageSummary(report);
4063
4070
  } catch {
@@ -4776,7 +4783,7 @@ var BuildVerifier = class {
4776
4783
  async verifyTypes() {
4777
4784
  const startTime = Date.now();
4778
4785
  try {
4779
- const hasTsConfig = await this.fileExists(path16.join(this.projectPath, "tsconfig.json"));
4786
+ const hasTsConfig = await this.fileExists(path17.join(this.projectPath, "tsconfig.json"));
4780
4787
  if (!hasTsConfig) {
4781
4788
  return {
4782
4789
  success: true,
@@ -4826,8 +4833,8 @@ var BuildVerifier = class {
4826
4833
  */
4827
4834
  async detectBuildCommand() {
4828
4835
  try {
4829
- const packageJsonPath = path16.join(this.projectPath, "package.json");
4830
- const content = await fs15.readFile(packageJsonPath, "utf-8");
4836
+ const packageJsonPath = path17.join(this.projectPath, "package.json");
4837
+ const content = await fs16.readFile(packageJsonPath, "utf-8");
4831
4838
  const packageJson = JSON.parse(content);
4832
4839
  if (packageJson.scripts?.build) {
4833
4840
  return "npm run build";
@@ -4903,7 +4910,7 @@ var BuildVerifier = class {
4903
4910
  */
4904
4911
  async fileExists(filePath) {
4905
4912
  try {
4906
- await fs15.access(filePath);
4913
+ await fs16.access(filePath);
4907
4914
  return true;
4908
4915
  } catch {
4909
4916
  return false;
@@ -6449,9 +6456,9 @@ function detectProjectLanguage(files) {
6449
6456
  return { language: dominant, confidence, evidence };
6450
6457
  }
6451
6458
  function getFileExtension(filePath) {
6452
- const base = path16.basename(filePath);
6459
+ const base = path17.basename(filePath);
6453
6460
  if (base.endsWith(".d.ts")) return ".d.ts";
6454
- return path16.extname(filePath).toLowerCase();
6461
+ return path17.extname(filePath).toLowerCase();
6455
6462
  }
6456
6463
  function buildEvidence(dominant, counts, totalSourceFiles, files) {
6457
6464
  const evidence = [];
@@ -6459,7 +6466,7 @@ function buildEvidence(dominant, counts, totalSourceFiles, files) {
6459
6466
  evidence.push(`${dominantCount} of ${totalSourceFiles} source files are ${dominant}`);
6460
6467
  const configFiles = ["tsconfig.json", "pom.xml", "build.gradle", "Cargo.toml", "go.mod"];
6461
6468
  for (const cfg of configFiles) {
6462
- if (files.some((f) => path16.basename(f) === cfg)) {
6469
+ if (files.some((f) => path17.basename(f) === cfg)) {
6463
6470
  evidence.push(`Found ${cfg}`);
6464
6471
  }
6465
6472
  }
@@ -8171,7 +8178,7 @@ function setupFileLogging(logger, logDir, name) {
8171
8178
  if (!fs4__default.existsSync(logDir)) {
8172
8179
  fs4__default.mkdirSync(logDir, { recursive: true });
8173
8180
  }
8174
- const logFile = path16__default.join(logDir, `${name}.log`);
8181
+ const logFile = path17__default.join(logDir, `${name}.log`);
8175
8182
  logger.attachTransport((logObj) => {
8176
8183
  const line = JSON.stringify(logObj) + "\n";
8177
8184
  fs4__default.appendFileSync(logFile, line);
@@ -8234,12 +8241,12 @@ function humanizeError(message, toolName) {
8234
8241
  return msg;
8235
8242
  }
8236
8243
  if (/ENOENT/i.test(msg)) {
8237
- const path39 = extractQuotedPath(msg);
8238
- return path39 ? `File or directory not found: ${path39}` : "File or directory not found";
8244
+ const path40 = extractQuotedPath(msg);
8245
+ return path40 ? `File or directory not found: ${path40}` : "File or directory not found";
8239
8246
  }
8240
8247
  if (/EACCES/i.test(msg)) {
8241
- const path39 = extractQuotedPath(msg);
8242
- return path39 ? `Permission denied: ${path39}` : "Permission denied \u2014 check file permissions";
8248
+ const path40 = extractQuotedPath(msg);
8249
+ return path40 ? `Permission denied: ${path40}` : "Permission denied \u2014 check file permissions";
8243
8250
  }
8244
8251
  if (/EISDIR/i.test(msg)) {
8245
8252
  return "Expected a file but found a directory at the specified path";
@@ -9724,14 +9731,14 @@ var CompleteExecutor = class {
9724
9731
  */
9725
9732
  async checkpoint(context) {
9726
9733
  if (this.checkpointState && this.currentSprint) {
9727
- const checkpointPath = path16__default.join(
9734
+ const checkpointPath = path17__default.join(
9728
9735
  context.projectPath,
9729
9736
  ".coco",
9730
9737
  "checkpoints",
9731
9738
  `complete-${this.currentSprint.id}.json`
9732
9739
  );
9733
- await fs15__default.mkdir(path16__default.dirname(checkpointPath), { recursive: true });
9734
- await fs15__default.writeFile(checkpointPath, JSON.stringify(this.checkpointState, null, 2), "utf-8");
9740
+ await fs16__default.mkdir(path17__default.dirname(checkpointPath), { recursive: true });
9741
+ await fs16__default.writeFile(checkpointPath, JSON.stringify(this.checkpointState, null, 2), "utf-8");
9735
9742
  }
9736
9743
  return {
9737
9744
  phase: "complete",
@@ -9751,13 +9758,13 @@ var CompleteExecutor = class {
9751
9758
  const sprintId = checkpoint.resumePoint;
9752
9759
  if (sprintId === "start") return;
9753
9760
  try {
9754
- const checkpointPath = path16__default.join(
9761
+ const checkpointPath = path17__default.join(
9755
9762
  context.projectPath,
9756
9763
  ".coco",
9757
9764
  "checkpoints",
9758
9765
  `complete-${sprintId}.json`
9759
9766
  );
9760
- const content = await fs15__default.readFile(checkpointPath, "utf-8");
9767
+ const content = await fs16__default.readFile(checkpointPath, "utf-8");
9761
9768
  this.checkpointState = JSON.parse(content);
9762
9769
  this.completedTaskIds = new Set(this.checkpointState.completedTaskIds);
9763
9770
  } catch {
@@ -10004,14 +10011,14 @@ var CompleteExecutor = class {
10004
10011
  };
10005
10012
  const saveFiles = async (files) => {
10006
10013
  for (const file of files) {
10007
- const filePath = path16__default.join(context.projectPath, file.path);
10008
- const dir = path16__default.dirname(filePath);
10009
- await fs15__default.mkdir(dir, { recursive: true });
10014
+ const filePath = path17__default.join(context.projectPath, file.path);
10015
+ const dir = path17__default.dirname(filePath);
10016
+ await fs16__default.mkdir(dir, { recursive: true });
10010
10017
  if (file.action === "delete") {
10011
- await fs15__default.unlink(filePath).catch(() => {
10018
+ await fs16__default.unlink(filePath).catch(() => {
10012
10019
  });
10013
10020
  } else {
10014
- await fs15__default.writeFile(filePath, file.content, "utf-8");
10021
+ await fs16__default.writeFile(filePath, file.content, "utf-8");
10015
10022
  }
10016
10023
  }
10017
10024
  };
@@ -10137,8 +10144,8 @@ var CompleteExecutor = class {
10137
10144
  */
10138
10145
  async loadBacklog(projectPath) {
10139
10146
  try {
10140
- const backlogPath = path16__default.join(projectPath, ".coco", "planning", "backlog.json");
10141
- const content = await fs15__default.readFile(backlogPath, "utf-8");
10147
+ const backlogPath = path17__default.join(projectPath, ".coco", "planning", "backlog.json");
10148
+ const content = await fs16__default.readFile(backlogPath, "utf-8");
10142
10149
  const data = JSON.parse(content);
10143
10150
  return data.backlog;
10144
10151
  } catch {
@@ -10150,12 +10157,12 @@ var CompleteExecutor = class {
10150
10157
  */
10151
10158
  async loadCurrentSprint(projectPath) {
10152
10159
  try {
10153
- const sprintsDir = path16__default.join(projectPath, ".coco", "planning", "sprints");
10154
- const files = await fs15__default.readdir(sprintsDir);
10160
+ const sprintsDir = path17__default.join(projectPath, ".coco", "planning", "sprints");
10161
+ const files = await fs16__default.readdir(sprintsDir);
10155
10162
  const jsonFiles = files.filter((f) => f.endsWith(".json"));
10156
10163
  if (jsonFiles.length === 0) return null;
10157
- const sprintPath = path16__default.join(sprintsDir, jsonFiles[0] || "");
10158
- const content = await fs15__default.readFile(sprintPath, "utf-8");
10164
+ const sprintPath = path17__default.join(sprintsDir, jsonFiles[0] || "");
10165
+ const content = await fs16__default.readFile(sprintPath, "utf-8");
10159
10166
  const sprint = JSON.parse(content);
10160
10167
  sprint.startDate = new Date(sprint.startDate);
10161
10168
  return sprint;
@@ -10167,12 +10174,12 @@ var CompleteExecutor = class {
10167
10174
  * Save sprint results
10168
10175
  */
10169
10176
  async saveSprintResults(projectPath, result) {
10170
- const resultsDir = path16__default.join(projectPath, ".coco", "results");
10171
- await fs15__default.mkdir(resultsDir, { recursive: true });
10172
- const resultsPath = path16__default.join(resultsDir, `${result.sprintId}-results.json`);
10173
- await fs15__default.writeFile(resultsPath, JSON.stringify(result, null, 2), "utf-8");
10174
- const mdPath = path16__default.join(resultsDir, `${result.sprintId}-results.md`);
10175
- await fs15__default.writeFile(mdPath, this.generateResultsMarkdown(result), "utf-8");
10177
+ const resultsDir = path17__default.join(projectPath, ".coco", "results");
10178
+ await fs16__default.mkdir(resultsDir, { recursive: true });
10179
+ const resultsPath = path17__default.join(resultsDir, `${result.sprintId}-results.json`);
10180
+ await fs16__default.writeFile(resultsPath, JSON.stringify(result, null, 2), "utf-8");
10181
+ const mdPath = path17__default.join(resultsDir, `${result.sprintId}-results.md`);
10182
+ await fs16__default.writeFile(mdPath, this.generateResultsMarkdown(result), "utf-8");
10176
10183
  return resultsPath;
10177
10184
  }
10178
10185
  /**
@@ -11396,9 +11403,9 @@ var OutputExecutor = class {
11396
11403
  const cicdGenerator = new CICDGenerator(metadata, cicdConfig);
11397
11404
  const cicdFiles = cicdGenerator.generate();
11398
11405
  for (const file of cicdFiles) {
11399
- const filePath = path16__default.join(context.projectPath, file.path);
11400
- await this.ensureDir(path16__default.dirname(filePath));
11401
- await fs15__default.writeFile(filePath, file.content, "utf-8");
11406
+ const filePath = path17__default.join(context.projectPath, file.path);
11407
+ await this.ensureDir(path17__default.dirname(filePath));
11408
+ await fs16__default.writeFile(filePath, file.content, "utf-8");
11402
11409
  artifacts.push({
11403
11410
  type: "cicd",
11404
11411
  path: filePath,
@@ -11408,16 +11415,16 @@ var OutputExecutor = class {
11408
11415
  if (this.config.docker.enabled) {
11409
11416
  const dockerGenerator = new DockerGenerator(metadata);
11410
11417
  const dockerfile2 = dockerGenerator.generateDockerfile();
11411
- const dockerfilePath = path16__default.join(context.projectPath, "Dockerfile");
11412
- await fs15__default.writeFile(dockerfilePath, dockerfile2, "utf-8");
11418
+ const dockerfilePath = path17__default.join(context.projectPath, "Dockerfile");
11419
+ await fs16__default.writeFile(dockerfilePath, dockerfile2, "utf-8");
11413
11420
  artifacts.push({
11414
11421
  type: "deployment",
11415
11422
  path: dockerfilePath,
11416
11423
  description: "Dockerfile"
11417
11424
  });
11418
11425
  const dockerignore = dockerGenerator.generateDockerignore();
11419
- const dockerignorePath = path16__default.join(context.projectPath, ".dockerignore");
11420
- await fs15__default.writeFile(dockerignorePath, dockerignore, "utf-8");
11426
+ const dockerignorePath = path17__default.join(context.projectPath, ".dockerignore");
11427
+ await fs16__default.writeFile(dockerignorePath, dockerignore, "utf-8");
11421
11428
  artifacts.push({
11422
11429
  type: "deployment",
11423
11430
  path: dockerignorePath,
@@ -11425,8 +11432,8 @@ var OutputExecutor = class {
11425
11432
  });
11426
11433
  if (this.config.docker.compose) {
11427
11434
  const compose = dockerGenerator.generateDockerCompose();
11428
- const composePath = path16__default.join(context.projectPath, "docker-compose.yml");
11429
- await fs15__default.writeFile(composePath, compose, "utf-8");
11435
+ const composePath = path17__default.join(context.projectPath, "docker-compose.yml");
11436
+ await fs16__default.writeFile(composePath, compose, "utf-8");
11430
11437
  artifacts.push({
11431
11438
  type: "deployment",
11432
11439
  path: composePath,
@@ -11437,8 +11444,8 @@ var OutputExecutor = class {
11437
11444
  const docsGenerator = new DocsGenerator(metadata);
11438
11445
  const docs = docsGenerator.generate();
11439
11446
  if (this.config.docs.readme) {
11440
- const readmePath = path16__default.join(context.projectPath, "README.md");
11441
- await fs15__default.writeFile(readmePath, docs.readme, "utf-8");
11447
+ const readmePath = path17__default.join(context.projectPath, "README.md");
11448
+ await fs16__default.writeFile(readmePath, docs.readme, "utf-8");
11442
11449
  artifacts.push({
11443
11450
  type: "documentation",
11444
11451
  path: readmePath,
@@ -11446,8 +11453,8 @@ var OutputExecutor = class {
11446
11453
  });
11447
11454
  }
11448
11455
  if (this.config.docs.contributing) {
11449
- const contributingPath = path16__default.join(context.projectPath, "CONTRIBUTING.md");
11450
- await fs15__default.writeFile(contributingPath, docs.contributing, "utf-8");
11456
+ const contributingPath = path17__default.join(context.projectPath, "CONTRIBUTING.md");
11457
+ await fs16__default.writeFile(contributingPath, docs.contributing, "utf-8");
11451
11458
  artifacts.push({
11452
11459
  type: "documentation",
11453
11460
  path: contributingPath,
@@ -11455,8 +11462,8 @@ var OutputExecutor = class {
11455
11462
  });
11456
11463
  }
11457
11464
  if (this.config.docs.changelog) {
11458
- const changelogPath = path16__default.join(context.projectPath, "CHANGELOG.md");
11459
- await fs15__default.writeFile(changelogPath, docs.changelog, "utf-8");
11465
+ const changelogPath = path17__default.join(context.projectPath, "CHANGELOG.md");
11466
+ await fs16__default.writeFile(changelogPath, docs.changelog, "utf-8");
11460
11467
  artifacts.push({
11461
11468
  type: "documentation",
11462
11469
  path: changelogPath,
@@ -11464,11 +11471,11 @@ var OutputExecutor = class {
11464
11471
  });
11465
11472
  }
11466
11473
  if (this.config.docs.api) {
11467
- const docsDir = path16__default.join(context.projectPath, "docs");
11474
+ const docsDir = path17__default.join(context.projectPath, "docs");
11468
11475
  await this.ensureDir(docsDir);
11469
11476
  if (docs.api) {
11470
- const apiPath = path16__default.join(docsDir, "api.md");
11471
- await fs15__default.writeFile(apiPath, docs.api, "utf-8");
11477
+ const apiPath = path17__default.join(docsDir, "api.md");
11478
+ await fs16__default.writeFile(apiPath, docs.api, "utf-8");
11472
11479
  artifacts.push({
11473
11480
  type: "documentation",
11474
11481
  path: apiPath,
@@ -11476,8 +11483,8 @@ var OutputExecutor = class {
11476
11483
  });
11477
11484
  }
11478
11485
  if (docs.deployment) {
11479
- const deployPath = path16__default.join(docsDir, "deployment.md");
11480
- await fs15__default.writeFile(deployPath, docs.deployment, "utf-8");
11486
+ const deployPath = path17__default.join(docsDir, "deployment.md");
11487
+ await fs16__default.writeFile(deployPath, docs.deployment, "utf-8");
11481
11488
  artifacts.push({
11482
11489
  type: "documentation",
11483
11490
  path: deployPath,
@@ -11485,8 +11492,8 @@ var OutputExecutor = class {
11485
11492
  });
11486
11493
  }
11487
11494
  if (docs.development) {
11488
- const devPath = path16__default.join(docsDir, "development.md");
11489
- await fs15__default.writeFile(devPath, docs.development, "utf-8");
11495
+ const devPath = path17__default.join(docsDir, "development.md");
11496
+ await fs16__default.writeFile(devPath, docs.development, "utf-8");
11490
11497
  artifacts.push({
11491
11498
  type: "documentation",
11492
11499
  path: devPath,
@@ -11551,16 +11558,16 @@ var OutputExecutor = class {
11551
11558
  */
11552
11559
  async loadMetadata(projectPath) {
11553
11560
  try {
11554
- const packagePath = path16__default.join(projectPath, "package.json");
11555
- const content = await fs15__default.readFile(packagePath, "utf-8");
11561
+ const packagePath = path17__default.join(projectPath, "package.json");
11562
+ const content = await fs16__default.readFile(packagePath, "utf-8");
11556
11563
  const pkg = JSON.parse(content);
11557
11564
  let packageManager = "npm";
11558
11565
  try {
11559
- await fs15__default.access(path16__default.join(projectPath, "pnpm-lock.yaml"));
11566
+ await fs16__default.access(path17__default.join(projectPath, "pnpm-lock.yaml"));
11560
11567
  packageManager = "pnpm";
11561
11568
  } catch {
11562
11569
  try {
11563
- await fs15__default.access(path16__default.join(projectPath, "yarn.lock"));
11570
+ await fs16__default.access(path17__default.join(projectPath, "yarn.lock"));
11564
11571
  packageManager = "yarn";
11565
11572
  } catch {
11566
11573
  }
@@ -11572,7 +11579,7 @@ var OutputExecutor = class {
11572
11579
  repository = pkg.repository.url;
11573
11580
  }
11574
11581
  return {
11575
- name: pkg.name || path16__default.basename(projectPath),
11582
+ name: pkg.name || path17__default.basename(projectPath),
11576
11583
  description: pkg.description || "",
11577
11584
  version: pkg.version || "0.1.0",
11578
11585
  language: "typescript",
@@ -11586,7 +11593,7 @@ var OutputExecutor = class {
11586
11593
  };
11587
11594
  } catch {
11588
11595
  return {
11589
- name: path16__default.basename(projectPath),
11596
+ name: path17__default.basename(projectPath),
11590
11597
  description: "",
11591
11598
  version: "0.1.0",
11592
11599
  language: "typescript",
@@ -11602,7 +11609,7 @@ var OutputExecutor = class {
11602
11609
  * Ensure directory exists
11603
11610
  */
11604
11611
  async ensureDir(dir) {
11605
- await fs15__default.mkdir(dir, { recursive: true });
11612
+ await fs16__default.mkdir(dir, { recursive: true });
11606
11613
  }
11607
11614
  };
11608
11615
  function createOutputExecutor(config) {
@@ -11664,18 +11671,19 @@ async function withRetry(fn, config = {}) {
11664
11671
  }
11665
11672
 
11666
11673
  // src/providers/anthropic.ts
11667
- var DEFAULT_MODEL = "claude-opus-4-6-20260115";
11674
+ var DEFAULT_MODEL = "claude-opus-4-6";
11668
11675
  var CONTEXT_WINDOWS = {
11669
11676
  // Kimi Code model (Anthropic-compatible endpoint)
11670
11677
  "kimi-for-coding": 131072,
11671
- // Claude 4.6 (latest, Jan 2026) - 200K-1M context, 128K output
11672
- "claude-opus-4-6-20260115": 2e5,
11673
- // Claude 4.5 models (Nov 2025)
11674
- "claude-opus-4-5-20251124": 2e5,
11678
+ // Claude 4.6 (latest) 200K standard, 1M beta
11679
+ "claude-opus-4-6": 2e5,
11680
+ "claude-sonnet-4-6": 2e5,
11681
+ // Claude 4.5 models
11682
+ "claude-opus-4-5-20251101": 2e5,
11675
11683
  "claude-sonnet-4-5-20250929": 2e5,
11676
11684
  "claude-haiku-4-5-20251001": 2e5,
11677
11685
  // Claude 4.1 models
11678
- "claude-opus-4-1-20250801": 2e5,
11686
+ "claude-opus-4-1-20250805": 2e5,
11679
11687
  // Claude 4 models
11680
11688
  "claude-sonnet-4-20250514": 2e5,
11681
11689
  "claude-opus-4-20250514": 2e5,
@@ -12985,18 +12993,18 @@ async function refreshAccessToken(provider, refreshToken) {
12985
12993
  }
12986
12994
  function getTokenStoragePath(provider) {
12987
12995
  const home = process.env.HOME || process.env.USERPROFILE || "";
12988
- return path16.join(home, ".coco", "tokens", `${provider}.json`);
12996
+ return path17.join(home, ".coco", "tokens", `${provider}.json`);
12989
12997
  }
12990
12998
  async function saveTokens(provider, tokens) {
12991
12999
  const filePath = getTokenStoragePath(provider);
12992
- const dir = path16.dirname(filePath);
12993
- await fs15.mkdir(dir, { recursive: true, mode: 448 });
12994
- await fs15.writeFile(filePath, JSON.stringify(tokens, null, 2), { mode: 384 });
13000
+ const dir = path17.dirname(filePath);
13001
+ await fs16.mkdir(dir, { recursive: true, mode: 448 });
13002
+ await fs16.writeFile(filePath, JSON.stringify(tokens, null, 2), { mode: 384 });
12995
13003
  }
12996
13004
  async function loadTokens(provider) {
12997
13005
  const filePath = getTokenStoragePath(provider);
12998
13006
  try {
12999
- const content = await fs15.readFile(filePath, "utf-8");
13007
+ const content = await fs16.readFile(filePath, "utf-8");
13000
13008
  return JSON.parse(content);
13001
13009
  } catch {
13002
13010
  return null;
@@ -13005,7 +13013,7 @@ async function loadTokens(provider) {
13005
13013
  async function deleteTokens(provider) {
13006
13014
  const filePath = getTokenStoragePath(provider);
13007
13015
  try {
13008
- await fs15.unlink(filePath);
13016
+ await fs16.unlink(filePath);
13009
13017
  } catch {
13010
13018
  }
13011
13019
  }
@@ -13043,6 +13051,124 @@ function detectWSL() {
13043
13051
  }
13044
13052
  }
13045
13053
  var isWSL = detectWSL();
13054
+ var COPILOT_TOKEN_URL = "https://api.github.com/copilot_internal/v2/token";
13055
+ var COPILOT_BASE_URLS = {
13056
+ individual: "https://api.githubcopilot.com",
13057
+ business: "https://api.business.githubcopilot.com",
13058
+ enterprise: "https://api.enterprise.githubcopilot.com"
13059
+ };
13060
+ var DEFAULT_COPILOT_BASE_URL = "https://api.githubcopilot.com";
13061
+ var REFRESH_BUFFER_MS = 6e4;
13062
+ var CopilotAuthError = class extends Error {
13063
+ constructor(message, permanent) {
13064
+ super(message);
13065
+ this.permanent = permanent;
13066
+ this.name = "CopilotAuthError";
13067
+ }
13068
+ };
13069
+ async function exchangeForCopilotToken(githubToken) {
13070
+ const response = await fetch(COPILOT_TOKEN_URL, {
13071
+ method: "GET",
13072
+ headers: {
13073
+ Authorization: `token ${githubToken}`,
13074
+ Accept: "application/json",
13075
+ "User-Agent": "Corbat-Coco/1.0"
13076
+ }
13077
+ });
13078
+ if (!response.ok) {
13079
+ const error = await response.text();
13080
+ if (response.status === 401) {
13081
+ throw new CopilotAuthError(
13082
+ "GitHub token is invalid or expired. Please re-authenticate with /provider copilot.",
13083
+ true
13084
+ );
13085
+ }
13086
+ if (response.status === 403) {
13087
+ throw new CopilotAuthError(
13088
+ "GitHub Copilot is not enabled for this account.\n Please ensure you have an active Copilot subscription:\n https://github.com/settings/copilot",
13089
+ true
13090
+ );
13091
+ }
13092
+ throw new Error(`Copilot token exchange failed: ${response.status} - ${error}`);
13093
+ }
13094
+ return await response.json();
13095
+ }
13096
+ function getCopilotBaseUrl(accountType) {
13097
+ if (accountType && accountType in COPILOT_BASE_URLS) {
13098
+ return COPILOT_BASE_URLS[accountType];
13099
+ }
13100
+ return DEFAULT_COPILOT_BASE_URL;
13101
+ }
13102
+ function getCopilotCredentialsPath() {
13103
+ const home = process.env.HOME || process.env.USERPROFILE || "";
13104
+ return path17.join(home, ".coco", "tokens", "copilot.json");
13105
+ }
13106
+ async function saveCopilotCredentials(creds) {
13107
+ const filePath = getCopilotCredentialsPath();
13108
+ const dir = path17.dirname(filePath);
13109
+ await fs16.mkdir(dir, { recursive: true, mode: 448 });
13110
+ await fs16.writeFile(filePath, JSON.stringify(creds, null, 2), { mode: 384 });
13111
+ }
13112
+ var CopilotCredentialsSchema = z.object({
13113
+ githubToken: z.string().min(1),
13114
+ copilotToken: z.string().optional(),
13115
+ copilotTokenExpiresAt: z.number().optional(),
13116
+ accountType: z.string().optional()
13117
+ });
13118
+ async function loadCopilotCredentials() {
13119
+ try {
13120
+ const content = await fs16.readFile(getCopilotCredentialsPath(), "utf-8");
13121
+ const parsed = CopilotCredentialsSchema.safeParse(JSON.parse(content));
13122
+ return parsed.success ? parsed.data : null;
13123
+ } catch {
13124
+ return null;
13125
+ }
13126
+ }
13127
+ async function deleteCopilotCredentials() {
13128
+ try {
13129
+ await fs16.unlink(getCopilotCredentialsPath());
13130
+ } catch {
13131
+ }
13132
+ }
13133
+ function isCopilotTokenExpired(creds) {
13134
+ if (!creds.copilotToken || !creds.copilotTokenExpiresAt) return true;
13135
+ return Date.now() >= creds.copilotTokenExpiresAt - REFRESH_BUFFER_MS;
13136
+ }
13137
+ async function getValidCopilotToken() {
13138
+ const creds = await loadCopilotCredentials();
13139
+ if (!creds) return null;
13140
+ const envToken = process.env["GITHUB_TOKEN"] || process.env["GH_TOKEN"];
13141
+ const githubToken = envToken || creds.githubToken;
13142
+ if (!isCopilotTokenExpired(creds) && creds.copilotToken) {
13143
+ return {
13144
+ token: creds.copilotToken,
13145
+ baseUrl: getCopilotBaseUrl(creds.accountType),
13146
+ isNew: false
13147
+ };
13148
+ }
13149
+ try {
13150
+ const copilotToken = await exchangeForCopilotToken(githubToken);
13151
+ const updatedCreds = {
13152
+ ...creds,
13153
+ githubToken: creds.githubToken,
13154
+ copilotToken: copilotToken.token,
13155
+ copilotTokenExpiresAt: copilotToken.expires_at * 1e3,
13156
+ accountType: copilotToken.annotations?.copilot_plan ?? creds.accountType
13157
+ };
13158
+ await saveCopilotCredentials(updatedCreds);
13159
+ return {
13160
+ token: copilotToken.token,
13161
+ baseUrl: getCopilotBaseUrl(updatedCreds.accountType),
13162
+ isNew: true
13163
+ };
13164
+ } catch (error) {
13165
+ if (error instanceof CopilotAuthError && error.permanent) {
13166
+ await deleteCopilotCredentials();
13167
+ return null;
13168
+ }
13169
+ throw error;
13170
+ }
13171
+ }
13046
13172
 
13047
13173
  // src/auth/flow.ts
13048
13174
  promisify(execFile);
@@ -13355,22 +13481,496 @@ var CodexProvider = class {
13355
13481
  yield* this.stream(messages, options);
13356
13482
  }
13357
13483
  };
13358
- var DEFAULT_MODEL4 = "gemini-3-flash-preview";
13359
13484
  var CONTEXT_WINDOWS4 = {
13360
- // Gemini 3 series (latest, Jan 2026 - use -preview suffix)
13485
+ // Claude models
13486
+ "claude-sonnet-4.6": 2e5,
13487
+ "claude-opus-4.6": 2e5,
13488
+ "claude-sonnet-4.5": 2e5,
13489
+ "claude-opus-4.5": 2e5,
13490
+ "claude-haiku-4.5": 2e5,
13491
+ // OpenAI models — chat/completions
13492
+ "gpt-4.1": 1048576,
13493
+ // OpenAI models — /responses API (Codex/GPT-5+)
13494
+ "gpt-5.3-codex": 4e5,
13495
+ "gpt-5.2-codex": 4e5,
13496
+ "gpt-5.1-codex-max": 4e5,
13497
+ "gpt-5.2": 4e5,
13498
+ "gpt-5.1": 4e5,
13499
+ // Google models
13500
+ "gemini-3.1-pro-preview": 1e6,
13501
+ "gemini-3-flash-preview": 1e6,
13502
+ "gemini-2.5-pro": 1048576
13503
+ };
13504
+ var DEFAULT_MODEL4 = "claude-sonnet-4.6";
13505
+ var COPILOT_HEADERS = {
13506
+ "Copilot-Integration-Id": "vscode-chat",
13507
+ "Editor-Version": "vscode/1.99.0",
13508
+ "Editor-Plugin-Version": "copilot-chat/0.26.7",
13509
+ "X-GitHub-Api-Version": "2025-04-01"
13510
+ };
13511
+ function needsResponsesApi(model) {
13512
+ return model.includes("codex") || model.startsWith("gpt-5") || model.startsWith("o4-") || model.startsWith("o3-");
13513
+ }
13514
+ var CopilotProvider = class extends OpenAIProvider {
13515
+ baseUrl = "https://api.githubcopilot.com";
13516
+ currentToken = null;
13517
+ /** In-flight refresh promise to prevent concurrent token exchanges */
13518
+ refreshPromise = null;
13519
+ constructor() {
13520
+ super("copilot", "GitHub Copilot");
13521
+ }
13522
+ /**
13523
+ * Initialize the provider with Copilot credentials.
13524
+ *
13525
+ * Gets a valid Copilot API token (from cache or by refreshing),
13526
+ * then creates an OpenAI client configured for the Copilot endpoint.
13527
+ */
13528
+ async initialize(config) {
13529
+ this.config = {
13530
+ ...config,
13531
+ model: config.model ?? DEFAULT_MODEL4
13532
+ };
13533
+ const tokenResult = await getValidCopilotToken();
13534
+ if (tokenResult) {
13535
+ this.currentToken = tokenResult.token;
13536
+ this.baseUrl = tokenResult.baseUrl;
13537
+ } else if (config.apiKey) {
13538
+ this.currentToken = config.apiKey;
13539
+ }
13540
+ if (!this.currentToken) {
13541
+ throw new ProviderError(
13542
+ "No Copilot token found. Please authenticate with: coco --provider copilot",
13543
+ { provider: this.id }
13544
+ );
13545
+ }
13546
+ this.createCopilotClient();
13547
+ }
13548
+ /**
13549
+ * Create the OpenAI client configured for Copilot API
13550
+ */
13551
+ createCopilotClient() {
13552
+ this.client = new OpenAI({
13553
+ apiKey: this.currentToken,
13554
+ baseURL: this.config.baseUrl ?? this.baseUrl,
13555
+ timeout: this.config.timeout ?? 12e4,
13556
+ defaultHeaders: COPILOT_HEADERS
13557
+ });
13558
+ }
13559
+ /**
13560
+ * Refresh the Copilot token if expired.
13561
+ *
13562
+ * Uses a mutex so concurrent callers share a single in-flight token
13563
+ * exchange. The slot is cleared inside the IIFE's finally block,
13564
+ * which runs after all awaiting callers have resumed.
13565
+ */
13566
+ async refreshTokenIfNeeded() {
13567
+ if (!this.refreshPromise) {
13568
+ this.refreshPromise = (async () => {
13569
+ try {
13570
+ const tokenResult = await getValidCopilotToken();
13571
+ if (tokenResult && tokenResult.isNew) {
13572
+ this.currentToken = tokenResult.token;
13573
+ this.baseUrl = tokenResult.baseUrl;
13574
+ this.createCopilotClient();
13575
+ }
13576
+ } finally {
13577
+ this.refreshPromise = null;
13578
+ }
13579
+ })();
13580
+ }
13581
+ await this.refreshPromise;
13582
+ }
13583
+ // --- Override public methods to add token refresh + Responses API routing ---
13584
+ async chat(messages, options) {
13585
+ await this.refreshTokenIfNeeded();
13586
+ const model = options?.model ?? this.config.model ?? DEFAULT_MODEL4;
13587
+ if (needsResponsesApi(model)) {
13588
+ return this.chatViaResponses(messages, options);
13589
+ }
13590
+ return super.chat(messages, options);
13591
+ }
13592
+ async chatWithTools(messages, options) {
13593
+ await this.refreshTokenIfNeeded();
13594
+ const model = options?.model ?? this.config.model ?? DEFAULT_MODEL4;
13595
+ if (needsResponsesApi(model)) {
13596
+ return this.chatWithToolsViaResponses(messages, options);
13597
+ }
13598
+ return super.chatWithTools(messages, options);
13599
+ }
13600
+ // Note: Token is refreshed before the stream starts but NOT mid-stream.
13601
+ // Copilot tokens last ~25 min. Very long streams may get a 401 mid-stream
13602
+ // which surfaces as a ProviderError. The retry layer handles re-attempts.
13603
+ async *stream(messages, options) {
13604
+ await this.refreshTokenIfNeeded();
13605
+ const model = options?.model ?? this.config.model ?? DEFAULT_MODEL4;
13606
+ if (needsResponsesApi(model)) {
13607
+ yield* this.streamViaResponses(messages, options);
13608
+ return;
13609
+ }
13610
+ yield* super.stream(messages, options);
13611
+ }
13612
+ async *streamWithTools(messages, options) {
13613
+ await this.refreshTokenIfNeeded();
13614
+ const model = options?.model ?? this.config.model ?? DEFAULT_MODEL4;
13615
+ if (needsResponsesApi(model)) {
13616
+ yield* this.streamWithToolsViaResponses(messages, options);
13617
+ return;
13618
+ }
13619
+ yield* super.streamWithTools(messages, options);
13620
+ }
13621
+ // --- Responses API implementations ---
13622
+ /**
13623
+ * Simple chat via Responses API (no tools)
13624
+ */
13625
+ async chatViaResponses(messages, options) {
13626
+ this.ensureInitialized();
13627
+ return withRetry(async () => {
13628
+ try {
13629
+ const model = options?.model ?? this.config.model ?? DEFAULT_MODEL4;
13630
+ const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
13631
+ const response = await this.client.responses.create({
13632
+ model,
13633
+ input,
13634
+ instructions: instructions ?? void 0,
13635
+ max_output_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
13636
+ temperature: options?.temperature ?? this.config.temperature ?? 0,
13637
+ store: false
13638
+ });
13639
+ return {
13640
+ id: response.id,
13641
+ content: response.output_text ?? "",
13642
+ stopReason: response.status === "completed" ? "end_turn" : "max_tokens",
13643
+ usage: {
13644
+ inputTokens: response.usage?.input_tokens ?? 0,
13645
+ outputTokens: response.usage?.output_tokens ?? 0
13646
+ },
13647
+ model: String(response.model)
13648
+ };
13649
+ } catch (error) {
13650
+ throw this.handleError(error);
13651
+ }
13652
+ }, DEFAULT_RETRY_CONFIG);
13653
+ }
13654
+ /**
13655
+ * Chat with tools via Responses API
13656
+ */
13657
+ async chatWithToolsViaResponses(messages, options) {
13658
+ this.ensureInitialized();
13659
+ return withRetry(async () => {
13660
+ try {
13661
+ const model = options?.model ?? this.config.model ?? DEFAULT_MODEL4;
13662
+ const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
13663
+ const tools = this.convertToolsForResponses(options.tools);
13664
+ const response = await this.client.responses.create({
13665
+ model,
13666
+ input,
13667
+ instructions: instructions ?? void 0,
13668
+ tools,
13669
+ max_output_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
13670
+ temperature: options?.temperature ?? this.config.temperature ?? 0,
13671
+ store: false
13672
+ });
13673
+ let content = "";
13674
+ const toolCalls = [];
13675
+ for (const item of response.output) {
13676
+ if (item.type === "message") {
13677
+ for (const part of item.content) {
13678
+ if (part.type === "output_text") {
13679
+ content += part.text;
13680
+ }
13681
+ }
13682
+ } else if (item.type === "function_call") {
13683
+ toolCalls.push({
13684
+ id: item.call_id,
13685
+ name: item.name,
13686
+ input: this.parseToolArguments(item.arguments)
13687
+ });
13688
+ }
13689
+ }
13690
+ return {
13691
+ id: response.id,
13692
+ content,
13693
+ stopReason: response.status === "completed" ? "end_turn" : "tool_use",
13694
+ usage: {
13695
+ inputTokens: response.usage?.input_tokens ?? 0,
13696
+ outputTokens: response.usage?.output_tokens ?? 0
13697
+ },
13698
+ model: String(response.model),
13699
+ toolCalls
13700
+ };
13701
+ } catch (error) {
13702
+ throw this.handleError(error);
13703
+ }
13704
+ }, DEFAULT_RETRY_CONFIG);
13705
+ }
13706
+ /**
13707
+ * Stream via Responses API (no tools)
13708
+ */
13709
+ async *streamViaResponses(messages, options) {
13710
+ this.ensureInitialized();
13711
+ try {
13712
+ const model = options?.model ?? this.config.model ?? DEFAULT_MODEL4;
13713
+ const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
13714
+ const stream = await this.client.responses.create({
13715
+ model,
13716
+ input,
13717
+ instructions: instructions ?? void 0,
13718
+ max_output_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
13719
+ temperature: options?.temperature ?? this.config.temperature ?? 0,
13720
+ store: false,
13721
+ stream: true
13722
+ });
13723
+ for await (const event of stream) {
13724
+ if (event.type === "response.output_text.delta") {
13725
+ yield { type: "text", text: event.delta };
13726
+ } else if (event.type === "response.completed") {
13727
+ yield { type: "done", stopReason: "end_turn" };
13728
+ }
13729
+ }
13730
+ } catch (error) {
13731
+ throw this.handleError(error);
13732
+ }
13733
+ }
13734
+ /**
13735
+ * Stream with tools via Responses API
13736
+ */
13737
+ async *streamWithToolsViaResponses(messages, options) {
13738
+ this.ensureInitialized();
13739
+ try {
13740
+ const model = options?.model ?? this.config.model ?? DEFAULT_MODEL4;
13741
+ const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
13742
+ const tools = this.convertToolsForResponses(options.tools);
13743
+ const stream = await this.client.responses.create({
13744
+ model,
13745
+ input,
13746
+ instructions: instructions ?? void 0,
13747
+ tools,
13748
+ max_output_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
13749
+ temperature: options?.temperature ?? this.config.temperature ?? 0,
13750
+ store: false,
13751
+ stream: true
13752
+ });
13753
+ const fnCallBuilders = /* @__PURE__ */ new Map();
13754
+ for await (const event of stream) {
13755
+ switch (event.type) {
13756
+ case "response.output_text.delta":
13757
+ yield { type: "text", text: event.delta };
13758
+ break;
13759
+ case "response.output_item.added":
13760
+ if (event.item.type === "function_call") {
13761
+ const fc = event.item;
13762
+ fnCallBuilders.set(fc.call_id, {
13763
+ callId: fc.call_id,
13764
+ name: fc.name,
13765
+ arguments: ""
13766
+ });
13767
+ yield {
13768
+ type: "tool_use_start",
13769
+ toolCall: { id: fc.call_id, name: fc.name }
13770
+ };
13771
+ }
13772
+ break;
13773
+ case "response.function_call_arguments.delta":
13774
+ {
13775
+ const builder = fnCallBuilders.get(event.item_id);
13776
+ if (builder) {
13777
+ builder.arguments += event.delta;
13778
+ }
13779
+ }
13780
+ break;
13781
+ case "response.function_call_arguments.done":
13782
+ {
13783
+ const builder = fnCallBuilders.get(event.item_id);
13784
+ if (builder) {
13785
+ yield {
13786
+ type: "tool_use_end",
13787
+ toolCall: {
13788
+ id: builder.callId,
13789
+ name: builder.name,
13790
+ input: this.parseToolArguments(event.arguments)
13791
+ }
13792
+ };
13793
+ fnCallBuilders.delete(event.item_id);
13794
+ }
13795
+ }
13796
+ break;
13797
+ case "response.completed":
13798
+ {
13799
+ for (const [, builder] of fnCallBuilders) {
13800
+ yield {
13801
+ type: "tool_use_end",
13802
+ toolCall: {
13803
+ id: builder.callId,
13804
+ name: builder.name,
13805
+ input: this.parseToolArguments(builder.arguments)
13806
+ }
13807
+ };
13808
+ }
13809
+ fnCallBuilders.clear();
13810
+ const hasToolCalls = event.response.output.some((i) => i.type === "function_call");
13811
+ yield {
13812
+ type: "done",
13813
+ stopReason: hasToolCalls ? "tool_use" : "end_turn"
13814
+ };
13815
+ }
13816
+ break;
13817
+ }
13818
+ }
13819
+ } catch (error) {
13820
+ throw this.handleError(error);
13821
+ }
13822
+ }
13823
+ // --- Responses API helpers ---
13824
+ /**
13825
+ * Convert our internal messages to Responses API input format.
13826
+ *
13827
+ * The Responses API uses a flat array of input items (EasyInputMessage,
13828
+ * function_call, function_call_output) instead of the chat completions
13829
+ * messages array.
13830
+ */
13831
+ convertToResponsesInput(messages, systemPrompt) {
13832
+ const input = [];
13833
+ let instructions = null;
13834
+ if (systemPrompt) {
13835
+ instructions = systemPrompt;
13836
+ }
13837
+ for (const msg of messages) {
13838
+ if (msg.role === "system") {
13839
+ instructions = (instructions ? instructions + "\n\n" : "") + this.contentToStr(msg.content);
13840
+ } else if (msg.role === "user") {
13841
+ if (Array.isArray(msg.content) && msg.content.some((b) => b.type === "tool_result")) {
13842
+ for (const block of msg.content) {
13843
+ if (block.type === "tool_result") {
13844
+ const tr = block;
13845
+ input.push({
13846
+ type: "function_call_output",
13847
+ call_id: tr.tool_use_id,
13848
+ output: tr.content
13849
+ });
13850
+ }
13851
+ }
13852
+ } else {
13853
+ input.push({
13854
+ role: "user",
13855
+ content: this.contentToStr(msg.content)
13856
+ });
13857
+ }
13858
+ } else if (msg.role === "assistant") {
13859
+ if (typeof msg.content === "string") {
13860
+ input.push({
13861
+ role: "assistant",
13862
+ content: msg.content
13863
+ });
13864
+ } else if (Array.isArray(msg.content)) {
13865
+ const textParts = [];
13866
+ for (const block of msg.content) {
13867
+ if (block.type === "text") {
13868
+ textParts.push(block.text);
13869
+ } else if (block.type === "tool_use") {
13870
+ if (textParts.length > 0) {
13871
+ input.push({
13872
+ role: "assistant",
13873
+ content: textParts.join("")
13874
+ });
13875
+ textParts.length = 0;
13876
+ }
13877
+ input.push({
13878
+ type: "function_call",
13879
+ call_id: block.id,
13880
+ name: block.name,
13881
+ arguments: JSON.stringify(block.input)
13882
+ });
13883
+ }
13884
+ }
13885
+ if (textParts.length > 0) {
13886
+ input.push({
13887
+ role: "assistant",
13888
+ content: textParts.join("")
13889
+ });
13890
+ }
13891
+ }
13892
+ }
13893
+ }
13894
+ return { input, instructions };
13895
+ }
13896
+ /**
13897
+ * Convert our tool definitions to Responses API FunctionTool format
13898
+ */
13899
+ convertToolsForResponses(tools) {
13900
+ return tools.map((tool) => ({
13901
+ type: "function",
13902
+ name: tool.name,
13903
+ description: tool.description ?? void 0,
13904
+ parameters: tool.input_schema ?? null,
13905
+ strict: false
13906
+ }));
13907
+ }
13908
+ /**
13909
+ * Parse tool call arguments with jsonrepair fallback
13910
+ */
13911
+ parseToolArguments(args) {
13912
+ try {
13913
+ return args ? JSON.parse(args) : {};
13914
+ } catch {
13915
+ try {
13916
+ if (args) {
13917
+ const repaired = jsonrepair(args);
13918
+ return JSON.parse(repaired);
13919
+ }
13920
+ } catch {
13921
+ console.error(`[${this.name}] Cannot parse tool arguments: ${args.slice(0, 200)}`);
13922
+ }
13923
+ return {};
13924
+ }
13925
+ }
13926
+ /**
13927
+ * Convert message content to string
13928
+ */
13929
+ contentToStr(content) {
13930
+ if (typeof content === "string") return content;
13931
+ return content.filter((b) => b.type === "text").map((b) => b.text).join("");
13932
+ }
13933
+ // --- Override metadata methods ---
13934
+ /**
13935
+ * Count tokens (approximate — Copilot models vary in tokenizer)
13936
+ */
13937
+ countTokens(text) {
13938
+ if (!text) return 0;
13939
+ return Math.ceil(text.length / 3.5);
13940
+ }
13941
+ /**
13942
+ * Get context window for the current model
13943
+ */
13944
+ getContextWindow() {
13945
+ const model = this.config.model ?? DEFAULT_MODEL4;
13946
+ return CONTEXT_WINDOWS4[model] ?? 128e3;
13947
+ }
13948
+ /**
13949
+ * Check if Copilot credentials are available
13950
+ */
13951
+ async isAvailable() {
13952
+ try {
13953
+ const tokenResult = await getValidCopilotToken();
13954
+ return tokenResult !== null;
13955
+ } catch {
13956
+ return false;
13957
+ }
13958
+ }
13959
+ };
13960
+ var DEFAULT_MODEL5 = "gemini-3.1-pro-preview";
13961
+ var CONTEXT_WINDOWS5 = {
13962
+ // Gemini 3.1 series (latest)
13963
+ "gemini-3.1-pro-preview": 1e6,
13964
+ "gemini-3.1-flash-lite-preview": 1e6,
13965
+ // Gemini 3 series
13361
13966
  "gemini-3-flash-preview": 1e6,
13362
- "gemini-3-pro-preview": 1e6,
13363
13967
  // Gemini 2.5 series (production stable)
13364
- "gemini-2.5-pro-preview-05-06": 1048576,
13365
- "gemini-2.5-flash-preview-05-20": 1048576,
13366
13968
  "gemini-2.5-pro": 1048576,
13367
13969
  "gemini-2.5-flash": 1048576,
13368
- // Gemini 2.0 series (GA stable)
13369
- "gemini-2.0-flash": 1048576,
13970
+ "gemini-2.5-flash-lite": 1048576,
13370
13971
  // Legacy
13371
13972
  "gemini-1.5-flash": 1e6,
13372
- "gemini-1.5-pro": 2e6,
13373
- "gemini-1.0-pro": 32e3
13973
+ "gemini-1.5-pro": 2e6
13374
13974
  };
13375
13975
  var GeminiProvider = class {
13376
13976
  id = "gemini";
@@ -13429,7 +14029,7 @@ var GeminiProvider = class {
13429
14029
  await this.refreshADCIfNeeded();
13430
14030
  try {
13431
14031
  const model = this.client.getGenerativeModel({
13432
- model: options?.model ?? this.config.model ?? DEFAULT_MODEL4,
14032
+ model: options?.model ?? this.config.model ?? DEFAULT_MODEL5,
13433
14033
  generationConfig: {
13434
14034
  maxOutputTokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
13435
14035
  temperature: options?.temperature ?? this.config.temperature ?? 0,
@@ -13458,7 +14058,7 @@ var GeminiProvider = class {
13458
14058
  }
13459
14059
  ];
13460
14060
  const model = this.client.getGenerativeModel({
13461
- model: options?.model ?? this.config.model ?? DEFAULT_MODEL4,
14061
+ model: options?.model ?? this.config.model ?? DEFAULT_MODEL5,
13462
14062
  generationConfig: {
13463
14063
  maxOutputTokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
13464
14064
  temperature: options?.temperature ?? this.config.temperature ?? 0
@@ -13487,7 +14087,7 @@ var GeminiProvider = class {
13487
14087
  await this.refreshADCIfNeeded();
13488
14088
  try {
13489
14089
  const model = this.client.getGenerativeModel({
13490
- model: options?.model ?? this.config.model ?? DEFAULT_MODEL4,
14090
+ model: options?.model ?? this.config.model ?? DEFAULT_MODEL5,
13491
14091
  generationConfig: {
13492
14092
  maxOutputTokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
13493
14093
  temperature: options?.temperature ?? this.config.temperature ?? 0
@@ -13526,7 +14126,7 @@ var GeminiProvider = class {
13526
14126
  }
13527
14127
  ];
13528
14128
  const model = this.client.getGenerativeModel({
13529
- model: options?.model ?? this.config.model ?? DEFAULT_MODEL4,
14129
+ model: options?.model ?? this.config.model ?? DEFAULT_MODEL5,
13530
14130
  generationConfig: {
13531
14131
  maxOutputTokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
13532
14132
  temperature: options?.temperature ?? this.config.temperature ?? 0
@@ -13610,8 +14210,8 @@ var GeminiProvider = class {
13610
14210
  * Get context window size
13611
14211
  */
13612
14212
  getContextWindow() {
13613
- const model = this.config.model ?? DEFAULT_MODEL4;
13614
- return CONTEXT_WINDOWS4[model] ?? 1e6;
14213
+ const model = this.config.model ?? DEFAULT_MODEL5;
14214
+ return CONTEXT_WINDOWS5[model] ?? 1e6;
13615
14215
  }
13616
14216
  /**
13617
14217
  * Check if provider is available
@@ -13619,7 +14219,7 @@ var GeminiProvider = class {
13619
14219
  async isAvailable() {
13620
14220
  if (!this.client) return false;
13621
14221
  try {
13622
- const modelName = this.config.model ?? DEFAULT_MODEL4;
14222
+ const modelName = this.config.model ?? DEFAULT_MODEL5;
13623
14223
  const model = this.client.getGenerativeModel({ model: modelName });
13624
14224
  await model.generateContent("hi");
13625
14225
  return true;
@@ -13751,7 +14351,7 @@ var GeminiProvider = class {
13751
14351
  inputTokens: usage?.promptTokenCount ?? 0,
13752
14352
  outputTokens: usage?.candidatesTokenCount ?? 0
13753
14353
  },
13754
- model: this.config.model ?? DEFAULT_MODEL4
14354
+ model: this.config.model ?? DEFAULT_MODEL5
13755
14355
  };
13756
14356
  }
13757
14357
  /**
@@ -13786,7 +14386,7 @@ var GeminiProvider = class {
13786
14386
  inputTokens: usage?.promptTokenCount ?? 0,
13787
14387
  outputTokens: usage?.candidatesTokenCount ?? 0
13788
14388
  },
13789
- model: this.config.model ?? DEFAULT_MODEL4,
14389
+ model: this.config.model ?? DEFAULT_MODEL5,
13790
14390
  toolCalls
13791
14391
  };
13792
14392
  }
@@ -13820,8 +14420,6 @@ var GeminiProvider = class {
13820
14420
  });
13821
14421
  }
13822
14422
  };
13823
-
13824
- // src/providers/index.ts
13825
14423
  init_env();
13826
14424
  async function createProvider(type, config = {}) {
13827
14425
  let provider;
@@ -13843,6 +14441,9 @@ async function createProvider(type, config = {}) {
13843
14441
  case "codex":
13844
14442
  provider = new CodexProvider();
13845
14443
  break;
14444
+ case "copilot":
14445
+ provider = new CopilotProvider();
14446
+ break;
13846
14447
  case "gemini":
13847
14448
  provider = new GeminiProvider();
13848
14449
  break;
@@ -14013,9 +14614,9 @@ function createInitialState(config) {
14013
14614
  }
14014
14615
  async function loadExistingState(projectPath) {
14015
14616
  try {
14016
- const fs37 = await import('fs/promises');
14617
+ const fs38 = await import('fs/promises');
14017
14618
  const statePath = `${projectPath}/.coco/state/project.json`;
14018
- const content = await fs37.readFile(statePath, "utf-8");
14619
+ const content = await fs38.readFile(statePath, "utf-8");
14019
14620
  const data = JSON.parse(content);
14020
14621
  data.createdAt = new Date(data.createdAt);
14021
14622
  data.updatedAt = new Date(data.updatedAt);
@@ -14025,13 +14626,13 @@ async function loadExistingState(projectPath) {
14025
14626
  }
14026
14627
  }
14027
14628
  async function saveState(state) {
14028
- const fs37 = await import('fs/promises');
14629
+ const fs38 = await import('fs/promises');
14029
14630
  const statePath = `${state.path}/.coco/state`;
14030
- await fs37.mkdir(statePath, { recursive: true });
14631
+ await fs38.mkdir(statePath, { recursive: true });
14031
14632
  const filePath = `${statePath}/project.json`;
14032
14633
  const tmpPath = `${filePath}.tmp.${Date.now()}`;
14033
- await fs37.writeFile(tmpPath, JSON.stringify(state, null, 2), "utf-8");
14034
- await fs37.rename(tmpPath, filePath);
14634
+ await fs38.writeFile(tmpPath, JSON.stringify(state, null, 2), "utf-8");
14635
+ await fs38.rename(tmpPath, filePath);
14035
14636
  }
14036
14637
  function getPhaseExecutor(phase) {
14037
14638
  switch (phase) {
@@ -14090,20 +14691,20 @@ async function createPhaseContext(config, state) {
14090
14691
  };
14091
14692
  const tools = {
14092
14693
  file: {
14093
- async read(path39) {
14094
- const fs37 = await import('fs/promises');
14095
- return fs37.readFile(path39, "utf-8");
14694
+ async read(path40) {
14695
+ const fs38 = await import('fs/promises');
14696
+ return fs38.readFile(path40, "utf-8");
14096
14697
  },
14097
- async write(path39, content) {
14098
- const fs37 = await import('fs/promises');
14698
+ async write(path40, content) {
14699
+ const fs38 = await import('fs/promises');
14099
14700
  const nodePath = await import('path');
14100
- await fs37.mkdir(nodePath.dirname(path39), { recursive: true });
14101
- await fs37.writeFile(path39, content, "utf-8");
14701
+ await fs38.mkdir(nodePath.dirname(path40), { recursive: true });
14702
+ await fs38.writeFile(path40, content, "utf-8");
14102
14703
  },
14103
- async exists(path39) {
14104
- const fs37 = await import('fs/promises');
14704
+ async exists(path40) {
14705
+ const fs38 = await import('fs/promises');
14105
14706
  try {
14106
- await fs37.access(path39);
14707
+ await fs38.access(path40);
14107
14708
  return true;
14108
14709
  } catch {
14109
14710
  return false;
@@ -14252,9 +14853,9 @@ async function createSnapshot(state) {
14252
14853
  var MAX_CHECKPOINT_VERSIONS = 5;
14253
14854
  async function getCheckpointFiles(state, phase) {
14254
14855
  try {
14255
- const fs37 = await import('fs/promises');
14856
+ const fs38 = await import('fs/promises');
14256
14857
  const checkpointDir = `${state.path}/.coco/checkpoints`;
14257
- const files = await fs37.readdir(checkpointDir);
14858
+ const files = await fs38.readdir(checkpointDir);
14258
14859
  const phaseFiles = files.filter((f) => f.startsWith(`snapshot-pre-${phase}-`) && f.endsWith(".json")).sort((a, b) => {
14259
14860
  const tsA = parseInt(a.split("-").pop()?.replace(".json", "") ?? "0", 10);
14260
14861
  const tsB = parseInt(b.split("-").pop()?.replace(".json", "") ?? "0", 10);
@@ -14267,11 +14868,11 @@ async function getCheckpointFiles(state, phase) {
14267
14868
  }
14268
14869
  async function cleanupOldCheckpoints(state, phase) {
14269
14870
  try {
14270
- const fs37 = await import('fs/promises');
14871
+ const fs38 = await import('fs/promises');
14271
14872
  const files = await getCheckpointFiles(state, phase);
14272
14873
  if (files.length > MAX_CHECKPOINT_VERSIONS) {
14273
14874
  const filesToDelete = files.slice(MAX_CHECKPOINT_VERSIONS);
14274
- await Promise.all(filesToDelete.map((f) => fs37.unlink(f).catch(() => {
14875
+ await Promise.all(filesToDelete.map((f) => fs38.unlink(f).catch(() => {
14275
14876
  })));
14276
14877
  }
14277
14878
  } catch {
@@ -14279,13 +14880,13 @@ async function cleanupOldCheckpoints(state, phase) {
14279
14880
  }
14280
14881
  async function saveSnapshot(state, snapshotId) {
14281
14882
  try {
14282
- const fs37 = await import('fs/promises');
14883
+ const fs38 = await import('fs/promises');
14283
14884
  const snapshotPath = `${state.path}/.coco/checkpoints/snapshot-${snapshotId}.json`;
14284
14885
  const snapshotDir = `${state.path}/.coco/checkpoints`;
14285
- await fs37.mkdir(snapshotDir, { recursive: true });
14886
+ await fs38.mkdir(snapshotDir, { recursive: true });
14286
14887
  const createdAt = state.createdAt instanceof Date ? state.createdAt.toISOString() : String(state.createdAt);
14287
14888
  const updatedAt = state.updatedAt instanceof Date ? state.updatedAt.toISOString() : String(state.updatedAt);
14288
- await fs37.writeFile(
14889
+ await fs38.writeFile(
14289
14890
  snapshotPath,
14290
14891
  JSON.stringify(
14291
14892
  {
@@ -14597,7 +15198,7 @@ async function loadConfig(configPath) {
14597
15198
  async function loadConfigFile(configPath, options = {}) {
14598
15199
  const { strict = true } = options;
14599
15200
  try {
14600
- const content = await fs15__default.readFile(configPath, "utf-8");
15201
+ const content = await fs16__default.readFile(configPath, "utf-8");
14601
15202
  const parsed = JSON5.parse(content);
14602
15203
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
14603
15204
  if (!strict) {
@@ -14653,7 +15254,7 @@ function deepMergeConfig(base, override) {
14653
15254
  };
14654
15255
  }
14655
15256
  function getProjectConfigPath2() {
14656
- return path16__default.join(process.cwd(), ".coco", "config.json");
15257
+ return path17__default.join(process.cwd(), ".coco", "config.json");
14657
15258
  }
14658
15259
  async function saveConfig(config, configPath, global = false) {
14659
15260
  const result = CocoConfigSchema.safeParse(config);
@@ -14668,10 +15269,10 @@ async function saveConfig(config, configPath, global = false) {
14668
15269
  });
14669
15270
  }
14670
15271
  const resolvedPath = configPath || (global ? CONFIG_PATHS.config : getProjectConfigPath2());
14671
- const dir = path16__default.dirname(resolvedPath);
14672
- await fs15__default.mkdir(dir, { recursive: true });
15272
+ const dir = path17__default.dirname(resolvedPath);
15273
+ await fs16__default.mkdir(dir, { recursive: true });
14673
15274
  const content = JSON.stringify(result.data, null, 2);
14674
- await fs15__default.writeFile(resolvedPath, content, "utf-8");
15275
+ await fs16__default.writeFile(resolvedPath, content, "utf-8");
14675
15276
  }
14676
15277
  function createDefaultConfig(projectName, language = "typescript") {
14677
15278
  return createDefaultConfigObject(projectName, language);
@@ -14679,7 +15280,7 @@ function createDefaultConfig(projectName, language = "typescript") {
14679
15280
  async function configExists(configPath, scope = "any") {
14680
15281
  if (configPath) {
14681
15282
  try {
14682
- await fs15__default.access(configPath);
15283
+ await fs16__default.access(configPath);
14683
15284
  return true;
14684
15285
  } catch {
14685
15286
  return false;
@@ -14687,7 +15288,7 @@ async function configExists(configPath, scope = "any") {
14687
15288
  }
14688
15289
  if (scope === "project" || scope === "any") {
14689
15290
  try {
14690
- await fs15__default.access(getProjectConfigPath2());
15291
+ await fs16__default.access(getProjectConfigPath2());
14691
15292
  return true;
14692
15293
  } catch {
14693
15294
  if (scope === "project") return false;
@@ -14695,7 +15296,7 @@ async function configExists(configPath, scope = "any") {
14695
15296
  }
14696
15297
  if (scope === "global" || scope === "any") {
14697
15298
  try {
14698
- await fs15__default.access(CONFIG_PATHS.config);
15299
+ await fs16__default.access(CONFIG_PATHS.config);
14699
15300
  return true;
14700
15301
  } catch {
14701
15302
  return false;
@@ -14737,15 +15338,15 @@ function levenshtein(a, b) {
14737
15338
  var MAX_DIR_ENTRIES = 200;
14738
15339
  var MAX_SUGGESTIONS = 5;
14739
15340
  async function suggestSimilarFiles(missingPath, options) {
14740
- const absPath = path16__default.resolve(missingPath);
14741
- const dir = path16__default.dirname(absPath);
14742
- const target = path16__default.basename(absPath);
15341
+ const absPath = path17__default.resolve(missingPath);
15342
+ const dir = path17__default.dirname(absPath);
15343
+ const target = path17__default.basename(absPath);
14743
15344
  const maxResults = MAX_SUGGESTIONS;
14744
15345
  try {
14745
- const entries = await fs15__default.readdir(dir);
15346
+ const entries = await fs16__default.readdir(dir);
14746
15347
  const limited = entries.slice(0, MAX_DIR_ENTRIES);
14747
15348
  const scored = limited.map((name) => ({
14748
- path: path16__default.join(dir, name),
15349
+ path: path17__default.join(dir, name),
14749
15350
  distance: levenshtein(target.toLowerCase(), name.toLowerCase())
14750
15351
  })).filter((s) => s.distance <= Math.max(target.length * 0.6, 3)).sort((a, b) => a.distance - b.distance);
14751
15352
  return scored.slice(0, maxResults);
@@ -14756,15 +15357,15 @@ async function suggestSimilarFiles(missingPath, options) {
14756
15357
  async function suggestSimilarPaths(missingPath, options) {
14757
15358
  const fileSuggestions = await suggestSimilarFiles(missingPath);
14758
15359
  if (fileSuggestions.length > 0) return fileSuggestions;
14759
- const absPath = path16__default.resolve(missingPath);
14760
- const grandparent = path16__default.dirname(path16__default.dirname(absPath));
14761
- const parentBasename = path16__default.basename(path16__default.dirname(absPath));
15360
+ const absPath = path17__default.resolve(missingPath);
15361
+ const grandparent = path17__default.dirname(path17__default.dirname(absPath));
15362
+ const parentBasename = path17__default.basename(path17__default.dirname(absPath));
14762
15363
  const maxResults = MAX_SUGGESTIONS;
14763
15364
  try {
14764
- const entries = await fs15__default.readdir(grandparent, { withFileTypes: true });
15365
+ const entries = await fs16__default.readdir(grandparent, { withFileTypes: true });
14765
15366
  const dirs = entries.filter((e) => e.isDirectory()).slice(0, MAX_DIR_ENTRIES);
14766
15367
  const scored = dirs.map((d) => ({
14767
- path: path16__default.join(grandparent, d.name),
15368
+ path: path17__default.join(grandparent, d.name),
14768
15369
  distance: levenshtein(parentBasename.toLowerCase(), d.name.toLowerCase())
14769
15370
  })).filter((s) => s.distance <= Math.max(parentBasename.length * 0.6, 3)).sort((a, b) => a.distance - b.distance);
14770
15371
  return scored.slice(0, maxResults);
@@ -14776,7 +15377,7 @@ function formatSuggestions(suggestions, baseDir) {
14776
15377
  if (suggestions.length === 0) return "";
14777
15378
  const base = baseDir ?? process.cwd();
14778
15379
  const lines = suggestions.map((s) => {
14779
- const rel = path16__default.relative(base, s.path);
15380
+ const rel = path17__default.relative(base, s.path);
14780
15381
  return ` - ${rel}`;
14781
15382
  });
14782
15383
  return `
@@ -14809,7 +15410,7 @@ function hasNullByte(str) {
14809
15410
  }
14810
15411
  function normalizePath(filePath) {
14811
15412
  let normalized = filePath.replace(/\0/g, "");
14812
- normalized = path16__default.normalize(normalized);
15413
+ normalized = path17__default.normalize(normalized);
14813
15414
  return normalized;
14814
15415
  }
14815
15416
  function isPathAllowed(filePath, operation) {
@@ -14817,31 +15418,31 @@ function isPathAllowed(filePath, operation) {
14817
15418
  return { allowed: false, reason: "Path contains invalid characters" };
14818
15419
  }
14819
15420
  const normalized = normalizePath(filePath);
14820
- const absolute = path16__default.resolve(normalized);
15421
+ const absolute = path17__default.resolve(normalized);
14821
15422
  const cwd = process.cwd();
14822
15423
  for (const blocked of BLOCKED_PATHS) {
14823
- const normalizedBlocked = path16__default.normalize(blocked);
14824
- if (absolute === normalizedBlocked || absolute.startsWith(normalizedBlocked + path16__default.sep)) {
15424
+ const normalizedBlocked = path17__default.normalize(blocked);
15425
+ if (absolute === normalizedBlocked || absolute.startsWith(normalizedBlocked + path17__default.sep)) {
14825
15426
  return { allowed: false, reason: `Access to system path '${blocked}' is not allowed` };
14826
15427
  }
14827
15428
  }
14828
15429
  const home = process.env.HOME;
14829
15430
  if (home) {
14830
- const normalizedHome = path16__default.normalize(home);
14831
- const normalizedCwd = path16__default.normalize(cwd);
15431
+ const normalizedHome = path17__default.normalize(home);
15432
+ const normalizedCwd = path17__default.normalize(cwd);
14832
15433
  if (absolute.startsWith(normalizedHome) && !absolute.startsWith(normalizedCwd)) {
14833
15434
  if (isWithinAllowedPath(absolute, operation)) ; else if (operation === "read") {
14834
15435
  const allowedHomeReads = [".gitconfig", ".zshrc", ".bashrc"];
14835
- const basename5 = path16__default.basename(absolute);
15436
+ const basename5 = path17__default.basename(absolute);
14836
15437
  if (!allowedHomeReads.includes(basename5)) {
14837
- const targetDir = path16__default.dirname(absolute);
15438
+ const targetDir = path17__default.dirname(absolute);
14838
15439
  return {
14839
15440
  allowed: false,
14840
15441
  reason: `Reading files outside project directory is not allowed. Use /allow-path ${targetDir} to grant access.`
14841
15442
  };
14842
15443
  }
14843
15444
  } else {
14844
- const targetDir = path16__default.dirname(absolute);
15445
+ const targetDir = path17__default.dirname(absolute);
14845
15446
  return {
14846
15447
  allowed: false,
14847
15448
  reason: `${operation} operations outside project directory are not allowed. Use /allow-path ${targetDir} to grant access.`
@@ -14850,7 +15451,7 @@ function isPathAllowed(filePath, operation) {
14850
15451
  }
14851
15452
  }
14852
15453
  if (operation === "write" || operation === "delete") {
14853
- const basename5 = path16__default.basename(absolute);
15454
+ const basename5 = path17__default.basename(absolute);
14854
15455
  for (const pattern of SENSITIVE_PATTERNS) {
14855
15456
  if (pattern.test(basename5)) {
14856
15457
  return {
@@ -14873,17 +15474,17 @@ function isENOENT(error) {
14873
15474
  return error.code === "ENOENT";
14874
15475
  }
14875
15476
  async function enrichENOENT(filePath, operation) {
14876
- const absPath = path16__default.resolve(filePath);
15477
+ const absPath = path17__default.resolve(filePath);
14877
15478
  const suggestions = await suggestSimilarFiles(absPath);
14878
- const hint = formatSuggestions(suggestions, path16__default.dirname(absPath));
15479
+ const hint = formatSuggestions(suggestions, path17__default.dirname(absPath));
14879
15480
  const action = operation === "read" ? "Use glob or list_dir to find the correct path." : "Check that the parent directory exists.";
14880
15481
  return `File not found: ${filePath}${hint}
14881
15482
  ${action}`;
14882
15483
  }
14883
15484
  async function enrichDirENOENT(dirPath) {
14884
- const absPath = path16__default.resolve(dirPath);
15485
+ const absPath = path17__default.resolve(dirPath);
14885
15486
  const suggestions = await suggestSimilarPaths(absPath);
14886
- const hint = formatSuggestions(suggestions, path16__default.dirname(absPath));
15487
+ const hint = formatSuggestions(suggestions, path17__default.dirname(absPath));
14887
15488
  return `Directory not found: ${dirPath}${hint}
14888
15489
  Use list_dir or glob to find the correct path.`;
14889
15490
  }
@@ -14904,13 +15505,13 @@ Examples:
14904
15505
  async execute({ path: filePath, encoding, maxSize }) {
14905
15506
  validatePath(filePath, "read");
14906
15507
  try {
14907
- const absolutePath = path16__default.resolve(filePath);
14908
- const stats = await fs15__default.stat(absolutePath);
15508
+ const absolutePath = path17__default.resolve(filePath);
15509
+ const stats = await fs16__default.stat(absolutePath);
14909
15510
  const maxBytes = maxSize ?? DEFAULT_MAX_FILE_SIZE;
14910
15511
  let truncated = false;
14911
15512
  let content;
14912
15513
  if (stats.size > maxBytes) {
14913
- const handle = await fs15__default.open(absolutePath, "r");
15514
+ const handle = await fs16__default.open(absolutePath, "r");
14914
15515
  try {
14915
15516
  const buffer = Buffer.alloc(maxBytes);
14916
15517
  await handle.read(buffer, 0, maxBytes, 0);
@@ -14920,7 +15521,7 @@ Examples:
14920
15521
  await handle.close();
14921
15522
  }
14922
15523
  } else {
14923
- content = await fs15__default.readFile(absolutePath, encoding);
15524
+ content = await fs16__default.readFile(absolutePath, encoding);
14924
15525
  }
14925
15526
  return {
14926
15527
  content,
@@ -14963,10 +15564,10 @@ Examples:
14963
15564
  async execute({ path: filePath, content, createDirs, dryRun }) {
14964
15565
  validatePath(filePath, "write");
14965
15566
  try {
14966
- const absolutePath = path16__default.resolve(filePath);
15567
+ const absolutePath = path17__default.resolve(filePath);
14967
15568
  let wouldCreate = false;
14968
15569
  try {
14969
- await fs15__default.access(absolutePath);
15570
+ await fs16__default.access(absolutePath);
14970
15571
  } catch {
14971
15572
  wouldCreate = true;
14972
15573
  }
@@ -14979,10 +15580,10 @@ Examples:
14979
15580
  };
14980
15581
  }
14981
15582
  if (createDirs) {
14982
- await fs15__default.mkdir(path16__default.dirname(absolutePath), { recursive: true });
15583
+ await fs16__default.mkdir(path17__default.dirname(absolutePath), { recursive: true });
14983
15584
  }
14984
- await fs15__default.writeFile(absolutePath, content, "utf-8");
14985
- const stats = await fs15__default.stat(absolutePath);
15585
+ await fs16__default.writeFile(absolutePath, content, "utf-8");
15586
+ const stats = await fs16__default.stat(absolutePath);
14986
15587
  return {
14987
15588
  path: absolutePath,
14988
15589
  size: stats.size,
@@ -15025,8 +15626,8 @@ Examples:
15025
15626
  async execute({ path: filePath, oldText, newText, all, dryRun }) {
15026
15627
  validatePath(filePath, "write");
15027
15628
  try {
15028
- const absolutePath = path16__default.resolve(filePath);
15029
- let content = await fs15__default.readFile(absolutePath, "utf-8");
15629
+ const absolutePath = path17__default.resolve(filePath);
15630
+ let content = await fs16__default.readFile(absolutePath, "utf-8");
15030
15631
  let replacements = 0;
15031
15632
  if (all) {
15032
15633
  const regex = new RegExp(escapeRegex(oldText), "g");
@@ -15075,7 +15676,7 @@ Hint: Use read_file first to verify the exact content.`
15075
15676
  preview
15076
15677
  };
15077
15678
  }
15078
- await fs15__default.writeFile(absolutePath, content, "utf-8");
15679
+ await fs16__default.writeFile(absolutePath, content, "utf-8");
15079
15680
  return {
15080
15681
  path: absolutePath,
15081
15682
  replacements,
@@ -15146,8 +15747,8 @@ Examples:
15146
15747
  }),
15147
15748
  async execute({ path: filePath }) {
15148
15749
  try {
15149
- const absolutePath = path16__default.resolve(filePath);
15150
- const stats = await fs15__default.stat(absolutePath);
15750
+ const absolutePath = path17__default.resolve(filePath);
15751
+ const stats = await fs16__default.stat(absolutePath);
15151
15752
  return {
15152
15753
  exists: true,
15153
15754
  isFile: stats.isFile(),
@@ -15177,12 +15778,12 @@ Examples:
15177
15778
  }),
15178
15779
  async execute({ path: dirPath, recursive }) {
15179
15780
  try {
15180
- const absolutePath = path16__default.resolve(dirPath);
15781
+ const absolutePath = path17__default.resolve(dirPath);
15181
15782
  const entries = [];
15182
15783
  async function listDir(dir, prefix = "") {
15183
- const items = await fs15__default.readdir(dir, { withFileTypes: true });
15784
+ const items = await fs16__default.readdir(dir, { withFileTypes: true });
15184
15785
  for (const item of items) {
15185
- const fullPath = path16__default.join(dir, item.name);
15786
+ const fullPath = path17__default.join(dir, item.name);
15186
15787
  const relativePath = prefix ? `${prefix}/${item.name}` : item.name;
15187
15788
  if (item.isDirectory()) {
15188
15789
  entries.push({ name: relativePath, type: "directory" });
@@ -15190,7 +15791,7 @@ Examples:
15190
15791
  await listDir(fullPath, relativePath);
15191
15792
  }
15192
15793
  } else if (item.isFile()) {
15193
- const stats = await fs15__default.stat(fullPath);
15794
+ const stats = await fs16__default.stat(fullPath);
15194
15795
  entries.push({ name: relativePath, type: "file", size: stats.size });
15195
15796
  }
15196
15797
  }
@@ -15237,23 +15838,23 @@ Examples:
15237
15838
  }
15238
15839
  validatePath(filePath, "delete");
15239
15840
  try {
15240
- const absolutePath = path16__default.resolve(filePath);
15241
- const stats = await fs15__default.stat(absolutePath);
15841
+ const absolutePath = path17__default.resolve(filePath);
15842
+ const stats = await fs16__default.stat(absolutePath);
15242
15843
  if (stats.isDirectory()) {
15243
15844
  if (!recursive) {
15244
15845
  throw new ToolError("Cannot delete directory without recursive: true", {
15245
15846
  tool: "delete_file"
15246
15847
  });
15247
15848
  }
15248
- await fs15__default.rm(absolutePath, { recursive: true });
15849
+ await fs16__default.rm(absolutePath, { recursive: true });
15249
15850
  } else {
15250
- await fs15__default.unlink(absolutePath);
15851
+ await fs16__default.unlink(absolutePath);
15251
15852
  }
15252
15853
  return { deleted: true, path: absolutePath };
15253
15854
  } catch (error) {
15254
15855
  if (error instanceof ToolError) throw error;
15255
15856
  if (error.code === "ENOENT") {
15256
- return { deleted: false, path: path16__default.resolve(filePath) };
15857
+ return { deleted: false, path: path17__default.resolve(filePath) };
15257
15858
  }
15258
15859
  throw new FileSystemError(`Failed to delete: ${filePath}`, {
15259
15860
  path: filePath,
@@ -15281,11 +15882,11 @@ Examples:
15281
15882
  validatePath(source, "read");
15282
15883
  validatePath(destination, "write");
15283
15884
  try {
15284
- const srcPath = path16__default.resolve(source);
15285
- const destPath = path16__default.resolve(destination);
15885
+ const srcPath = path17__default.resolve(source);
15886
+ const destPath = path17__default.resolve(destination);
15286
15887
  if (!overwrite) {
15287
15888
  try {
15288
- await fs15__default.access(destPath);
15889
+ await fs16__default.access(destPath);
15289
15890
  throw new ToolError(
15290
15891
  `Destination already exists: ${destination}. Use overwrite: true to replace.`,
15291
15892
  {
@@ -15298,9 +15899,9 @@ Examples:
15298
15899
  }
15299
15900
  }
15300
15901
  }
15301
- await fs15__default.mkdir(path16__default.dirname(destPath), { recursive: true });
15302
- await fs15__default.copyFile(srcPath, destPath);
15303
- const stats = await fs15__default.stat(destPath);
15902
+ await fs16__default.mkdir(path17__default.dirname(destPath), { recursive: true });
15903
+ await fs16__default.copyFile(srcPath, destPath);
15904
+ const stats = await fs16__default.stat(destPath);
15304
15905
  return {
15305
15906
  source: srcPath,
15306
15907
  destination: destPath,
@@ -15342,11 +15943,11 @@ Examples:
15342
15943
  validatePath(source, "delete");
15343
15944
  validatePath(destination, "write");
15344
15945
  try {
15345
- const srcPath = path16__default.resolve(source);
15346
- const destPath = path16__default.resolve(destination);
15946
+ const srcPath = path17__default.resolve(source);
15947
+ const destPath = path17__default.resolve(destination);
15347
15948
  if (!overwrite) {
15348
15949
  try {
15349
- await fs15__default.access(destPath);
15950
+ await fs16__default.access(destPath);
15350
15951
  throw new ToolError(
15351
15952
  `Destination already exists: ${destination}. Use overwrite: true to replace.`,
15352
15953
  {
@@ -15359,8 +15960,8 @@ Examples:
15359
15960
  }
15360
15961
  }
15361
15962
  }
15362
- await fs15__default.mkdir(path16__default.dirname(destPath), { recursive: true });
15363
- await fs15__default.rename(srcPath, destPath);
15963
+ await fs16__default.mkdir(path17__default.dirname(destPath), { recursive: true });
15964
+ await fs16__default.rename(srcPath, destPath);
15364
15965
  return {
15365
15966
  source: srcPath,
15366
15967
  destination: destPath
@@ -15402,13 +16003,13 @@ Examples:
15402
16003
  }),
15403
16004
  async execute({ path: dirPath, depth, showHidden, dirsOnly }) {
15404
16005
  try {
15405
- const absolutePath = path16__default.resolve(dirPath ?? ".");
16006
+ const absolutePath = path17__default.resolve(dirPath ?? ".");
15406
16007
  let totalFiles = 0;
15407
16008
  let totalDirs = 0;
15408
- const lines = [path16__default.basename(absolutePath) + "/"];
16009
+ const lines = [path17__default.basename(absolutePath) + "/"];
15409
16010
  async function buildTree(dir, prefix, currentDepth) {
15410
16011
  if (currentDepth > (depth ?? 4)) return;
15411
- let items = await fs15__default.readdir(dir, { withFileTypes: true });
16012
+ let items = await fs16__default.readdir(dir, { withFileTypes: true });
15412
16013
  if (!showHidden) {
15413
16014
  items = items.filter((item) => !item.name.startsWith("."));
15414
16015
  }
@@ -15428,7 +16029,7 @@ Examples:
15428
16029
  if (item.isDirectory()) {
15429
16030
  totalDirs++;
15430
16031
  lines.push(`${prefix}${connector}${item.name}/`);
15431
- await buildTree(path16__default.join(dir, item.name), prefix + childPrefix, currentDepth + 1);
16032
+ await buildTree(path17__default.join(dir, item.name), prefix + childPrefix, currentDepth + 1);
15432
16033
  } else {
15433
16034
  totalFiles++;
15434
16035
  lines.push(`${prefix}${connector}${item.name}`);
@@ -15968,9 +16569,9 @@ Examples:
15968
16569
  if (file) {
15969
16570
  options.file = file;
15970
16571
  }
15971
- const log2 = await git.log(options);
16572
+ const log3 = await git.log(options);
15972
16573
  return {
15973
- commits: log2.all.map((commit) => ({
16574
+ commits: log3.all.map((commit) => ({
15974
16575
  hash: commit.hash,
15975
16576
  message: commit.message,
15976
16577
  author: commit.author_name,
@@ -16282,6 +16883,34 @@ var simpleAutoCommitTool = defineTool({
16282
16883
  }
16283
16884
  });
16284
16885
  var gitSimpleTools = [checkProtectedBranchTool, simpleAutoCommitTool];
16886
+ var AGENT_NAMES = {
16887
+ explore: "Explorer",
16888
+ plan: "Planner",
16889
+ test: "Tester",
16890
+ debug: "Debugger",
16891
+ review: "Reviewer",
16892
+ architect: "Architect",
16893
+ security: "Security Auditor",
16894
+ tdd: "TDD Guide",
16895
+ refactor: "Refactorer",
16896
+ e2e: "E2E Tester",
16897
+ docs: "Docs Writer",
16898
+ database: "Database Engineer"
16899
+ };
16900
+ var AGENT_DESCRIPTIONS = {
16901
+ explore: "Search the codebase to answer questions and gather information",
16902
+ plan: "Design implementation approaches and create detailed plans",
16903
+ test: "Write and run tests to ensure code quality",
16904
+ debug: "Analyze errors and fix issues",
16905
+ review: "Review code for quality and best practices",
16906
+ architect: "Design system architecture and create architectural decision records",
16907
+ security: "Audit code for security vulnerabilities using OWASP Top 10",
16908
+ tdd: "Drive development with test-first methodology and RED-GREEN-REFACTOR cycle",
16909
+ refactor: "Improve code structure and quality without changing behavior",
16910
+ e2e: "Write and run end-to-end tests covering full user workflows",
16911
+ docs: "Generate and maintain documentation for code, APIs, and architecture",
16912
+ database: "Design database schemas, write migrations, and optimize queries"
16913
+ };
16285
16914
 
16286
16915
  // src/agents/provider-bridge.ts
16287
16916
  var agentProvider = null;
@@ -16292,103 +16921,80 @@ function getAgentProvider() {
16292
16921
  function getAgentToolRegistry() {
16293
16922
  return agentToolRegistry;
16294
16923
  }
16295
- var AGENT_ROLES = {
16296
- researcher: {
16297
- role: "researcher",
16298
- systemPrompt: `You are a code researcher agent. Your role is to:
16299
- - Explore and understand existing codebases
16300
- - Find relevant code patterns and examples
16301
- - Identify dependencies and relationships
16302
- - Document your findings clearly
16303
-
16304
- Use tools to search, read files, and analyze code structure.`,
16305
- allowedTools: ["read_file", "grep", "find_in_file", "glob", "codebase_map"]
16306
- },
16307
- coder: {
16308
- role: "coder",
16309
- systemPrompt: `You are a code generation agent. Your role is to:
16310
- - Write high-quality, production-ready code
16311
- - Follow best practices and coding standards
16312
- - Ensure code is syntactically valid
16313
- - Write clean, maintainable code
16314
-
16315
- Use tools to read existing code, write new files, and validate syntax.`,
16316
- allowedTools: ["read_file", "write_file", "edit_file", "bash_exec", "validateCode"]
16317
- },
16318
- tester: {
16319
- role: "tester",
16320
- systemPrompt: `You are a test generation agent. Your role is to:
16321
- - Write comprehensive test suites
16322
- - Achieve high code coverage
16323
- - Test edge cases and error conditions
16324
- - Ensure tests are reliable and maintainable
16325
-
16326
- Use tools to read code, write tests, and run them.`,
16327
- allowedTools: ["read_file", "write_file", "run_tests", "get_coverage", "run_test_file"]
16328
- },
16329
- reviewer: {
16330
- role: "reviewer",
16331
- systemPrompt: `You are a code review agent. Your role is to:
16332
- - Identify code quality issues
16333
- - Check for security vulnerabilities
16334
- - Ensure best practices are followed
16335
- - Provide actionable feedback
16336
-
16337
- Use tools to read and analyze code quality.`,
16338
- allowedTools: ["read_file", "calculate_quality", "analyze_complexity", "grep"]
16339
- },
16340
- optimizer: {
16341
- role: "optimizer",
16342
- systemPrompt: `You are a code optimization agent. Your role is to:
16343
- - Reduce code complexity
16344
- - Eliminate duplication
16345
- - Improve performance
16346
- - Refactor for maintainability
16347
-
16348
- Use tools to analyze and improve code.`,
16349
- allowedTools: ["read_file", "write_file", "edit_file", "analyze_complexity", "grep"]
16350
- },
16351
- planner: {
16352
- role: "planner",
16353
- systemPrompt: `You are a task planning agent. Your role is to:
16354
- - Break down complex tasks into subtasks
16355
- - Identify dependencies between tasks
16356
- - Estimate complexity and effort
16357
- - Create actionable plans
16358
-
16359
- Use tools to analyze requirements and explore the codebase.`,
16360
- allowedTools: ["read_file", "grep", "glob", "codebase_map"]
16924
+ function getAgentManager() {
16925
+ {
16926
+ return null;
16361
16927
  }
16362
- };
16928
+ }
16363
16929
 
16364
16930
  // src/tools/simple-agent.ts
16931
+ var AGENT_TYPES = [
16932
+ "explore",
16933
+ "plan",
16934
+ "test",
16935
+ "debug",
16936
+ "review",
16937
+ "architect",
16938
+ "security",
16939
+ "tdd",
16940
+ "refactor",
16941
+ "e2e",
16942
+ "docs",
16943
+ "database"
16944
+ ];
16945
+ var LEGACY_ROLE_MAP = {
16946
+ researcher: "explore",
16947
+ coder: "debug",
16948
+ // "debug" has write + bash + read — closest to general coding
16949
+ tester: "test",
16950
+ reviewer: "review",
16951
+ optimizer: "refactor",
16952
+ planner: "plan"
16953
+ };
16365
16954
  var SpawnSimpleAgentSchema = z.object({
16366
16955
  task: z.string().describe("Task description for the sub-agent"),
16367
16956
  context: z.string().optional().describe("Additional context or instructions for the agent"),
16368
- role: z.enum(["researcher", "coder", "tester", "reviewer", "optimizer", "planner"]).default("coder").describe("Agent role to use"),
16957
+ type: z.enum(AGENT_TYPES).optional().describe(
16958
+ "Specialized agent type. Use 'explore' for codebase search, 'plan' for design, 'test' for testing, 'review' for code review, 'architect' for system design, 'security' for security audit, 'tdd' for test-driven development, 'debug' for debugging, 'refactor' for code improvement, 'e2e' for integration tests, 'docs' for documentation, 'database' for DB operations."
16959
+ ),
16960
+ role: z.enum(["researcher", "coder", "tester", "reviewer", "optimizer", "planner"]).optional().describe("DEPRECATED: Use 'type' instead. Legacy role name, mapped to new agent types."),
16369
16961
  maxTurns: z.number().default(10).describe("Maximum tool-use turns for the agent")
16370
16962
  });
16963
+ function resolveAgentType(input) {
16964
+ if (input.type) return input.type;
16965
+ if (input.role && input.role in LEGACY_ROLE_MAP) return LEGACY_ROLE_MAP[input.role];
16966
+ return "explore";
16967
+ }
16371
16968
  var spawnSimpleAgentTool = defineTool({
16372
16969
  name: "spawnSimpleAgent",
16373
- description: `Spawn a sub-agent to handle a specific task with real LLM tool-use execution.
16374
-
16375
- Use this when you need to:
16376
- - Delegate a focused task to another agent
16377
- - Get a second opinion or alternative approach
16378
- - Handle multiple independent subtasks
16379
-
16380
- The sub-agent will work on the task autonomously using available tools.
16381
-
16382
- Example: "Write unit tests for the authentication module"`,
16970
+ description: `Spawn a specialized sub-agent to handle a specific task autonomously.
16971
+
16972
+ Available agent types:
16973
+ - explore: Search and understand codebases (read-only, fast)
16974
+ - plan: Design implementation approaches (read-only)
16975
+ - test: Write and run tests
16976
+ - debug: Analyze errors and fix issues
16977
+ - review: Review code for quality and best practices (read-only)
16978
+ - architect: Design system architecture (read-only)
16979
+ - security: Audit code for security vulnerabilities (read-only)
16980
+ - tdd: Test-driven development with RED-GREEN-REFACTOR
16981
+ - refactor: Improve code structure without changing behavior
16982
+ - e2e: End-to-end integration testing
16983
+ - docs: Generate and maintain documentation
16984
+ - database: Design schemas, migrations, and optimize queries
16985
+
16986
+ Each type has a filtered set of tools appropriate for its role.
16987
+ Use 'explore' for quick codebase searches, 'plan' for design before execution.`,
16383
16988
  category: "build",
16384
16989
  parameters: SpawnSimpleAgentSchema,
16385
16990
  async execute(input) {
16386
16991
  const typedInput = input;
16387
- {
16388
- const agentId2 = `agent-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
16992
+ const manager = getAgentManager();
16993
+ if (!manager) {
16994
+ const agentId = `agent-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
16389
16995
  return {
16390
16996
  stdout: JSON.stringify({
16391
- agentId: agentId2,
16997
+ agentId,
16392
16998
  status: "unavailable",
16393
16999
  task: typedInput.task,
16394
17000
  message: "Agent provider not initialized. Call setAgentProvider() during orchestrator startup.",
@@ -16399,6 +17005,31 @@ Example: "Write unit tests for the authentication module"`,
16399
17005
  duration: 0
16400
17006
  };
16401
17007
  }
17008
+ const agentType = resolveAgentType(typedInput);
17009
+ const taskDescription = typedInput.context ? `${typedInput.task}
17010
+
17011
+ Additional context: ${typedInput.context}` : typedInput.task;
17012
+ const startTime = Date.now();
17013
+ const result = await manager.spawn(agentType, taskDescription, {
17014
+ timeout: typedInput.maxTurns * 6e4
17015
+ // rough estimate: 1 min per turn
17016
+ });
17017
+ const duration = Date.now() - startTime;
17018
+ return {
17019
+ stdout: JSON.stringify({
17020
+ agentId: result.agent.id,
17021
+ agentType,
17022
+ status: result.success ? "completed" : "failed",
17023
+ task: typedInput.task,
17024
+ output: result.output,
17025
+ success: result.success,
17026
+ usage: result.usage,
17027
+ duration
17028
+ }),
17029
+ stderr: "",
17030
+ exitCode: result.success ? 0 : 1,
17031
+ duration
17032
+ };
16402
17033
  }
16403
17034
  });
16404
17035
  var checkAgentCapabilityTool = defineTool({
@@ -16410,17 +17041,23 @@ var checkAgentCapabilityTool = defineTool({
16410
17041
  const provider = getAgentProvider();
16411
17042
  const toolRegistry = getAgentToolRegistry();
16412
17043
  const isReady = provider !== null;
17044
+ const agentTypes = Object.entries(AGENT_DESCRIPTIONS).map(([type, description]) => ({
17045
+ type,
17046
+ name: AGENT_NAMES[type],
17047
+ description
17048
+ }));
16413
17049
  return {
16414
17050
  stdout: JSON.stringify({
16415
17051
  multiAgentSupported: true,
16416
17052
  providerConfigured: provider !== null,
16417
17053
  toolRegistryConfigured: toolRegistry !== null,
16418
17054
  ready: isReady,
16419
- availableRoles: Object.keys(AGENT_ROLES),
17055
+ availableTypes: agentTypes,
16420
17056
  features: {
16421
17057
  taskDelegation: "requires provider initialization",
16422
17058
  parallelSpawn: "requires provider initialization",
16423
- multiTurnToolUse: "requires provider initialization"
17059
+ multiTurnToolUse: "requires provider initialization",
17060
+ specializedAgents: "requires provider initialization"
16424
17061
  },
16425
17062
  status: "Provider not initialized. Call setAgentProvider() during startup."
16426
17063
  }),
@@ -16433,8 +17070,8 @@ var checkAgentCapabilityTool = defineTool({
16433
17070
  var simpleAgentTools = [spawnSimpleAgentTool, checkAgentCapabilityTool];
16434
17071
  async function detectTestFramework2(cwd) {
16435
17072
  try {
16436
- const pkgPath = path16__default.join(cwd, "package.json");
16437
- const pkgContent = await fs15__default.readFile(pkgPath, "utf-8");
17073
+ const pkgPath = path17__default.join(cwd, "package.json");
17074
+ const pkgContent = await fs16__default.readFile(pkgPath, "utf-8");
16438
17075
  const pkg = JSON.parse(pkgContent);
16439
17076
  const deps = {
16440
17077
  ...pkg.dependencies,
@@ -16615,13 +17252,13 @@ Examples:
16615
17252
  const projectDir = cwd ?? process.cwd();
16616
17253
  try {
16617
17254
  const coverageLocations = [
16618
- path16__default.join(projectDir, "coverage", "coverage-summary.json"),
16619
- path16__default.join(projectDir, "coverage", "coverage-final.json"),
16620
- path16__default.join(projectDir, ".nyc_output", "coverage-summary.json")
17255
+ path17__default.join(projectDir, "coverage", "coverage-summary.json"),
17256
+ path17__default.join(projectDir, "coverage", "coverage-final.json"),
17257
+ path17__default.join(projectDir, ".nyc_output", "coverage-summary.json")
16621
17258
  ];
16622
17259
  for (const location of coverageLocations) {
16623
17260
  try {
16624
- const content = await fs15__default.readFile(location, "utf-8");
17261
+ const content = await fs16__default.readFile(location, "utf-8");
16625
17262
  const coverage = JSON.parse(content);
16626
17263
  if (coverage.total) {
16627
17264
  return {
@@ -16674,8 +17311,8 @@ Examples:
16674
17311
  var testTools = [runTestsTool, getCoverageTool, runTestFileTool];
16675
17312
  async function detectLinter2(cwd) {
16676
17313
  try {
16677
- const pkgPath = path16__default.join(cwd, "package.json");
16678
- const pkgContent = await fs15__default.readFile(pkgPath, "utf-8");
17314
+ const pkgPath = path17__default.join(cwd, "package.json");
17315
+ const pkgContent = await fs16__default.readFile(pkgPath, "utf-8");
16679
17316
  const pkg = JSON.parse(pkgContent);
16680
17317
  const deps = {
16681
17318
  ...pkg.dependencies,
@@ -16833,7 +17470,7 @@ Examples:
16833
17470
  let totalFunctions = 0;
16834
17471
  let complexFunctions = 0;
16835
17472
  for (const file of targetFiles) {
16836
- const content = await fs15__default.readFile(file, "utf-8");
17473
+ const content = await fs16__default.readFile(file, "utf-8");
16837
17474
  const fileComplexity = analyzeFileComplexity(content, file);
16838
17475
  fileResults.push(fileComplexity);
16839
17476
  totalComplexity += fileComplexity.complexity;
@@ -16984,7 +17621,7 @@ Examples:
16984
17621
  caseSensitive,
16985
17622
  wholeWord
16986
17623
  }) {
16987
- const targetPath = searchPath ? path16__default.resolve(searchPath) : process.cwd();
17624
+ const targetPath = searchPath ? path17__default.resolve(searchPath) : process.cwd();
16988
17625
  const matches = [];
16989
17626
  let filesSearched = 0;
16990
17627
  const filesWithMatches = /* @__PURE__ */ new Set();
@@ -17006,7 +17643,7 @@ Examples:
17006
17643
  tool: "grep"
17007
17644
  });
17008
17645
  }
17009
- const stats = await fs15__default.stat(targetPath);
17646
+ const stats = await fs16__default.stat(targetPath);
17010
17647
  let filesToSearch;
17011
17648
  if (stats.isFile()) {
17012
17649
  filesToSearch = [targetPath];
@@ -17028,7 +17665,7 @@ Examples:
17028
17665
  }
17029
17666
  filesSearched++;
17030
17667
  try {
17031
- const content = await fs15__default.readFile(file, "utf-8");
17668
+ const content = await fs16__default.readFile(file, "utf-8");
17032
17669
  const lines = content.split("\n");
17033
17670
  let fileHasMatch = false;
17034
17671
  for (let i = 0; i < lines.length; i++) {
@@ -17051,7 +17688,7 @@ Examples:
17051
17688
  contextAfter.push(lines[j] ?? "");
17052
17689
  }
17053
17690
  matches.push({
17054
- file: path16__default.relative(process.cwd(), file),
17691
+ file: path17__default.relative(process.cwd(), file),
17055
17692
  line: i + 1,
17056
17693
  column: match.index + 1,
17057
17694
  content: line,
@@ -17102,8 +17739,8 @@ Examples:
17102
17739
  }),
17103
17740
  async execute({ file, pattern, caseSensitive }) {
17104
17741
  try {
17105
- const absolutePath = path16__default.resolve(file);
17106
- const content = await fs15__default.readFile(absolutePath, "utf-8");
17742
+ const absolutePath = path17__default.resolve(file);
17743
+ const content = await fs16__default.readFile(absolutePath, "utf-8");
17107
17744
  const lines = content.split("\n");
17108
17745
  const matches = [];
17109
17746
  const flags = caseSensitive ? "" : "i";
@@ -17132,7 +17769,7 @@ Examples:
17132
17769
  }
17133
17770
  });
17134
17771
  var searchTools = [grepTool, findInFileTool];
17135
- var DEFAULT_TIMEOUT_MS2 = 3e4;
17772
+ var DEFAULT_TIMEOUT_MS3 = 3e4;
17136
17773
  var MAX_RESPONSE_SIZE = 5 * 1024 * 1024;
17137
17774
  var httpFetchTool = defineTool({
17138
17775
  name: "http_fetch",
@@ -17155,7 +17792,7 @@ Examples:
17155
17792
  }),
17156
17793
  async execute({ url, method, headers, body, timeout, maxSize }) {
17157
17794
  const startTime = performance.now();
17158
- const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS2;
17795
+ const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
17159
17796
  const maxBytes = maxSize ?? MAX_RESPONSE_SIZE;
17160
17797
  try {
17161
17798
  const controller = new AbortController();
@@ -17273,7 +17910,7 @@ Examples:
17273
17910
  }
17274
17911
  });
17275
17912
  var httpTools = [httpFetchTool, httpJsonTool];
17276
- var DEFAULT_TIMEOUT_MS3 = 6e5;
17913
+ var DEFAULT_TIMEOUT_MS4 = 6e5;
17277
17914
  var MAX_OUTPUT_SIZE2 = 2 * 1024 * 1024;
17278
17915
  function getBuildHint(stderr, tool) {
17279
17916
  if (/MODULE_NOT_FOUND|Cannot find module/i.test(stderr))
@@ -17300,7 +17937,7 @@ async function detectPackageManager(cwd) {
17300
17937
  ];
17301
17938
  for (const { file, pm } of lockfiles) {
17302
17939
  try {
17303
- await fs15__default.access(path16__default.join(cwd, file));
17940
+ await fs16__default.access(path17__default.join(cwd, file));
17304
17941
  return pm;
17305
17942
  } catch {
17306
17943
  }
@@ -17337,7 +17974,7 @@ Examples:
17337
17974
  async execute({ script, cwd, packageManager, args, env: env2, timeout }) {
17338
17975
  const projectDir = cwd ?? process.cwd();
17339
17976
  const startTime = performance.now();
17340
- const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
17977
+ const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS4;
17341
17978
  const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
17342
17979
  const heartbeat = new CommandHeartbeat2({
17343
17980
  onUpdate: (stats) => {
@@ -17433,7 +18070,7 @@ Examples:
17433
18070
  async execute({ cwd, packageManager, packages, dev, frozen, timeout }) {
17434
18071
  const projectDir = cwd ?? process.cwd();
17435
18072
  const startTime = performance.now();
17436
- const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
18073
+ const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS4;
17437
18074
  const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
17438
18075
  const heartbeat = new CommandHeartbeat2({
17439
18076
  onUpdate: (stats) => {
@@ -17557,7 +18194,7 @@ Examples:
17557
18194
  async execute({ target, cwd, args, env: env2, timeout }) {
17558
18195
  const projectDir = cwd ?? process.cwd();
17559
18196
  const startTime = performance.now();
17560
- const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
18197
+ const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS4;
17561
18198
  const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
17562
18199
  const heartbeat = new CommandHeartbeat2({
17563
18200
  onUpdate: (stats) => {
@@ -17573,7 +18210,7 @@ ${message}
17573
18210
  });
17574
18211
  try {
17575
18212
  try {
17576
- await fs15__default.access(path16__default.join(projectDir, "Makefile"));
18213
+ await fs16__default.access(path17__default.join(projectDir, "Makefile"));
17577
18214
  } catch {
17578
18215
  throw new ToolError("No Makefile found in directory", { tool: "make" });
17579
18216
  }
@@ -17660,7 +18297,7 @@ Examples:
17660
18297
  async execute({ cwd, project, noEmit, watch: watch2, args, timeout }) {
17661
18298
  const projectDir = cwd ?? process.cwd();
17662
18299
  const startTime = performance.now();
17663
- const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
18300
+ const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS4;
17664
18301
  const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
17665
18302
  const heartbeat = new CommandHeartbeat2({
17666
18303
  onUpdate: (stats) => {
@@ -17778,7 +18415,7 @@ z.object({
17778
18415
  });
17779
18416
 
17780
18417
  // src/cli/repl/session.ts
17781
- path16__default.dirname(CONFIG_PATHS.trustedTools);
18418
+ path17__default.dirname(CONFIG_PATHS.trustedTools);
17782
18419
  CONFIG_PATHS.trustedTools;
17783
18420
 
17784
18421
  // src/cli/repl/recommended-permissions.ts
@@ -18440,7 +19077,7 @@ Examples:
18440
19077
  }
18441
19078
  }
18442
19079
  });
18443
- var DEFAULT_TIMEOUT_MS4 = 3e4;
19080
+ var DEFAULT_TIMEOUT_MS5 = 3e4;
18444
19081
  var DEFAULT_MAX_LENGTH = 5e4;
18445
19082
  var MAX_DOWNLOAD_SIZE = 10 * 1024 * 1024;
18446
19083
  var BLOCKED_SCHEMES = ["file:", "ftp:", "data:", "javascript:"];
@@ -18671,12 +19308,12 @@ Examples:
18671
19308
  url: z.string().url().describe("URL to fetch"),
18672
19309
  extractContent: z.boolean().optional().default(true).describe("Extract and clean main content (true) or return raw (false)"),
18673
19310
  maxLength: z.number().min(1e3).max(2e5).optional().default(DEFAULT_MAX_LENGTH).describe("Maximum content length in characters"),
18674
- timeout: z.number().min(1e3).max(12e4).optional().default(DEFAULT_TIMEOUT_MS4).describe("Timeout in milliseconds")
19311
+ timeout: z.number().min(1e3).max(12e4).optional().default(DEFAULT_TIMEOUT_MS5).describe("Timeout in milliseconds")
18675
19312
  }),
18676
19313
  async execute({ url, extractContent, maxLength, timeout }) {
18677
19314
  const startTime = performance.now();
18678
19315
  const effectiveMaxLength = maxLength ?? DEFAULT_MAX_LENGTH;
18679
- const effectiveTimeout = timeout ?? DEFAULT_TIMEOUT_MS4;
19316
+ const effectiveTimeout = timeout ?? DEFAULT_TIMEOUT_MS5;
18680
19317
  validateUrl(url);
18681
19318
  const controller = new AbortController();
18682
19319
  const timeoutId = setTimeout(() => controller.abort(), effectiveTimeout);
@@ -18805,63 +19442,63 @@ var LANG_ALIASES = {
18805
19442
  };
18806
19443
  var TOKEN_COLORS = {
18807
19444
  // Keywords & control flow
18808
- keyword: (t) => chalk3.blue(t),
18809
- "keyword.control": (t) => chalk3.blue(t),
19445
+ keyword: (t) => chalk4.blue(t),
19446
+ "keyword.control": (t) => chalk4.blue(t),
18810
19447
  // Built-in types and literals
18811
- built_in: (t) => chalk3.cyan(t),
18812
- type: (t) => chalk3.cyan(t),
18813
- class: (t) => chalk3.cyan(t),
18814
- "title.class": (t) => chalk3.cyan(t),
18815
- "title.class.inherited": (t) => chalk3.cyan(t),
19448
+ built_in: (t) => chalk4.cyan(t),
19449
+ type: (t) => chalk4.cyan(t),
19450
+ class: (t) => chalk4.cyan(t),
19451
+ "title.class": (t) => chalk4.cyan(t),
19452
+ "title.class.inherited": (t) => chalk4.cyan(t),
18816
19453
  // Functions
18817
- "title.function": (t) => chalk3.green(t),
18818
- "title.function.invoke": (t) => chalk3.green(t),
18819
- title: (t) => chalk3.green(t),
19454
+ "title.function": (t) => chalk4.green(t),
19455
+ "title.function.invoke": (t) => chalk4.green(t),
19456
+ title: (t) => chalk4.green(t),
18820
19457
  // Strings
18821
- string: (t) => chalk3.yellow(t),
18822
- "template-tag": (t) => chalk3.yellow(t),
18823
- "template-variable": (t) => chalk3.green(t),
19458
+ string: (t) => chalk4.yellow(t),
19459
+ "template-tag": (t) => chalk4.yellow(t),
19460
+ "template-variable": (t) => chalk4.green(t),
18824
19461
  // Numbers
18825
- number: (t) => chalk3.magenta(t),
19462
+ number: (t) => chalk4.magenta(t),
18826
19463
  // Literals (true, false, null)
18827
- literal: (t) => chalk3.magenta(t),
19464
+ literal: (t) => chalk4.magenta(t),
18828
19465
  // Comments
18829
- comment: (t) => chalk3.dim(t),
18830
- doctag: (t) => chalk3.dim.bold(t),
19466
+ comment: (t) => chalk4.dim(t),
19467
+ doctag: (t) => chalk4.dim.bold(t),
18831
19468
  // Regular expressions
18832
- regexp: (t) => chalk3.red(t),
19469
+ regexp: (t) => chalk4.red(t),
18833
19470
  // Attributes & properties
18834
- attr: (t) => chalk3.cyan(t),
18835
- attribute: (t) => chalk3.cyan(t),
18836
- property: (t) => chalk3.white(t),
19471
+ attr: (t) => chalk4.cyan(t),
19472
+ attribute: (t) => chalk4.cyan(t),
19473
+ property: (t) => chalk4.white(t),
18837
19474
  // Operators & punctuation
18838
- operator: (t) => chalk3.dim.white(t),
18839
- punctuation: (t) => chalk3.dim.white(t),
19475
+ operator: (t) => chalk4.dim.white(t),
19476
+ punctuation: (t) => chalk4.dim.white(t),
18840
19477
  // Meta / preprocessor
18841
- meta: (t) => chalk3.dim(t),
18842
- "meta keyword": (t) => chalk3.blue(t),
18843
- "meta string": (t) => chalk3.yellow(t),
19478
+ meta: (t) => chalk4.dim(t),
19479
+ "meta keyword": (t) => chalk4.blue(t),
19480
+ "meta string": (t) => chalk4.yellow(t),
18844
19481
  // Variables & params
18845
- variable: (t) => chalk3.white(t),
18846
- "variable.language": (t) => chalk3.blue(t),
18847
- params: (t) => chalk3.white(t),
19482
+ variable: (t) => chalk4.white(t),
19483
+ "variable.language": (t) => chalk4.blue(t),
19484
+ params: (t) => chalk4.white(t),
18848
19485
  // Tags (HTML/XML)
18849
- tag: (t) => chalk3.blue(t),
18850
- name: (t) => chalk3.blue(t),
19486
+ tag: (t) => chalk4.blue(t),
19487
+ name: (t) => chalk4.blue(t),
18851
19488
  // Symbols & selectors (CSS, Ruby)
18852
- symbol: (t) => chalk3.magenta(t),
18853
- selector: (t) => chalk3.green(t),
18854
- "selector-tag": (t) => chalk3.blue(t),
18855
- "selector-class": (t) => chalk3.green(t),
18856
- "selector-id": (t) => chalk3.cyan(t),
19489
+ symbol: (t) => chalk4.magenta(t),
19490
+ selector: (t) => chalk4.green(t),
19491
+ "selector-tag": (t) => chalk4.blue(t),
19492
+ "selector-class": (t) => chalk4.green(t),
19493
+ "selector-id": (t) => chalk4.cyan(t),
18857
19494
  // Additions/deletions (diffs)
18858
- addition: (t) => chalk3.green(t),
18859
- deletion: (t) => chalk3.red(t),
19495
+ addition: (t) => chalk4.green(t),
19496
+ deletion: (t) => chalk4.red(t),
18860
19497
  // Section headers
18861
- section: (t) => chalk3.bold(t),
19498
+ section: (t) => chalk4.bold(t),
18862
19499
  // Emphasis
18863
- emphasis: (t) => chalk3.italic(t),
18864
- strong: (t) => chalk3.bold(t)
19500
+ emphasis: (t) => chalk4.italic(t),
19501
+ strong: (t) => chalk4.bold(t)
18865
19502
  };
18866
19503
  function hljsToChalk(html) {
18867
19504
  const safeSpans = [];
@@ -18916,10 +19553,10 @@ function highlightLine(line, lang) {
18916
19553
  }
18917
19554
 
18918
19555
  // src/cli/repl/output/diff-renderer.ts
18919
- var bgDeleteLine = chalk3.bgRgb(80, 20, 20);
18920
- var bgAddLine = chalk3.bgRgb(20, 60, 20);
18921
- var bgDeleteWord = chalk3.bgRgb(160, 40, 40);
18922
- var bgAddWord = chalk3.bgRgb(40, 120, 40);
19556
+ var bgDeleteLine = chalk4.bgRgb(80, 20, 20);
19557
+ var bgAddLine = chalk4.bgRgb(20, 60, 20);
19558
+ var bgDeleteWord = chalk4.bgRgb(160, 40, 40);
19559
+ var bgAddWord = chalk4.bgRgb(40, 120, 40);
18923
19560
  function parseDiff(raw) {
18924
19561
  const files = [];
18925
19562
  const lines = raw.split("\n");
@@ -19116,7 +19753,7 @@ function renderDiff(diff, options) {
19116
19753
  const maxWidth = options?.maxWidth ?? Math.min(getTerminalWidth() - 2, 120);
19117
19754
  const compact = options?.compact ?? false;
19118
19755
  if (diff.files.length === 0) {
19119
- console.log(chalk3.dim("\n No changes\n"));
19756
+ console.log(chalk4.dim("\n No changes\n"));
19120
19757
  return;
19121
19758
  }
19122
19759
  for (const file of diff.files) {
@@ -19125,9 +19762,9 @@ function renderDiff(diff, options) {
19125
19762
  const { stats } = diff;
19126
19763
  const parts = [];
19127
19764
  parts.push(`${stats.filesChanged} file${stats.filesChanged !== 1 ? "s" : ""}`);
19128
- if (stats.additions > 0) parts.push(chalk3.green(`+${stats.additions}`));
19129
- if (stats.deletions > 0) parts.push(chalk3.red(`-${stats.deletions}`));
19130
- console.log(chalk3.dim(`
19765
+ if (stats.additions > 0) parts.push(chalk4.green(`+${stats.additions}`));
19766
+ if (stats.deletions > 0) parts.push(chalk4.red(`-${stats.deletions}`));
19767
+ console.log(chalk4.dim(`
19131
19768
  ${parts.join(", ")}
19132
19769
  `));
19133
19770
  }
@@ -19140,22 +19777,22 @@ function renderFileBlock(file, opts) {
19140
19777
  const title = ` ${file.path} (${typeLabel}${statsLabel}) `;
19141
19778
  const topFill = Math.max(0, maxWidth - 2 - stripAnsi(title).length);
19142
19779
  console.log(
19143
- chalk3.magenta("\u256D\u2500\u2500") + chalk3.cyan.bold(title) + chalk3.magenta("\u2500".repeat(topFill) + "\u256E")
19780
+ chalk4.magenta("\u256D\u2500\u2500") + chalk4.cyan.bold(title) + chalk4.magenta("\u2500".repeat(topFill) + "\u256E")
19144
19781
  );
19145
19782
  for (let h = 0; h < file.hunks.length; h++) {
19146
19783
  const hunk = file.hunks[h];
19147
19784
  if (!compact || h > 0) {
19148
- const hunkLabel = hunk.heading ? ` ${chalk3.dim(hunk.heading)}` : "";
19785
+ const hunkLabel = hunk.heading ? ` ${chalk4.dim(hunk.heading)}` : "";
19149
19786
  console.log(
19150
- chalk3.magenta("\u2502") + " " + chalk3.cyan(
19787
+ chalk4.magenta("\u2502") + " " + chalk4.cyan(
19151
19788
  `@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`
19152
19789
  ) + hunkLabel
19153
19790
  );
19154
19791
  }
19155
19792
  const pairs = pairAdjacentLines(hunk.lines);
19156
- const pairedDeleteIndices = new Set(pairs.map((p4) => p4.deleteIdx));
19157
- const pairedAddIndices = new Set(pairs.map((p4) => p4.addIdx));
19158
- const pairByAdd = new Map(pairs.map((p4) => [p4.addIdx, p4.deleteIdx]));
19793
+ const pairedDeleteIndices = new Set(pairs.map((p5) => p5.deleteIdx));
19794
+ const pairedAddIndices = new Set(pairs.map((p5) => p5.addIdx));
19795
+ const pairByAdd = new Map(pairs.map((p5) => [p5.addIdx, p5.deleteIdx]));
19159
19796
  const wordHighlights = /* @__PURE__ */ new Map();
19160
19797
  for (const pair of pairs) {
19161
19798
  const delLine = hunk.lines[pair.deleteIdx];
@@ -19179,7 +19816,7 @@ function renderFileBlock(file, opts) {
19179
19816
  const plainLen = stripAnsi(innerText).length + 1;
19180
19817
  const pad = Math.max(0, contentWidth - plainLen);
19181
19818
  console.log(
19182
- chalk3.magenta("\u2502") + bgAddLine(` ${innerText}` + " ".repeat(pad + 2)) + chalk3.magenta("\u2502")
19819
+ chalk4.magenta("\u2502") + bgAddLine(` ${innerText}` + " ".repeat(pad + 2)) + chalk4.magenta("\u2502")
19183
19820
  );
19184
19821
  } else if (line.type === "delete") {
19185
19822
  const isPaired = pairedDeleteIndices.has(li);
@@ -19193,7 +19830,7 @@ function renderFileBlock(file, opts) {
19193
19830
  const plainLen = stripAnsi(innerText).length + 1;
19194
19831
  const pad = Math.max(0, contentWidth - plainLen);
19195
19832
  console.log(
19196
- chalk3.magenta("\u2502") + bgDeleteLine(` ${innerText}` + " ".repeat(pad + 2)) + chalk3.magenta("\u2502")
19833
+ chalk4.magenta("\u2502") + bgDeleteLine(` ${innerText}` + " ".repeat(pad + 2)) + chalk4.magenta("\u2502")
19197
19834
  );
19198
19835
  } else {
19199
19836
  let content = line.content;
@@ -19204,17 +19841,17 @@ function renderFileBlock(file, opts) {
19204
19841
  const plainLen = stripAnsi(lineStr).length;
19205
19842
  const pad = Math.max(0, contentWidth - plainLen);
19206
19843
  console.log(
19207
- chalk3.magenta("\u2502") + chalk3.dim(` ${lineStr}`) + " ".repeat(pad) + " " + chalk3.magenta("\u2502")
19844
+ chalk4.magenta("\u2502") + chalk4.dim(` ${lineStr}`) + " ".repeat(pad) + " " + chalk4.magenta("\u2502")
19208
19845
  );
19209
19846
  }
19210
19847
  }
19211
19848
  }
19212
- console.log(chalk3.magenta("\u2570" + "\u2500".repeat(Math.max(0, maxWidth - 2)) + "\u256F"));
19849
+ console.log(chalk4.magenta("\u2570" + "\u2500".repeat(Math.max(0, maxWidth - 2)) + "\u256F"));
19213
19850
  }
19214
19851
  function formatLineNo(line, show) {
19215
19852
  if (!show) return "";
19216
19853
  const lineNo = line.type === "delete" ? line.oldLineNo : line.newLineNo;
19217
- return chalk3.dim(`${String(lineNo ?? "").padStart(5)} `);
19854
+ return chalk4.dim(`${String(lineNo ?? "").padStart(5)} `);
19218
19855
  }
19219
19856
  function getChangedLines(diff) {
19220
19857
  const result = /* @__PURE__ */ new Map();
@@ -19313,15 +19950,15 @@ Examples:
19313
19950
  var diffTools = [showDiffTool];
19314
19951
  async function fileExists(filePath) {
19315
19952
  try {
19316
- await fs15__default.access(filePath);
19953
+ await fs16__default.access(filePath);
19317
19954
  return true;
19318
19955
  } catch {
19319
19956
  return false;
19320
19957
  }
19321
19958
  }
19322
- async function fileExists2(path39) {
19959
+ async function fileExists2(path40) {
19323
19960
  try {
19324
- await access(path39);
19961
+ await access(path40);
19325
19962
  return true;
19326
19963
  } catch {
19327
19964
  return false;
@@ -19411,7 +20048,7 @@ async function detectMaturity(cwd) {
19411
20048
  if (!hasLintConfig && hasPackageJson) {
19412
20049
  try {
19413
20050
  const pkgRaw = await import('fs/promises').then(
19414
- (fs37) => fs37.readFile(join(cwd, "package.json"), "utf-8")
20051
+ (fs38) => fs38.readFile(join(cwd, "package.json"), "utf-8")
19415
20052
  );
19416
20053
  const pkg = JSON.parse(pkgRaw);
19417
20054
  if (pkg.scripts?.lint || pkg.scripts?.["lint:fix"]) {
@@ -19580,7 +20217,7 @@ async function checkTestCoverage(diff, cwd) {
19580
20217
  );
19581
20218
  if (!hasTestChange) {
19582
20219
  const ext = src.path.match(/\.(ts|tsx|js|jsx)$/)?.[0] ?? ".ts";
19583
- const testExists = await fileExists(path16__default.join(cwd, `${baseName}.test${ext}`)) || await fileExists(path16__default.join(cwd, `${baseName}.spec${ext}`));
20220
+ const testExists = await fileExists(path17__default.join(cwd, `${baseName}.test${ext}`)) || await fileExists(path17__default.join(cwd, `${baseName}.spec${ext}`));
19584
20221
  if (testExists) {
19585
20222
  if (src.additions >= TEST_COVERAGE_LARGE_CHANGE_THRESHOLD) {
19586
20223
  findings.push({
@@ -19811,8 +20448,8 @@ Examples:
19811
20448
  }
19812
20449
  });
19813
20450
  var reviewTools = [reviewCodeTool];
19814
- var fs24 = await import('fs/promises');
19815
- var path26 = await import('path');
20451
+ var fs25 = await import('fs/promises');
20452
+ var path27 = await import('path');
19816
20453
  var { glob: glob14 } = await import('glob');
19817
20454
  var DEFAULT_MAX_FILES = 200;
19818
20455
  var LANGUAGE_EXTENSIONS = {
@@ -19838,7 +20475,7 @@ var DEFAULT_EXCLUDES = [
19838
20475
  "**/*.d.ts"
19839
20476
  ];
19840
20477
  function detectLanguage3(filePath) {
19841
- const ext = path26.extname(filePath).toLowerCase();
20478
+ const ext = path27.extname(filePath).toLowerCase();
19842
20479
  for (const [lang, extensions] of Object.entries(LANGUAGE_EXTENSIONS)) {
19843
20480
  if (extensions.includes(ext)) return lang;
19844
20481
  }
@@ -20247,9 +20884,9 @@ Examples:
20247
20884
  }),
20248
20885
  async execute({ path: rootPath, include, exclude, languages, maxFiles, depth }) {
20249
20886
  const startTime = performance.now();
20250
- const absPath = path26.resolve(rootPath);
20887
+ const absPath = path27.resolve(rootPath);
20251
20888
  try {
20252
- const stat2 = await fs24.stat(absPath);
20889
+ const stat2 = await fs25.stat(absPath);
20253
20890
  if (!stat2.isDirectory()) {
20254
20891
  throw new ToolError(`Path is not a directory: ${absPath}`, {
20255
20892
  tool: "codebase_map"
@@ -20286,14 +20923,14 @@ Examples:
20286
20923
  let totalDefinitions = 0;
20287
20924
  let exportedSymbols = 0;
20288
20925
  for (const file of limitedFiles) {
20289
- const fullPath = path26.join(absPath, file);
20926
+ const fullPath = path27.join(absPath, file);
20290
20927
  const language = detectLanguage3(file);
20291
20928
  if (!language) continue;
20292
20929
  if (languages && !languages.includes(language)) {
20293
20930
  continue;
20294
20931
  }
20295
20932
  try {
20296
- const content = await fs24.readFile(fullPath, "utf-8");
20933
+ const content = await fs25.readFile(fullPath, "utf-8");
20297
20934
  const lineCount = content.split("\n").length;
20298
20935
  const parsed = parseFile(content, language);
20299
20936
  const definitions = depth === "overview" ? parsed.definitions.filter((d) => d.exported) : parsed.definitions;
@@ -20326,23 +20963,23 @@ Examples:
20326
20963
  });
20327
20964
  var codebaseMapTools = [codebaseMapTool];
20328
20965
  init_paths();
20329
- var fs25 = await import('fs/promises');
20330
- var path27 = await import('path');
20966
+ var fs26 = await import('fs/promises');
20967
+ var path28 = await import('path');
20331
20968
  var crypto2 = await import('crypto');
20332
- var GLOBAL_MEMORIES_DIR = path27.join(COCO_HOME, "memories");
20969
+ var GLOBAL_MEMORIES_DIR = path28.join(COCO_HOME, "memories");
20333
20970
  var PROJECT_MEMORIES_DIR = ".coco/memories";
20334
20971
  var DEFAULT_MAX_MEMORIES = 1e3;
20335
20972
  async function ensureDir(dirPath) {
20336
- await fs25.mkdir(dirPath, { recursive: true });
20973
+ await fs26.mkdir(dirPath, { recursive: true });
20337
20974
  }
20338
20975
  function getMemoriesDir(scope) {
20339
20976
  return scope === "global" ? GLOBAL_MEMORIES_DIR : PROJECT_MEMORIES_DIR;
20340
20977
  }
20341
20978
  async function loadIndex(scope) {
20342
20979
  const dir = getMemoriesDir(scope);
20343
- const indexPath = path27.join(dir, "index.json");
20980
+ const indexPath = path28.join(dir, "index.json");
20344
20981
  try {
20345
- const content = await fs25.readFile(indexPath, "utf-8");
20982
+ const content = await fs26.readFile(indexPath, "utf-8");
20346
20983
  return JSON.parse(content);
20347
20984
  } catch {
20348
20985
  return [];
@@ -20351,14 +20988,14 @@ async function loadIndex(scope) {
20351
20988
  async function saveIndex(scope, index) {
20352
20989
  const dir = getMemoriesDir(scope);
20353
20990
  await ensureDir(dir);
20354
- const indexPath = path27.join(dir, "index.json");
20355
- await fs25.writeFile(indexPath, JSON.stringify(index, null, 2), "utf-8");
20991
+ const indexPath = path28.join(dir, "index.json");
20992
+ await fs26.writeFile(indexPath, JSON.stringify(index, null, 2), "utf-8");
20356
20993
  }
20357
20994
  async function loadMemory(scope, id) {
20358
20995
  const dir = getMemoriesDir(scope);
20359
- const memPath = path27.join(dir, `${id}.json`);
20996
+ const memPath = path28.join(dir, `${id}.json`);
20360
20997
  try {
20361
- const content = await fs25.readFile(memPath, "utf-8");
20998
+ const content = await fs26.readFile(memPath, "utf-8");
20362
20999
  return JSON.parse(content);
20363
21000
  } catch {
20364
21001
  return null;
@@ -20367,8 +21004,8 @@ async function loadMemory(scope, id) {
20367
21004
  async function saveMemory(scope, memory) {
20368
21005
  const dir = getMemoriesDir(scope);
20369
21006
  await ensureDir(dir);
20370
- const memPath = path27.join(dir, `${memory.id}.json`);
20371
- await fs25.writeFile(memPath, JSON.stringify(memory, null, 2), "utf-8");
21007
+ const memPath = path28.join(dir, `${memory.id}.json`);
21008
+ await fs26.writeFile(memPath, JSON.stringify(memory, null, 2), "utf-8");
20372
21009
  }
20373
21010
  var createMemoryTool = defineTool({
20374
21011
  name: "create_memory",
@@ -20520,17 +21157,17 @@ Examples:
20520
21157
  }
20521
21158
  });
20522
21159
  var memoryTools = [createMemoryTool, recallMemoryTool, listMemoriesTool];
20523
- var fs26 = await import('fs/promises');
21160
+ var fs27 = await import('fs/promises');
20524
21161
  var crypto3 = await import('crypto');
20525
21162
  var CHECKPOINT_FILE = ".coco/checkpoints.json";
20526
21163
  var DEFAULT_MAX_CHECKPOINTS = 50;
20527
21164
  var STASH_PREFIX = "coco-cp";
20528
21165
  async function ensureCocoDir() {
20529
- await fs26.mkdir(".coco", { recursive: true });
21166
+ await fs27.mkdir(".coco", { recursive: true });
20530
21167
  }
20531
21168
  async function loadCheckpoints() {
20532
21169
  try {
20533
- const content = await fs26.readFile(CHECKPOINT_FILE, "utf-8");
21170
+ const content = await fs27.readFile(CHECKPOINT_FILE, "utf-8");
20534
21171
  return JSON.parse(content);
20535
21172
  } catch {
20536
21173
  return [];
@@ -20538,7 +21175,7 @@ async function loadCheckpoints() {
20538
21175
  }
20539
21176
  async function saveCheckpoints(checkpoints) {
20540
21177
  await ensureCocoDir();
20541
- await fs26.writeFile(CHECKPOINT_FILE, JSON.stringify(checkpoints, null, 2), "utf-8");
21178
+ await fs27.writeFile(CHECKPOINT_FILE, JSON.stringify(checkpoints, null, 2), "utf-8");
20542
21179
  }
20543
21180
  async function execGit(args) {
20544
21181
  const { execaCommand } = await import('execa');
@@ -20700,8 +21337,8 @@ Examples:
20700
21337
  }
20701
21338
  });
20702
21339
  var checkpointTools = [createCheckpointTool, restoreCheckpointTool, listCheckpointsTool];
20703
- var fs27 = await import('fs/promises');
20704
- var path28 = await import('path');
21340
+ var fs28 = await import('fs/promises');
21341
+ var path29 = await import('path');
20705
21342
  var { glob: glob15 } = await import('glob');
20706
21343
  var INDEX_DIR = ".coco/search-index";
20707
21344
  var DEFAULT_CHUNK_SIZE = 20;
@@ -20829,20 +21466,20 @@ async function getEmbedding(text) {
20829
21466
  }
20830
21467
  async function loadIndex2(indexDir) {
20831
21468
  try {
20832
- const indexPath = path28.join(indexDir, "index.json");
20833
- const content = await fs27.readFile(indexPath, "utf-8");
21469
+ const indexPath = path29.join(indexDir, "index.json");
21470
+ const content = await fs28.readFile(indexPath, "utf-8");
20834
21471
  return JSON.parse(content);
20835
21472
  } catch {
20836
21473
  return null;
20837
21474
  }
20838
21475
  }
20839
21476
  async function saveIndex2(indexDir, index) {
20840
- await fs27.mkdir(indexDir, { recursive: true });
20841
- const indexPath = path28.join(indexDir, "index.json");
20842
- await fs27.writeFile(indexPath, JSON.stringify(index), "utf-8");
21477
+ await fs28.mkdir(indexDir, { recursive: true });
21478
+ const indexPath = path29.join(indexDir, "index.json");
21479
+ await fs28.writeFile(indexPath, JSON.stringify(index), "utf-8");
20843
21480
  }
20844
21481
  function isBinary(filePath) {
20845
- return BINARY_EXTENSIONS.has(path28.extname(filePath).toLowerCase());
21482
+ return BINARY_EXTENSIONS.has(path29.extname(filePath).toLowerCase());
20846
21483
  }
20847
21484
  var semanticSearchTool = defineTool({
20848
21485
  name: "semantic_search",
@@ -20867,8 +21504,8 @@ Examples:
20867
21504
  const effectivePath = rootPath ?? ".";
20868
21505
  const effectiveMaxResults = maxResults ?? 10;
20869
21506
  const effectiveThreshold = threshold ?? 0.3;
20870
- const absPath = path28.resolve(effectivePath);
20871
- const indexDir = path28.join(absPath, INDEX_DIR);
21507
+ const absPath = path29.resolve(effectivePath);
21508
+ const indexDir = path29.join(absPath, INDEX_DIR);
20872
21509
  let index = reindex ? null : await loadIndex2(indexDir);
20873
21510
  let warnings = [];
20874
21511
  if (!index) {
@@ -20884,10 +21521,10 @@ Examples:
20884
21521
  let indexSaveWarning = "";
20885
21522
  for (const file of files) {
20886
21523
  if (isBinary(file)) continue;
20887
- const fullPath = path28.join(absPath, file);
21524
+ const fullPath = path29.join(absPath, file);
20888
21525
  try {
20889
- const stat2 = await fs27.stat(fullPath);
20890
- const content = await fs27.readFile(fullPath, "utf-8");
21526
+ const stat2 = await fs28.stat(fullPath);
21527
+ const content = await fs28.readFile(fullPath, "utf-8");
20891
21528
  if (content.length > 1e5) continue;
20892
21529
  const fileChunks = chunkContent(content, DEFAULT_CHUNK_SIZE);
20893
21530
  for (const chunk of fileChunks) {
@@ -20963,8 +21600,8 @@ Examples:
20963
21600
  }
20964
21601
  });
20965
21602
  var semanticSearchTools = [semanticSearchTool];
20966
- var fs28 = await import('fs/promises');
20967
- var path29 = await import('path');
21603
+ var fs29 = await import('fs/promises');
21604
+ var path30 = await import('path');
20968
21605
  var { glob: glob16 } = await import('glob');
20969
21606
  async function parseClassRelationships(rootPath, include) {
20970
21607
  const pattern = include ?? "**/*.{ts,tsx,js,jsx}";
@@ -20977,7 +21614,7 @@ async function parseClassRelationships(rootPath, include) {
20977
21614
  const interfaces = [];
20978
21615
  for (const file of files.slice(0, 100)) {
20979
21616
  try {
20980
- const content = await fs28.readFile(path29.join(rootPath, file), "utf-8");
21617
+ const content = await fs29.readFile(path30.join(rootPath, file), "utf-8");
20981
21618
  const lines = content.split("\n");
20982
21619
  for (let i = 0; i < lines.length; i++) {
20983
21620
  const line = lines[i];
@@ -21096,14 +21733,14 @@ async function generateClassDiagram(rootPath, include) {
21096
21733
  };
21097
21734
  }
21098
21735
  async function generateArchitectureDiagram(rootPath) {
21099
- const entries = await fs28.readdir(rootPath, { withFileTypes: true });
21736
+ const entries = await fs29.readdir(rootPath, { withFileTypes: true });
21100
21737
  const dirs = entries.filter(
21101
21738
  (e) => e.isDirectory() && !e.name.startsWith(".") && !["node_modules", "dist", "build", "coverage", "__pycache__", "target"].includes(e.name)
21102
21739
  );
21103
21740
  const lines = ["graph TD"];
21104
21741
  let nodeCount = 0;
21105
21742
  let edgeCount = 0;
21106
- const rootName = path29.basename(rootPath);
21743
+ const rootName = path30.basename(rootPath);
21107
21744
  lines.push(` ROOT["${rootName}"]`);
21108
21745
  nodeCount++;
21109
21746
  for (const dir of dirs) {
@@ -21113,7 +21750,7 @@ async function generateArchitectureDiagram(rootPath) {
21113
21750
  nodeCount++;
21114
21751
  edgeCount++;
21115
21752
  try {
21116
- const subEntries = await fs28.readdir(path29.join(rootPath, dir.name), {
21753
+ const subEntries = await fs29.readdir(path30.join(rootPath, dir.name), {
21117
21754
  withFileTypes: true
21118
21755
  });
21119
21756
  const subDirs = subEntries.filter(
@@ -21236,7 +21873,7 @@ Examples:
21236
21873
  tool: "generate_diagram"
21237
21874
  });
21238
21875
  }
21239
- const absPath = rootPath ? path29.resolve(rootPath) : process.cwd();
21876
+ const absPath = rootPath ? path30.resolve(rootPath) : process.cwd();
21240
21877
  switch (type) {
21241
21878
  case "class":
21242
21879
  return generateClassDiagram(absPath, include);
@@ -21297,8 +21934,8 @@ Examples:
21297
21934
  }
21298
21935
  });
21299
21936
  var diagramTools = [generateDiagramTool];
21300
- var fs29 = await import('fs/promises');
21301
- var path30 = await import('path');
21937
+ var fs30 = await import('fs/promises');
21938
+ var path31 = await import('path');
21302
21939
  var DEFAULT_MAX_PAGES = 20;
21303
21940
  var MAX_FILE_SIZE = 50 * 1024 * 1024;
21304
21941
  function parsePageRange(rangeStr, totalPages) {
@@ -21333,9 +21970,9 @@ Examples:
21333
21970
  }),
21334
21971
  async execute({ path: filePath, pages, maxPages }) {
21335
21972
  const startTime = performance.now();
21336
- const absPath = path30.resolve(filePath);
21973
+ const absPath = path31.resolve(filePath);
21337
21974
  try {
21338
- const stat2 = await fs29.stat(absPath);
21975
+ const stat2 = await fs30.stat(absPath);
21339
21976
  if (!stat2.isFile()) {
21340
21977
  throw new ToolError(`Path is not a file: ${absPath}`, {
21341
21978
  tool: "read_pdf"
@@ -21366,7 +22003,7 @@ Examples:
21366
22003
  }
21367
22004
  try {
21368
22005
  const pdfParse = await import('pdf-parse');
21369
- const dataBuffer = await fs29.readFile(absPath);
22006
+ const dataBuffer = await fs30.readFile(absPath);
21370
22007
  const pdfData = await pdfParse.default(dataBuffer, {
21371
22008
  max: maxPages
21372
22009
  });
@@ -21413,8 +22050,8 @@ Examples:
21413
22050
  }
21414
22051
  });
21415
22052
  var pdfTools = [readPdfTool];
21416
- var fs30 = await import('fs/promises');
21417
- var path31 = await import('path');
22053
+ var fs31 = await import('fs/promises');
22054
+ var path32 = await import('path');
21418
22055
  var SUPPORTED_FORMATS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp"]);
21419
22056
  var MAX_IMAGE_SIZE = 20 * 1024 * 1024;
21420
22057
  var MIME_TYPES = {
@@ -21442,15 +22079,15 @@ Examples:
21442
22079
  async execute({ path: filePath, prompt, provider }) {
21443
22080
  const startTime = performance.now();
21444
22081
  const effectivePrompt = prompt ?? "Describe this image in detail. If it's code or a UI, identify the key elements.";
21445
- const absPath = path31.resolve(filePath);
22082
+ const absPath = path32.resolve(filePath);
21446
22083
  const cwd = process.cwd();
21447
- if (!absPath.startsWith(cwd + path31.sep) && absPath !== cwd) {
22084
+ if (!absPath.startsWith(cwd + path32.sep) && absPath !== cwd) {
21448
22085
  throw new ToolError(
21449
22086
  `Path traversal denied: '${filePath}' resolves outside the project directory`,
21450
22087
  { tool: "read_image" }
21451
22088
  );
21452
22089
  }
21453
- const ext = path31.extname(absPath).toLowerCase();
22090
+ const ext = path32.extname(absPath).toLowerCase();
21454
22091
  if (!SUPPORTED_FORMATS.has(ext)) {
21455
22092
  throw new ToolError(
21456
22093
  `Unsupported image format '${ext}'. Supported: ${Array.from(SUPPORTED_FORMATS).join(", ")}`,
@@ -21458,7 +22095,7 @@ Examples:
21458
22095
  );
21459
22096
  }
21460
22097
  try {
21461
- const stat2 = await fs30.stat(absPath);
22098
+ const stat2 = await fs31.stat(absPath);
21462
22099
  if (!stat2.isFile()) {
21463
22100
  throw new ToolError(`Path is not a file: ${absPath}`, {
21464
22101
  tool: "read_image"
@@ -21479,7 +22116,7 @@ Examples:
21479
22116
  if (error instanceof ToolError) throw error;
21480
22117
  throw error;
21481
22118
  }
21482
- const imageBuffer = await fs30.readFile(absPath);
22119
+ const imageBuffer = await fs31.readFile(absPath);
21483
22120
  const base64 = imageBuffer.toString("base64");
21484
22121
  const mimeType = MIME_TYPES[ext] ?? "image/png";
21485
22122
  const selectedProvider = provider ?? "anthropic";
@@ -21516,8 +22153,8 @@ Examples:
21516
22153
  description = response.content.filter((block) => block.type === "text").map((block) => block.text).join("\n") || "No description generated";
21517
22154
  } else if (selectedProvider === "openai") {
21518
22155
  model = "gpt-4o";
21519
- const { default: OpenAI2 } = await import('openai');
21520
- const client = new OpenAI2();
22156
+ const { default: OpenAI3 } = await import('openai');
22157
+ const client = new OpenAI3();
21521
22158
  const openaiMessages = [
21522
22159
  {
21523
22160
  role: "user",
@@ -21597,7 +22234,7 @@ Examples:
21597
22234
  }
21598
22235
  });
21599
22236
  var imageTools = [readImageTool];
21600
- var path32 = await import('path');
22237
+ var path33 = await import('path');
21601
22238
  var DANGEROUS_PATTERNS = [
21602
22239
  /\bDROP\s+(?:TABLE|DATABASE|INDEX|VIEW)\b/i,
21603
22240
  /\bTRUNCATE\b/i,
@@ -21628,7 +22265,7 @@ Examples:
21628
22265
  async execute({ database, query, params, readonly: isReadonlyParam }) {
21629
22266
  const isReadonly = isReadonlyParam ?? true;
21630
22267
  const startTime = performance.now();
21631
- const absPath = path32.resolve(database);
22268
+ const absPath = path33.resolve(database);
21632
22269
  if (isReadonly && isDangerousSql(query)) {
21633
22270
  throw new ToolError(
21634
22271
  "Write operations (INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, CREATE) are blocked in readonly mode. Set readonly: false to allow writes.",
@@ -21711,7 +22348,7 @@ Examples:
21711
22348
  }),
21712
22349
  async execute({ database, table }) {
21713
22350
  const startTime = performance.now();
21714
- const absPath = path32.resolve(database);
22351
+ const absPath = path33.resolve(database);
21715
22352
  try {
21716
22353
  const { default: Database } = await import('better-sqlite3');
21717
22354
  const db = new Database(absPath, { readonly: true, fileMustExist: true });
@@ -21770,14 +22407,14 @@ Examples:
21770
22407
  }
21771
22408
  });
21772
22409
  var databaseTools = [sqlQueryTool, inspectSchemaTool];
21773
- var fs31 = await import('fs/promises');
21774
- var path33 = await import('path');
22410
+ var fs32 = await import('fs/promises');
22411
+ var path34 = await import('path');
21775
22412
  var AnalyzeFileSchema = z.object({
21776
22413
  filePath: z.string().describe("Path to file to analyze"),
21777
22414
  includeAst: z.boolean().default(false).describe("Include AST in result")
21778
22415
  });
21779
22416
  async function analyzeFile(filePath, includeAst = false) {
21780
- const content = await fs31.readFile(filePath, "utf-8");
22417
+ const content = await fs32.readFile(filePath, "utf-8");
21781
22418
  const lines = content.split("\n").length;
21782
22419
  const functions = [];
21783
22420
  const classes = [];
@@ -21881,10 +22518,10 @@ async function analyzeDirectory(dirPath) {
21881
22518
  try {
21882
22519
  const analysis = await analyzeFile(file, false);
21883
22520
  totalLines += analysis.lines;
21884
- const ext = path33.extname(file);
22521
+ const ext = path34.extname(file);
21885
22522
  filesByType[ext] = (filesByType[ext] || 0) + 1;
21886
22523
  fileStats.push({
21887
- file: path33.relative(dirPath, file),
22524
+ file: path34.relative(dirPath, file),
21888
22525
  lines: analysis.lines,
21889
22526
  complexity: analysis.complexity.cyclomatic
21890
22527
  });
@@ -22121,6 +22758,13 @@ var createAgentPlanTool = defineTool({
22121
22758
  };
22122
22759
  }
22123
22760
  });
22761
+ var LEGACY_ROLE_TO_TYPE = {
22762
+ researcher: "explore",
22763
+ coder: "debug",
22764
+ reviewer: "review",
22765
+ tester: "test",
22766
+ optimizer: "refactor"
22767
+ };
22124
22768
  var delegateTaskTool = defineTool({
22125
22769
  name: "delegateTask",
22126
22770
  description: "Delegate a task to a specialized sub-agent with real LLM tool-use execution.",
@@ -22128,22 +22772,57 @@ var delegateTaskTool = defineTool({
22128
22772
  parameters: z.object({
22129
22773
  taskId: z.string(),
22130
22774
  task: z.string().describe("Description of the task for the agent to execute"),
22131
- agentRole: z.enum(["researcher", "coder", "reviewer", "tester", "optimizer"]).default("coder"),
22775
+ agentType: z.enum([
22776
+ "explore",
22777
+ "plan",
22778
+ "test",
22779
+ "debug",
22780
+ "review",
22781
+ "architect",
22782
+ "security",
22783
+ "tdd",
22784
+ "refactor",
22785
+ "e2e",
22786
+ "docs",
22787
+ "database"
22788
+ ]).optional().describe("Specialized agent type to use"),
22789
+ agentRole: z.enum(["researcher", "coder", "reviewer", "tester", "optimizer"]).optional().describe("DEPRECATED: Use agentType instead"),
22132
22790
  context: z.string().optional(),
22133
22791
  maxTurns: z.number().default(10)
22134
22792
  }),
22135
22793
  async execute(input) {
22136
22794
  const typedInput = input;
22137
- {
22795
+ const manager = getAgentManager();
22796
+ if (!manager) {
22797
+ const resolvedType = typedInput.agentType ?? "explore";
22138
22798
  return {
22139
- agentId: `agent-${Date.now()}-${typedInput.agentRole}`,
22799
+ agentId: `agent-${Date.now()}-${resolvedType}`,
22140
22800
  taskId: typedInput.taskId,
22141
- role: typedInput.agentRole,
22801
+ agentType: resolvedType,
22142
22802
  status: "unavailable",
22143
22803
  message: "Agent provider not initialized. Call setAgentProvider() during orchestrator startup.",
22144
22804
  success: false
22145
22805
  };
22146
22806
  }
22807
+ const agentType = typedInput.agentType ?? (typedInput.agentRole ? LEGACY_ROLE_TO_TYPE[typedInput.agentRole] ?? "explore" : "explore");
22808
+ const taskDescription = typedInput.context ? `${typedInput.task}
22809
+
22810
+ Additional context: ${typedInput.context}` : typedInput.task;
22811
+ const startTime = Date.now();
22812
+ const result = await manager.spawn(agentType, taskDescription, {
22813
+ timeout: typedInput.maxTurns * 6e4
22814
+ });
22815
+ const duration = Date.now() - startTime;
22816
+ return {
22817
+ agentId: result.agent.id,
22818
+ taskId: typedInput.taskId,
22819
+ agentType,
22820
+ status: result.success ? "completed" : "failed",
22821
+ output: result.output,
22822
+ success: result.success,
22823
+ usage: result.usage,
22824
+ duration
22825
+ };
22147
22826
  }
22148
22827
  });
22149
22828
  var aggregateResultsTool = defineTool({
@@ -22207,13 +22886,13 @@ ${completed.map((r) => `- ${r.agentId}: Success`).join("\n")}`;
22207
22886
  }
22208
22887
  });
22209
22888
  var agentCoordinatorTools = [createAgentPlanTool, delegateTaskTool, aggregateResultsTool];
22210
- var fs32 = await import('fs/promises');
22889
+ var fs33 = await import('fs/promises');
22211
22890
  var SuggestImprovementsSchema = z.object({
22212
22891
  filePath: z.string().describe("File to analyze for improvement suggestions"),
22213
22892
  context: z.string().optional().describe("Additional context about the code")
22214
22893
  });
22215
22894
  async function analyzeAndSuggest(filePath, _context) {
22216
- const content = await fs32.readFile(filePath, "utf-8");
22895
+ const content = await fs33.readFile(filePath, "utf-8");
22217
22896
  const lines = content.split("\n");
22218
22897
  const suggestions = [];
22219
22898
  for (let i = 0; i < lines.length; i++) {
@@ -22305,7 +22984,7 @@ async function analyzeAndSuggest(filePath, _context) {
22305
22984
  if (filePath.endsWith(".ts") && !filePath.includes("test") && !filePath.includes(".d.ts") && line.includes("export ")) {
22306
22985
  const testPath = filePath.replace(".ts", ".test.ts");
22307
22986
  try {
22308
- await fs32.access(testPath);
22987
+ await fs33.access(testPath);
22309
22988
  } catch {
22310
22989
  suggestions.push({
22311
22990
  type: "testing",
@@ -22362,7 +23041,7 @@ var calculateCodeScoreTool = defineTool({
22362
23041
  async execute(input) {
22363
23042
  const { filePath } = input;
22364
23043
  const suggestions = await analyzeAndSuggest(filePath);
22365
- const content = await fs32.readFile(filePath, "utf-8");
23044
+ const content = await fs33.readFile(filePath, "utf-8");
22366
23045
  const lines = content.split("\n");
22367
23046
  const nonEmptyLines = lines.filter((l) => l.trim()).length;
22368
23047
  let score = 100;
@@ -22396,8 +23075,8 @@ var calculateCodeScoreTool = defineTool({
22396
23075
  }
22397
23076
  });
22398
23077
  var smartSuggestionsTools = [suggestImprovementsTool, calculateCodeScoreTool];
22399
- var fs33 = await import('fs/promises');
22400
- var path34 = await import('path');
23078
+ var fs34 = await import('fs/promises');
23079
+ var path35 = await import('path');
22401
23080
  var ContextMemoryStore = class {
22402
23081
  items = /* @__PURE__ */ new Map();
22403
23082
  learnings = /* @__PURE__ */ new Map();
@@ -22409,7 +23088,7 @@ var ContextMemoryStore = class {
22409
23088
  }
22410
23089
  async load() {
22411
23090
  try {
22412
- const content = await fs33.readFile(this.storePath, "utf-8");
23091
+ const content = await fs34.readFile(this.storePath, "utf-8");
22413
23092
  const data = JSON.parse(content);
22414
23093
  this.items = new Map(Object.entries(data.items || {}));
22415
23094
  this.learnings = new Map(Object.entries(data.learnings || {}));
@@ -22417,15 +23096,15 @@ var ContextMemoryStore = class {
22417
23096
  }
22418
23097
  }
22419
23098
  async save() {
22420
- const dir = path34.dirname(this.storePath);
22421
- await fs33.mkdir(dir, { recursive: true });
23099
+ const dir = path35.dirname(this.storePath);
23100
+ await fs34.mkdir(dir, { recursive: true });
22422
23101
  const data = {
22423
23102
  sessionId: this.sessionId,
22424
23103
  items: Object.fromEntries(this.items),
22425
23104
  learnings: Object.fromEntries(this.learnings),
22426
23105
  savedAt: Date.now()
22427
23106
  };
22428
- await fs33.writeFile(this.storePath, JSON.stringify(data, null, 2));
23107
+ await fs34.writeFile(this.storePath, JSON.stringify(data, null, 2));
22429
23108
  }
22430
23109
  addContext(id, item) {
22431
23110
  this.items.set(id, item);
@@ -22575,11 +23254,11 @@ var getLearnedPatternsTool = defineTool({
22575
23254
  const patterns = store.getFrequentPatterns(typedInput.limit);
22576
23255
  return {
22577
23256
  totalPatterns: patterns.length,
22578
- patterns: patterns.map((p4) => ({
22579
- pattern: p4.pattern,
22580
- preference: p4.userPreference,
22581
- frequency: p4.frequency,
22582
- lastUsed: new Date(p4.lastUsed).toISOString()
23257
+ patterns: patterns.map((p5) => ({
23258
+ pattern: p5.pattern,
23259
+ preference: p5.userPreference,
23260
+ frequency: p5.frequency,
23261
+ lastUsed: new Date(p5.lastUsed).toISOString()
22583
23262
  }))
22584
23263
  };
22585
23264
  }
@@ -22590,11 +23269,11 @@ var contextEnhancerTools = [
22590
23269
  recordLearningTool,
22591
23270
  getLearnedPatternsTool
22592
23271
  ];
22593
- var fs34 = await import('fs/promises');
22594
- var path35 = await import('path');
23272
+ var fs35 = await import('fs/promises');
23273
+ var path36 = await import('path');
22595
23274
  async function discoverSkills(skillsDir) {
22596
23275
  try {
22597
- const files = await fs34.readdir(skillsDir);
23276
+ const files = await fs35.readdir(skillsDir);
22598
23277
  return files.filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
22599
23278
  } catch {
22600
23279
  return [];
@@ -22602,12 +23281,12 @@ async function discoverSkills(skillsDir) {
22602
23281
  }
22603
23282
  async function loadSkillMetadata(skillPath) {
22604
23283
  try {
22605
- const content = await fs34.readFile(skillPath, "utf-8");
23284
+ const content = await fs35.readFile(skillPath, "utf-8");
22606
23285
  const nameMatch = content.match(/@name\s+(\S+)/);
22607
23286
  const descMatch = content.match(/@description\s+(.+)/);
22608
23287
  const versionMatch = content.match(/@version\s+(\S+)/);
22609
23288
  return {
22610
- name: nameMatch?.[1] || path35.basename(skillPath, path35.extname(skillPath)),
23289
+ name: nameMatch?.[1] || path36.basename(skillPath, path36.extname(skillPath)),
22611
23290
  description: descMatch?.[1] || "No description",
22612
23291
  version: versionMatch?.[1] || "1.0.0",
22613
23292
  dependencies: []
@@ -22651,7 +23330,7 @@ var discoverSkillsTool = defineTool({
22651
23330
  const { skillsDir } = input;
22652
23331
  const skills = await discoverSkills(skillsDir);
22653
23332
  const metadata = await Promise.all(
22654
- skills.map((s) => loadSkillMetadata(path35.join(skillsDir, s)))
23333
+ skills.map((s) => loadSkillMetadata(path36.join(skillsDir, s)))
22655
23334
  );
22656
23335
  return {
22657
23336
  skillsDir,
@@ -23152,26 +23831,26 @@ function hasNullByte2(str) {
23152
23831
  }
23153
23832
  function isBlockedPath(absolute) {
23154
23833
  for (const blocked of BLOCKED_PATHS2) {
23155
- const normalizedBlocked = path16__default.normalize(blocked);
23156
- if (absolute === normalizedBlocked || absolute.startsWith(normalizedBlocked + path16__default.sep)) {
23834
+ const normalizedBlocked = path17__default.normalize(blocked);
23835
+ if (absolute === normalizedBlocked || absolute.startsWith(normalizedBlocked + path17__default.sep)) {
23157
23836
  return blocked;
23158
23837
  }
23159
23838
  }
23160
23839
  return void 0;
23161
23840
  }
23162
23841
  function isBlockedExecFile(filePath) {
23163
- return BLOCKED_EXEC_PATTERNS.some((p4) => p4.test(filePath));
23842
+ return BLOCKED_EXEC_PATTERNS.some((p5) => p5.test(filePath));
23164
23843
  }
23165
23844
  function hasDangerousArgs(args) {
23166
23845
  const joined = args.join(" ");
23167
- return DANGEROUS_ARG_PATTERNS.some((p4) => p4.test(joined));
23846
+ return DANGEROUS_ARG_PATTERNS.some((p5) => p5.test(joined));
23168
23847
  }
23169
23848
  function getInterpreter(ext) {
23170
23849
  return INTERPRETER_MAP[ext.toLowerCase()];
23171
23850
  }
23172
23851
  async function isExecutable(filePath) {
23173
23852
  try {
23174
- await fs15__default.access(filePath, fs15__default.constants.X_OK);
23853
+ await fs16__default.access(filePath, fs16__default.constants.X_OK);
23175
23854
  return true;
23176
23855
  } catch {
23177
23856
  return false;
@@ -23211,7 +23890,7 @@ Examples:
23211
23890
  throw new ToolError("Invalid file path", { tool: "open_file" });
23212
23891
  }
23213
23892
  const workDir = cwd ?? process.cwd();
23214
- const absolute = path16__default.isAbsolute(filePath) ? path16__default.normalize(filePath) : path16__default.resolve(workDir, filePath);
23893
+ const absolute = path17__default.isAbsolute(filePath) ? path17__default.normalize(filePath) : path17__default.resolve(workDir, filePath);
23215
23894
  const blockedBy = isBlockedPath(absolute);
23216
23895
  if (blockedBy) {
23217
23896
  throw new ToolError(`Access to system path '${blockedBy}' is not allowed`, {
@@ -23219,7 +23898,7 @@ Examples:
23219
23898
  });
23220
23899
  }
23221
23900
  try {
23222
- await fs15__default.access(absolute);
23901
+ await fs16__default.access(absolute);
23223
23902
  } catch {
23224
23903
  throw new ToolError(`File not found: ${absolute}`, { tool: "open_file" });
23225
23904
  }
@@ -23234,14 +23913,14 @@ Examples:
23234
23913
  };
23235
23914
  }
23236
23915
  if (isBlockedExecFile(absolute)) {
23237
- throw new ToolError(`Execution of sensitive file is blocked: ${path16__default.basename(absolute)}`, {
23916
+ throw new ToolError(`Execution of sensitive file is blocked: ${path17__default.basename(absolute)}`, {
23238
23917
  tool: "open_file"
23239
23918
  });
23240
23919
  }
23241
23920
  if (args.length > 0 && hasDangerousArgs(args)) {
23242
23921
  throw new ToolError("Arguments contain dangerous patterns", { tool: "open_file" });
23243
23922
  }
23244
- const ext = path16__default.extname(absolute);
23923
+ const ext = path17__default.extname(absolute);
23245
23924
  const interpreter = getInterpreter(ext);
23246
23925
  const executable = await isExecutable(absolute);
23247
23926
  let command;
@@ -23254,7 +23933,7 @@ Examples:
23254
23933
  cmdArgs = [...args];
23255
23934
  } else {
23256
23935
  throw new ToolError(
23257
- `Cannot execute '${path16__default.basename(absolute)}': no known interpreter for '${ext || "(no extension)"}' and file is not executable`,
23936
+ `Cannot execute '${path17__default.basename(absolute)}': no known interpreter for '${ext || "(no extension)"}' and file is not executable`,
23258
23937
  { tool: "open_file" }
23259
23938
  );
23260
23939
  }
@@ -23306,7 +23985,7 @@ Examples:
23306
23985
  reason: z.string().optional().describe("Why access is needed (shown to user for context)")
23307
23986
  }),
23308
23987
  async execute({ path: dirPath, reason }) {
23309
- const absolute = path16__default.resolve(dirPath);
23988
+ const absolute = path17__default.resolve(dirPath);
23310
23989
  if (isWithinAllowedPath(absolute, "read")) {
23311
23990
  return {
23312
23991
  authorized: true,
@@ -23315,8 +23994,8 @@ Examples:
23315
23994
  };
23316
23995
  }
23317
23996
  for (const blocked of BLOCKED_SYSTEM_PATHS) {
23318
- const normalizedBlocked = path16__default.normalize(blocked);
23319
- if (absolute === normalizedBlocked || absolute.startsWith(normalizedBlocked + path16__default.sep)) {
23997
+ const normalizedBlocked = path17__default.normalize(blocked);
23998
+ if (absolute === normalizedBlocked || absolute.startsWith(normalizedBlocked + path17__default.sep)) {
23320
23999
  return {
23321
24000
  authorized: false,
23322
24001
  path: absolute,
@@ -23325,7 +24004,7 @@ Examples:
23325
24004
  }
23326
24005
  }
23327
24006
  const cwd = process.cwd();
23328
- if (absolute === path16__default.normalize(cwd) || absolute.startsWith(path16__default.normalize(cwd) + path16__default.sep)) {
24007
+ if (absolute === path17__default.normalize(cwd) || absolute.startsWith(path17__default.normalize(cwd) + path17__default.sep)) {
23329
24008
  return {
23330
24009
  authorized: true,
23331
24010
  path: absolute,
@@ -23333,7 +24012,7 @@ Examples:
23333
24012
  };
23334
24013
  }
23335
24014
  try {
23336
- const stat2 = await fs15__default.stat(absolute);
24015
+ const stat2 = await fs16__default.stat(absolute);
23337
24016
  if (!stat2.isDirectory()) {
23338
24017
  return {
23339
24018
  authorized: false,
@@ -23349,7 +24028,7 @@ Examples:
23349
24028
  };
23350
24029
  }
23351
24030
  const existing = getAllowedPaths();
23352
- if (existing.some((e) => path16__default.normalize(e.path) === path16__default.normalize(absolute))) {
24031
+ if (existing.some((e) => path17__default.normalize(e.path) === path17__default.normalize(absolute))) {
23353
24032
  return {
23354
24033
  authorized: true,
23355
24034
  path: absolute,