@pikaa-ai/pikaa 0.3.18 → 0.3.20

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
@@ -1347,12 +1347,15 @@ class DefaultModelClientSession {
1347
1347
  };
1348
1348
  return;
1349
1349
  }
1350
- const messages = [
1351
- {
1352
- role: "system",
1353
- content: params.systemPrompt
1354
- }
1355
- ];
1350
+ const enablePromptCache = params.enablePromptCache ?? this.config.enablePromptCache ?? true;
1351
+ const systemMessage = {
1352
+ role: "system",
1353
+ content: params.systemPrompt
1354
+ };
1355
+ if (enablePromptCache) {
1356
+ systemMessage.cache_control = { type: "ephemeral" };
1357
+ }
1358
+ const messages = [systemMessage];
1356
1359
  for (let i = 0;i < params.history.length; i++) {
1357
1360
  const item = params.history[i];
1358
1361
  if (item.type === "user_message") {
@@ -1436,14 +1439,27 @@ class DefaultModelClientSession {
1436
1439
  temperature: params.temperature ?? 0.2
1437
1440
  };
1438
1441
  if (toolsPayload && toolsPayload.length > 0) {
1439
- body.tools = toolsPayload;
1442
+ if (enablePromptCache && toolsPayload.length > 0) {
1443
+ const clonedTools = [...toolsPayload];
1444
+ const lastIdx = clonedTools.length - 1;
1445
+ if (clonedTools[lastIdx] && typeof clonedTools[lastIdx] === "object") {
1446
+ clonedTools[lastIdx] = {
1447
+ ...clonedTools[lastIdx],
1448
+ cache_control: { type: "ephemeral" }
1449
+ };
1450
+ }
1451
+ body.tools = clonedTools;
1452
+ } else {
1453
+ body.tools = toolsPayload;
1454
+ }
1440
1455
  body.tool_choice = "auto";
1441
1456
  }
1442
1457
  const maxRetries = params.maxRetries ?? this.config.maxRetries ?? 10;
1443
1458
  let attempt = 0;
1444
1459
  let response = null;
1445
1460
  const headers = {
1446
- "Content-Type": "application/json"
1461
+ "Content-Type": "application/json",
1462
+ "anthropic-beta": "prompt-caching-2024-07-25"
1447
1463
  };
1448
1464
  if (apiKey) {
1449
1465
  headers["Authorization"] = `Bearer ${apiKey}`;
@@ -1553,7 +1569,8 @@ class DefaultModelClientSession {
1553
1569
  type: "done",
1554
1570
  inputTokens: usageMetrics.inputTokens,
1555
1571
  outputTokens: usageMetrics.outputTokens,
1556
- totalTokens: usageMetrics.totalTokens
1572
+ totalTokens: usageMetrics.totalTokens,
1573
+ cachedTokens: usageMetrics.cachedTokens
1557
1574
  };
1558
1575
  return;
1559
1576
  }
@@ -1564,10 +1581,12 @@ class DefaultModelClientSession {
1564
1581
  continue;
1565
1582
  }
1566
1583
  if (parsed.usage) {
1584
+ const cached = parsed.usage.prompt_tokens_details?.cached_tokens ?? parsed.usage.cache_read_input_tokens ?? parsed.usage.cached_content_token_count ?? 0;
1567
1585
  usageMetrics = {
1568
1586
  inputTokens: parsed.usage.prompt_tokens,
1569
1587
  outputTokens: parsed.usage.completion_tokens,
1570
- totalTokens: parsed.usage.total_tokens
1588
+ totalTokens: parsed.usage.total_tokens,
1589
+ cachedTokens: cached > 0 ? cached : undefined
1571
1590
  };
1572
1591
  }
1573
1592
  const choice = parsed.choices?.[0];
@@ -1772,24 +1791,30 @@ var applyPatchTool = {
1772
1791
  const replacementContent = String(args.replacementContent ?? "");
1773
1792
  if (ctx.execPolicy) {
1774
1793
  const evalResult = ctx.execPolicy.shouldPromptFileEdit(rawPath);
1775
- if (evalResult.isPlanBlocked || ctx.mode === "plan") {
1776
- return {
1777
- output: "Error: Cannot mutate files while in Plan Mode. Please present the implementation plan first.",
1778
- isError: true
1779
- };
1780
- }
1781
1794
  if (evalResult.prompt && ctx.requestApproval) {
1782
- const approval = await ctx.requestApproval(`Apply patch to: ${rawPath}`, `apply_patch ${rawPath}`);
1795
+ const approval = await ctx.requestApproval(evalResult.reason || `Apply patch to: ${rawPath}`, `apply_patch ${rawPath}`);
1783
1796
  const allowed = typeof approval === "object" ? approval.allowed : Boolean(approval);
1784
1797
  if (!allowed) {
1785
- return { output: `Action rejected by user: apply_patch '${rawPath}'`, isError: true };
1798
+ return {
1799
+ output: `[Plan Mode Gate]: File modification declined by user for '${rawPath}'. Please refine your implementation plan or ask the user for guidance.`,
1800
+ isError: true
1801
+ };
1786
1802
  }
1803
+ } else if (evalResult.isPlanBlocked || ctx.mode === "plan") {
1804
+ return {
1805
+ output: `[Plan Mode Gate]: Cannot mutate '${rawPath}' while in Plan Mode without user approval. Please present your implementation plan first.`,
1806
+ isError: true
1807
+ };
1787
1808
  }
1788
1809
  }
1789
1810
  if (!existsSync3(filePath)) {
1790
1811
  if (targetContent) {
1791
1812
  return {
1792
- output: `Error: Target file '${rawPath}' does not exist, but targetContent was provided.`,
1813
+ output: `Error: Target file '${rawPath}' does not exist, but targetContent was provided.
1814
+ [Systematic Error Recovery Checklist]:
1815
+ 1. Root Cause: Trying to patch a non-existent file with targetContent.
1816
+ 2. Fix: For creating new files, leave 'targetContent' empty and provide full contents in 'replacementContent'.
1817
+ 3. Alternatively, check if the file path '${rawPath}' was mistyped.`,
1793
1818
  isError: true
1794
1819
  };
1795
1820
  }
@@ -1799,7 +1824,7 @@ var applyPatchTool = {
1799
1824
  return { output: `Successfully created new file '${rawPath}'` };
1800
1825
  } catch (err) {
1801
1826
  return {
1802
- output: `Failed to create file: ${err instanceof Error ? err.message : String(err)}`,
1827
+ output: `Failed to create file '${rawPath}': ${err instanceof Error ? err.message : String(err)}`,
1803
1828
  isError: true
1804
1829
  };
1805
1830
  }
@@ -1808,21 +1833,33 @@ var applyPatchTool = {
1808
1833
  const originalFileContent = readFileSync2(filePath, "utf8");
1809
1834
  if (!targetContent) {
1810
1835
  return {
1811
- output: `Error: File '${rawPath}' already exists. Specify targetContent to replace specific lines or use overwrite.`,
1836
+ output: `Error: File '${rawPath}' already exists, but targetContent was empty.
1837
+ [Systematic Error Recovery Checklist]:
1838
+ 1. Root Cause: An existing file requires targetContent to specify which lines to replace.
1839
+ 2. Fix: Call 'read_file' on '${rawPath}', extract the exact target lines, and provide them in 'targetContent'.
1840
+ 3. To overwrite the whole file, use the 'write_file' tool instead.`,
1812
1841
  isError: true
1813
1842
  };
1814
1843
  }
1815
1844
  const firstIndex = originalFileContent.indexOf(targetContent);
1816
1845
  if (firstIndex === -1) {
1817
1846
  return {
1818
- output: `Error: targetContent was not found in '${rawPath}'. Please verify file contents before editing.`,
1847
+ output: `Error: targetContent was not found in '${rawPath}'.
1848
+ [Systematic Error Recovery Checklist]:
1849
+ 1. Root Cause: The snippet in targetContent does not match the actual file content (differences in whitespace, indentation, line endings, or prior edits).
1850
+ 2. Action: Call 'read_file' on '${rawPath}' to inspect current exact lines and indentation.
1851
+ 3. Fix: Provide the exact matching lines (including leading spaces) or wider context, then retry 'apply_patch'.`,
1819
1852
  isError: true
1820
1853
  };
1821
1854
  }
1822
1855
  const secondIndex = originalFileContent.indexOf(targetContent, firstIndex + 1);
1823
1856
  if (secondIndex !== -1) {
1824
1857
  return {
1825
- output: `Error: targetContent matched multiple locations in '${rawPath}'. Provide more surrounding context lines to ensure uniqueness.`,
1858
+ output: `Error: targetContent matched multiple locations in '${rawPath}'.
1859
+ [Systematic Error Recovery Checklist]:
1860
+ 1. Root Cause: targetContent is ambiguous and occurs multiple times in the file.
1861
+ 2. Action: Include 2-3 additional surrounding lines (before or after the target block) to make the target snippet uniquely identifiable.
1862
+ 3. Fix: Re-run 'apply_patch' with the extended unique block.`,
1826
1863
  isError: true
1827
1864
  };
1828
1865
  }
@@ -1833,7 +1870,7 @@ var applyPatchTool = {
1833
1870
  };
1834
1871
  } catch (err) {
1835
1872
  return {
1836
- output: `Failed to apply patch: ${err instanceof Error ? err.message : String(err)}`,
1873
+ output: `Failed to apply patch to '${rawPath}': ${err instanceof Error ? err.message : String(err)}`,
1837
1874
  isError: true
1838
1875
  };
1839
1876
  }
@@ -1867,9 +1904,9 @@ class ExecPolicy {
1867
1904
  shouldPromptFileEdit(filePath) {
1868
1905
  if (this.mode === "plan") {
1869
1906
  return {
1870
- prompt: false,
1907
+ prompt: true,
1871
1908
  isPlanBlocked: true,
1872
- reason: "Plan Mode is active. Mutating files is not allowed while planning."
1909
+ reason: `[Plan Mode Gate] Approval required to mutate '${filePath || "file"}' and proceed with implementation.`
1873
1910
  };
1874
1911
  }
1875
1912
  if (this.mode === "manual") {
@@ -1883,11 +1920,14 @@ class ExecPolicy {
1883
1920
  evaluate(command) {
1884
1921
  const trimmed = command.trim();
1885
1922
  if (this.mode === "plan") {
1886
- const isReadOnly = /^(git\s+(status|log|diff|branch|show)|ls|dir|cat|type|grep|rg|find|pwd|which|where)\b/i.test(trimmed);
1923
+ const isReadOnly = /^(git\s+(status|log|diff|branch|show|rev-parse)|ls|dir|cat|type|grep|rg|find|pwd|which|where)\b/i.test(trimmed);
1887
1924
  if (isReadOnly) {
1888
1925
  return { decision: "allow", reason: "Read-only inspection allowed in Plan mode" };
1889
1926
  }
1890
- return { decision: "deny", reason: "Cannot execute mutating shell commands in Plan mode" };
1927
+ return {
1928
+ decision: "prompt",
1929
+ reason: `[Plan Mode Gate] Approval required to execute shell command '${trimmed}' in Plan Mode`
1930
+ };
1891
1931
  }
1892
1932
  if (this.mode === "manual") {
1893
1933
  return {
@@ -2283,6 +2323,73 @@ class PrefixRulesStore {
2283
2323
  }
2284
2324
  var globalPrefixRulesStore = new PrefixRulesStore;
2285
2325
 
2326
+ // src/workspace/ephemeral.ts
2327
+ import { mkdirSync as mkdirSync5, rmSync, existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
2328
+ import { join as join2 } from "path";
2329
+ import { tmpdir } from "os";
2330
+
2331
+ class EphemeralWorkspaceManager {
2332
+ activeScratchpads = new Set;
2333
+ createScratchpad(turnId) {
2334
+ const uniqueId = `groupy_scratch_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
2335
+ const baseDir = join2(tmpdir(), "groupy-ephemeral", turnId ? `turn_${turnId}` : "general");
2336
+ const scratchPath = join2(baseDir, uniqueId);
2337
+ mkdirSync5(scratchPath, { recursive: true });
2338
+ this.activeScratchpads.add(scratchPath);
2339
+ return scratchPath;
2340
+ }
2341
+ cleanup(scratchPath) {
2342
+ if (!scratchPath || !this.activeScratchpads.has(scratchPath))
2343
+ return;
2344
+ try {
2345
+ if (existsSync7(scratchPath)) {
2346
+ rmSync(scratchPath, { recursive: true, force: true });
2347
+ }
2348
+ } catch {} finally {
2349
+ this.activeScratchpads.delete(scratchPath);
2350
+ }
2351
+ }
2352
+ cleanupTurn(turnId) {
2353
+ const turnDir = join2(tmpdir(), "groupy-ephemeral", `turn_${turnId}`);
2354
+ try {
2355
+ if (existsSync7(turnDir)) {
2356
+ rmSync(turnDir, { recursive: true, force: true });
2357
+ }
2358
+ } catch {}
2359
+ }
2360
+ cleanRootResidue(cwd) {
2361
+ const cleaned = [];
2362
+ try {
2363
+ const files = readdirSync2(cwd);
2364
+ const tempPatterns = [
2365
+ /^tmp_/i,
2366
+ /^draft_/i,
2367
+ /^scratch_/i,
2368
+ /^temp_/i,
2369
+ /^preview_.*\.html$/i,
2370
+ /\.tmp$/i,
2371
+ /\.bak$/i,
2372
+ /~$/i
2373
+ ];
2374
+ for (const file of files) {
2375
+ if (tempPatterns.some((p) => p.test(file))) {
2376
+ const fullPath = join2(cwd, file);
2377
+ const stat = statSync2(fullPath);
2378
+ if (stat.isFile()) {
2379
+ rmSync(fullPath, { force: true });
2380
+ cleaned.push(file);
2381
+ } else if (stat.isDirectory() && (file.startsWith("tmp_") || file.startsWith("scratch_") || file.startsWith("temp_"))) {
2382
+ rmSync(fullPath, { recursive: true, force: true });
2383
+ cleaned.push(file);
2384
+ }
2385
+ }
2386
+ }
2387
+ } catch {}
2388
+ return cleaned;
2389
+ }
2390
+ }
2391
+ var globalEphemeralWorkspace = new EphemeralWorkspaceManager;
2392
+
2286
2393
  // src/tools/handlers/shell.ts
2287
2394
  function createShellTool(policy = new ExecPolicy) {
2288
2395
  return {
@@ -2368,6 +2475,7 @@ function createShellTool(policy = new ExecPolicy) {
2368
2475
  const timeoutMs = typeof args.timeoutMs === "number" ? args.timeoutMs : 30000;
2369
2476
  const isWindows = process.platform === "win32";
2370
2477
  const baseCmd = isWindows ? ["cmd.exe", "/d", "/s", "/c", command] : ["/bin/sh", "-c", command];
2478
+ const ephemeralScratchpad = globalEphemeralWorkspace.createScratchpad(ctx.turnId);
2371
2479
  const sandboxProfile = globalKernelSandbox.buildDefaultProfile(ctx.cwd);
2372
2480
  if (isEscalated) {
2373
2481
  sandboxProfile.allowNetwork = true;
@@ -2378,6 +2486,10 @@ function createShellTool(policy = new ExecPolicy) {
2378
2486
  cwd: ctx.cwd,
2379
2487
  env: {
2380
2488
  ...process.env,
2489
+ TMPDIR: ephemeralScratchpad,
2490
+ TEMP: ephemeralScratchpad,
2491
+ TMP: ephemeralScratchpad,
2492
+ GROUPY_SCRATCH_DIR: ephemeralScratchpad,
2381
2493
  ...ctx.proxyEnv
2382
2494
  },
2383
2495
  stdout: "pipe",
@@ -2414,9 +2526,14 @@ function createShellTool(policy = new ExecPolicy) {
2414
2526
  if (result.stderr)
2415
2527
  outputParts.push(`STDERR:
2416
2528
  ${result.stderr.trim()}`);
2417
- if (result.code !== 0)
2529
+ if (result.code !== 0) {
2418
2530
  outputParts.push(`
2419
- [Process exited with code ${result.code}]`);
2531
+ [Process exited with non-zero code ${result.code}]`);
2532
+ outputParts.push(`[Systematic Error Recovery Checklist]:
2533
+ 1. Inspect STDERR above to pinpoint syntax errors, failed test assertions, or missing dependencies.
2534
+ 2. If this is a test failure, trace the failure in source code and fix the root cause before re-running.
2535
+ 3. If this is a missing command/module, install or configure the prerequisite.`);
2536
+ }
2420
2537
  const output = outputParts.join(`
2421
2538
  `) || "[Command completed with no output]";
2422
2539
  return {
@@ -2425,16 +2542,21 @@ ${result.stderr.trim()}`);
2425
2542
  };
2426
2543
  } catch (err) {
2427
2544
  return {
2428
- output: `Execution error: ${err instanceof Error ? err.message : String(err)}`,
2545
+ output: `Execution error: ${err instanceof Error ? err.message : String(err)}
2546
+ [Systematic Error Recovery Checklist]:
2547
+ 1. Verify command syntax, arguments, and executable availability in PATH.
2548
+ 2. Check if the current working directory ('${ctx.cwd}') is valid.`,
2429
2549
  isError: true
2430
2550
  };
2551
+ } finally {
2552
+ globalEphemeralWorkspace.cleanup(ephemeralScratchpad);
2431
2553
  }
2432
2554
  }
2433
2555
  };
2434
2556
  }
2435
2557
  var shellTool = createShellTool();
2436
2558
  // src/tools/handlers/file-ops.ts
2437
- import { readdirSync as readdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync7, statSync as statSync2, mkdirSync as mkdirSync5 } from "fs";
2559
+ import { readdirSync as readdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync8, statSync as statSync3, mkdirSync as mkdirSync6 } from "fs";
2438
2560
  import { resolve as resolve6, dirname as dirname4 } from "path";
2439
2561
  var readFileTool = {
2440
2562
  name: "read_file",
@@ -2448,7 +2570,7 @@ var readFileTool = {
2448
2570
  },
2449
2571
  async execute(args, ctx) {
2450
2572
  const filePath = resolve6(ctx.cwd, String(args.path || ""));
2451
- if (!existsSync7(filePath)) {
2573
+ if (!existsSync8(filePath)) {
2452
2574
  return { output: `Error: File not found: '${args.path}'`, isError: true };
2453
2575
  }
2454
2576
  try {
@@ -2470,14 +2592,14 @@ var listDirTool = {
2470
2592
  },
2471
2593
  async execute(args, ctx) {
2472
2594
  const dirPath = resolve6(ctx.cwd, String(args.path || "."));
2473
- if (!existsSync7(dirPath)) {
2595
+ if (!existsSync8(dirPath)) {
2474
2596
  return { output: `Error: Directory not found: '${args.path}'`, isError: true };
2475
2597
  }
2476
2598
  try {
2477
- const entries = readdirSync2(dirPath);
2599
+ const entries = readdirSync3(dirPath);
2478
2600
  const formatted = entries.map((entry) => {
2479
2601
  const full = resolve6(dirPath, entry);
2480
- const isDir = statSync2(full).isDirectory();
2602
+ const isDir = statSync3(full).isDirectory();
2481
2603
  return `${isDir ? "[DIR]" : "[FILE]"} ${entry}`;
2482
2604
  });
2483
2605
  return { output: formatted.join(`
@@ -2503,26 +2625,35 @@ var writeFileTool = {
2503
2625
  const filePath = resolve6(ctx.cwd, rawPath);
2504
2626
  if (ctx.execPolicy) {
2505
2627
  const evalResult = ctx.execPolicy.shouldPromptFileEdit(rawPath);
2506
- if (evalResult.isPlanBlocked || ctx.mode === "plan") {
2507
- return {
2508
- output: "Error: Cannot write or mutate files while in Plan Mode. Please present the implementation plan first.",
2509
- isError: true
2510
- };
2511
- }
2512
2628
  if (evalResult.prompt && ctx.requestApproval) {
2513
- const approval = await ctx.requestApproval(`Write file: ${rawPath}`, `write_file ${rawPath}`);
2629
+ const approval = await ctx.requestApproval(evalResult.reason || `Write file: ${rawPath}`, `write_file ${rawPath}`);
2514
2630
  const allowed = typeof approval === "object" ? approval.allowed : Boolean(approval);
2515
2631
  if (!allowed) {
2516
- return { output: `Action rejected by user: write_file '${rawPath}'`, isError: true };
2632
+ return {
2633
+ output: `[Plan Mode Gate]: File creation declined by user for '${rawPath}'. Please refine your implementation plan or ask the user for guidance.`,
2634
+ isError: true
2635
+ };
2517
2636
  }
2637
+ } else if (evalResult.isPlanBlocked || ctx.mode === "plan") {
2638
+ return {
2639
+ output: `[Plan Mode Gate]: Cannot write or mutate '${rawPath}' while in Plan Mode without user approval. Please present your implementation plan first.`,
2640
+ isError: true
2641
+ };
2518
2642
  }
2519
2643
  }
2520
2644
  try {
2521
- mkdirSync5(dirname4(filePath), { recursive: true });
2645
+ mkdirSync6(dirname4(filePath), { recursive: true });
2522
2646
  writeFileSync3(filePath, String(args.content ?? ""), "utf8");
2523
2647
  return { output: `Successfully wrote to '${args.path}'` };
2524
2648
  } catch (err) {
2525
- return { output: `Failed to write file: ${err instanceof Error ? err.message : String(err)}`, isError: true };
2649
+ return {
2650
+ output: `Failed to write file '${rawPath}': ${err instanceof Error ? err.message : String(err)}
2651
+ [Systematic Error Recovery Checklist]:
2652
+ 1. Check directory permissions and ensure the path is valid within the workspace.
2653
+ 2. If the path contains non-existent nested folders, they should be auto-created.
2654
+ 3. Verify that the file is not locked by another active process.`,
2655
+ isError: true
2656
+ };
2526
2657
  }
2527
2658
  }
2528
2659
  };
@@ -2641,8 +2772,8 @@ var updatePlanTool = {
2641
2772
  }
2642
2773
  };
2643
2774
  // src/search/engine.ts
2644
- import { readdirSync as readdirSync3, readFileSync as readFileSync4, statSync as statSync3, existsSync as existsSync8 } from "fs";
2645
- import { resolve as resolve7, relative, join as join2, extname } from "path";
2775
+ import { readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync4, existsSync as existsSync9 } from "fs";
2776
+ import { resolve as resolve7, relative, join as join3, extname } from "path";
2646
2777
  var DEFAULT_IGNORE_DIRS = new Set([
2647
2778
  ".git",
2648
2779
  "node_modules",
@@ -2688,7 +2819,7 @@ var BINARY_EXTENSIONS = new Set([
2688
2819
  class FileSearchEngine {
2689
2820
  grep(cwd, options) {
2690
2821
  const searchRoot = resolve7(cwd, options.path || ".");
2691
- if (!existsSync8(searchRoot)) {
2822
+ if (!existsSync9(searchRoot)) {
2692
2823
  return { matches: [], totalMatches: 0, truncated: false };
2693
2824
  }
2694
2825
  const maxResults = options.maxResults || 50;
@@ -2738,7 +2869,7 @@ class FileSearchEngine {
2738
2869
  }
2739
2870
  findFiles(cwd, options) {
2740
2871
  const searchRoot = resolve7(cwd, options.path || ".");
2741
- if (!existsSync8(searchRoot))
2872
+ if (!existsSync9(searchRoot))
2742
2873
  return [];
2743
2874
  const maxResults = options.maxResults || 100;
2744
2875
  const gitignoreRules = this.loadGitignoreRules(searchRoot);
@@ -2777,8 +2908,8 @@ class FileSearchEngine {
2777
2908
  }
2778
2909
  loadGitignoreRules(root) {
2779
2910
  const rules = new Set;
2780
- const gitignorePath = join2(root, ".gitignore");
2781
- if (existsSync8(gitignorePath)) {
2911
+ const gitignorePath = join3(root, ".gitignore");
2912
+ if (existsSync9(gitignorePath)) {
2782
2913
  try {
2783
2914
  const lines = readFileSync4(gitignorePath, "utf8").split(`
2784
2915
  `);
@@ -2795,7 +2926,7 @@ class FileSearchEngine {
2795
2926
  collectFiles(dir, root, gitignoreRules, includePattern) {
2796
2927
  const results = [];
2797
2928
  try {
2798
- const stat = statSync3(dir);
2929
+ const stat = statSync4(dir);
2799
2930
  if (!stat.isDirectory()) {
2800
2931
  if (!this.isBinary(dir)) {
2801
2932
  results.push(dir);
@@ -2809,9 +2940,9 @@ class FileSearchEngine {
2809
2940
  while (queue.length > 0) {
2810
2941
  const currentDir = queue.shift();
2811
2942
  try {
2812
- const entries = readdirSync3(currentDir, { withFileTypes: true });
2943
+ const entries = readdirSync4(currentDir, { withFileTypes: true });
2813
2944
  for (const entry of entries) {
2814
- const fullPath = join2(currentDir, entry.name);
2945
+ const fullPath = join3(currentDir, entry.name);
2815
2946
  const relToRoot = relative(root, fullPath).replace(/\\/g, "/");
2816
2947
  if (this.isIgnored(entry.name, relToRoot, gitignoreRules)) {
2817
2948
  continue;
@@ -3531,8 +3662,8 @@ class PathSandbox {
3531
3662
  }
3532
3663
  }
3533
3664
  // src/security/scanner.ts
3534
- import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
3535
- import { join as join3, relative as relative3, resolve as resolve9 } from "path";
3665
+ import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync5, statSync as statSync5 } from "fs";
3666
+ import { join as join4, relative as relative3, resolve as resolve9 } from "path";
3536
3667
  var SECURITY_RULES = [
3537
3668
  {
3538
3669
  id: "SEC-001",
@@ -3670,21 +3801,21 @@ async function runSecurityScan(targetDir, options = {}) {
3670
3801
  const findings = [];
3671
3802
  let scannedCount = 0;
3672
3803
  function walk(current) {
3673
- if (scannedCount >= maxFiles || !existsSync9(current))
3804
+ if (scannedCount >= maxFiles || !existsSync10(current))
3674
3805
  return;
3675
3806
  let entries;
3676
3807
  try {
3677
- entries = readdirSync4(current);
3808
+ entries = readdirSync5(current);
3678
3809
  } catch {
3679
3810
  return;
3680
3811
  }
3681
3812
  for (const entry of entries) {
3682
3813
  if (scannedCount >= maxFiles)
3683
3814
  break;
3684
- const fullPath = join3(current, entry);
3815
+ const fullPath = join4(current, entry);
3685
3816
  let stat;
3686
3817
  try {
3687
- stat = statSync4(fullPath);
3818
+ stat = statSync5(fullPath);
3688
3819
  } catch {
3689
3820
  continue;
3690
3821
  }
@@ -3793,9 +3924,11 @@ async function captureWorldState(cwd) {
3793
3924
  };
3794
3925
  }
3795
3926
  function formatWorldStatePrompt(state) {
3927
+ const isWindows = process.platform === "win32";
3928
+ const platformNote = isWindows ? `Platform: Windows (${state.os}). Shell is cmd.exe / PowerShell. POSIX commands (grep, find, cat, sed, awk) are NOT supported in shell. ALWAYS use native grep_search, find_files, and read_file tools.` : `Platform: ${state.os}`;
3796
3929
  const parts = [
3797
3930
  `Current Working Directory: ${state.cwd}`,
3798
- `Platform: ${state.os}`
3931
+ platformNote
3799
3932
  ];
3800
3933
  if (state.gitBranch) {
3801
3934
  parts.push(`Git Branch: ${state.gitBranch}`);
@@ -3805,13 +3938,13 @@ function formatWorldStatePrompt(state) {
3805
3938
  `);
3806
3939
  }
3807
3940
  // src/prompts/loader.ts
3808
- import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
3809
- import { resolve as resolve10, join as join4 } from "path";
3941
+ import { existsSync as existsSync11, readFileSync as readFileSync6 } from "fs";
3942
+ import { resolve as resolve10, join as join5 } from "path";
3810
3943
  import { homedir as homedir2 } from "os";
3811
3944
  class PromptTemplateLoader {
3812
3945
  builtInTemplatesDir;
3813
3946
  constructor(builtInDir) {
3814
- this.builtInTemplatesDir = builtInDir || resolve10(join4(import.meta.dir, "..", "..", "templates"));
3947
+ this.builtInTemplatesDir = builtInDir || resolve10(join5(import.meta.dir, "..", "..", "templates"));
3815
3948
  }
3816
3949
  loadTemplate(relativePath, variables = {}, cwd) {
3817
3950
  const rawContent = this.resolveTemplateContent(relativePath, cwd);
@@ -3820,27 +3953,27 @@ class PromptTemplateLoader {
3820
3953
  resolveTemplateContent(relativePath, cwd) {
3821
3954
  const normalizedRel = relativePath.replace(/^\/+/, "");
3822
3955
  if (cwd) {
3823
- const workspacePath = join4(cwd, ".agents", "templates", normalizedRel);
3824
- if (existsSync10(workspacePath)) {
3956
+ const workspacePath = join5(cwd, ".agents", "templates", normalizedRel);
3957
+ if (existsSync11(workspacePath)) {
3825
3958
  try {
3826
3959
  return readFileSync6(workspacePath, "utf-8");
3827
3960
  } catch {}
3828
3961
  }
3829
3962
  }
3830
- const globalPath = join4(getGlobalTemplatesDir(), normalizedRel);
3831
- if (existsSync10(globalPath)) {
3963
+ const globalPath = join5(getGlobalTemplatesDir(), normalizedRel);
3964
+ if (existsSync11(globalPath)) {
3832
3965
  try {
3833
3966
  return readFileSync6(globalPath, "utf-8");
3834
3967
  } catch {}
3835
3968
  }
3836
- const legacyGlobalPath = join4(homedir2(), ".groupy", "templates", normalizedRel);
3837
- if (existsSync10(legacyGlobalPath)) {
3969
+ const legacyGlobalPath = join5(homedir2(), ".groupy", "templates", normalizedRel);
3970
+ if (existsSync11(legacyGlobalPath)) {
3838
3971
  try {
3839
3972
  return readFileSync6(legacyGlobalPath, "utf-8");
3840
3973
  } catch {}
3841
3974
  }
3842
- const builtInPath = join4(this.builtInTemplatesDir, normalizedRel);
3843
- if (existsSync10(builtInPath)) {
3975
+ const builtInPath = join5(this.builtInTemplatesDir, normalizedRel);
3976
+ if (existsSync11(builtInPath)) {
3844
3977
  try {
3845
3978
  return readFileSync6(builtInPath, "utf-8");
3846
3979
  } catch {}
@@ -3857,8 +3990,8 @@ class PromptTemplateLoader {
3857
3990
  var globalPromptLoader = new PromptTemplateLoader;
3858
3991
 
3859
3992
  // src/prompts/agents-md.ts
3860
- import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
3861
- import { resolve as resolve11, join as join5, dirname as dirname5 } from "path";
3993
+ import { existsSync as existsSync12, readFileSync as readFileSync7 } from "fs";
3994
+ import { resolve as resolve11, join as join6, dirname as dirname5 } from "path";
3862
3995
  var DEFAULT_AGENTS_MD_FILENAMES = [
3863
3996
  "AGENTS.override.md",
3864
3997
  "AGENTS.md",
@@ -3875,7 +4008,7 @@ class AgentsMdLoader {
3875
4008
  findProjectRoot(startDir) {
3876
4009
  let current = resolve11(startDir);
3877
4010
  while (true) {
3878
- if (existsSync11(join5(current, ".git"))) {
4011
+ if (existsSync12(join6(current, ".git"))) {
3879
4012
  return current;
3880
4013
  }
3881
4014
  const parent = dirname5(current);
@@ -3909,8 +4042,8 @@ class AgentsMdLoader {
3909
4042
  const sourcePaths = [];
3910
4043
  for (const dir of dirHierarchy) {
3911
4044
  for (const filename of fallbackFilenames) {
3912
- const filePath = join5(dir, filename);
3913
- if (existsSync11(filePath)) {
4045
+ const filePath = join6(dir, filename);
4046
+ if (existsSync12(filePath)) {
3914
4047
  try {
3915
4048
  const content = readFileSync7(filePath, "utf-8").trim();
3916
4049
  if (content) {
@@ -3934,81 +4067,141 @@ class AgentsMdLoader {
3934
4067
  var globalAgentsMdLoader = new AgentsMdLoader;
3935
4068
 
3936
4069
  // src/context/instructions.ts
3937
- function buildSystemPrompt(params) {
3938
- const sections = [];
4070
+ function wrapXmlTag(tag, content, attrs = {}) {
4071
+ const attrStr = Object.entries(attrs).filter(([_, v]) => Boolean(v)).map(([k, v]) => ` ${k}="${v}"`).join("");
4072
+ return `<${tag}${attrStr}>
4073
+ ${content.trim()}
4074
+ </${tag}>`;
4075
+ }
4076
+ function buildStructuredSystemPrompt(params) {
3939
4077
  const cwd = params.cwd || process.cwd();
3940
4078
  const mode = params.collaborationMode || "default";
3941
- if (params.basePrompt) {
3942
- sections.push(params.basePrompt);
3943
- } else {
4079
+ const blocks = [];
4080
+ let baseContent = params.basePrompt;
4081
+ if (!baseContent) {
3944
4082
  const templateName = params.basePromptTemplate || "base/groupy_prompt.md";
3945
- const baseContent = globalPromptLoader.loadTemplate(templateName, {}, cwd);
3946
- if (baseContent) {
3947
- sections.push(baseContent.trim());
3948
- } else {
3949
- sections.push("You are Groupy, an expert autonomous AI coding assistant. You think step-by-step, act surgically, and write clean, correct code.");
3950
- }
4083
+ baseContent = globalPromptLoader.loadTemplate(templateName, {}, cwd) || "You are Groupy, an expert autonomous AI coding assistant. You think step-by-step, act surgically, and write clean, correct code.";
3951
4084
  }
4085
+ blocks.push({
4086
+ tag: "system_identity",
4087
+ content: wrapXmlTag("system_identity", baseContent),
4088
+ cacheable: true
4089
+ });
3952
4090
  if (params.personality) {
3953
4091
  const personalityContent = globalPromptLoader.loadTemplate(`personalities/${params.personality}.md`, {}, cwd);
3954
4092
  if (personalityContent) {
3955
- sections.push(personalityContent.trim());
4093
+ blocks.push({
4094
+ tag: "personality",
4095
+ content: wrapXmlTag("personality", personalityContent, { kind: params.personality }),
4096
+ cacheable: true
4097
+ });
3956
4098
  }
3957
4099
  }
3958
4100
  if (params.isOrchestrator) {
3959
4101
  const orchestratorContent = globalPromptLoader.loadTemplate("agents/orchestrator.md", {}, cwd);
3960
4102
  if (orchestratorContent) {
3961
- sections.push(orchestratorContent.trim());
4103
+ blocks.push({
4104
+ tag: "orchestrator_guidelines",
4105
+ content: wrapXmlTag("orchestrator_guidelines", orchestratorContent),
4106
+ cacheable: true
4107
+ });
3962
4108
  }
3963
4109
  }
3964
- const modeTemplate = globalPromptLoader.loadTemplate(`modes/${mode}.md`, {
3965
- KNOWN_MODE_NAMES: "default, plan, review"
3966
- }, cwd);
4110
+ const modeTemplate = globalPromptLoader.loadTemplate(`modes/${mode}.md`, { KNOWN_MODE_NAMES: "default, plan, review" }, cwd);
3967
4111
  if (modeTemplate) {
3968
- sections.push(modeTemplate.trim());
4112
+ blocks.push({
4113
+ tag: "collaboration_mode",
4114
+ content: wrapXmlTag("collaboration_mode", modeTemplate, { name: mode }),
4115
+ cacheable: true
4116
+ });
3969
4117
  }
3970
4118
  if (params.sandboxMode) {
3971
- const sandboxTemplate = globalPromptLoader.loadTemplate(`permissions/sandbox_mode/${params.sandboxMode}.md`, {
3972
- network_access: params.networkAccess ? "enabled" : "disabled"
3973
- }, cwd);
4119
+ const sandboxTemplate = globalPromptLoader.loadTemplate(`permissions/sandbox_mode/${params.sandboxMode}.md`, { network_access: params.networkAccess ? "enabled" : "disabled" }, cwd);
3974
4120
  if (sandboxTemplate) {
3975
- sections.push(sandboxTemplate.trim());
4121
+ blocks.push({
4122
+ tag: "sandbox_policy",
4123
+ content: wrapXmlTag("sandbox_policy", sandboxTemplate, { mode: params.sandboxMode }),
4124
+ cacheable: true
4125
+ });
3976
4126
  }
3977
4127
  }
3978
4128
  if (params.approvalPolicy) {
3979
4129
  const approvalTemplate = globalPromptLoader.loadTemplate(`permissions/approval_policy/${params.approvalPolicy}.md`, {}, cwd);
3980
4130
  if (approvalTemplate) {
3981
- sections.push(approvalTemplate.trim());
4131
+ blocks.push({
4132
+ tag: "approval_policy",
4133
+ content: wrapXmlTag("approval_policy", approvalTemplate, { policy: params.approvalPolicy }),
4134
+ cacheable: true
4135
+ });
3982
4136
  }
3983
4137
  }
3984
4138
  const projectInstructions = globalAgentsMdLoader.loadProjectInstructions(cwd);
3985
4139
  if (projectInstructions) {
3986
- sections.push(`## Project Instructions (AGENTS.md)
3987
-
3988
- ${projectInstructions.content.trim()}`);
4140
+ blocks.push({
4141
+ tag: "project_instructions",
4142
+ content: wrapXmlTag("project_instructions", projectInstructions.content, { source: "AGENTS.md" }),
4143
+ cacheable: true
4144
+ });
3989
4145
  }
3990
4146
  if (params.memoriesPrompt) {
3991
- sections.push(params.memoriesPrompt.trim());
4147
+ blocks.push({
4148
+ tag: "persistent_memories",
4149
+ content: wrapXmlTag("persistent_memories", params.memoriesPrompt),
4150
+ cacheable: true
4151
+ });
3992
4152
  }
3993
4153
  if (params.skillsPrompt) {
3994
- sections.push(params.skillsPrompt.trim());
4154
+ blocks.push({
4155
+ tag: "domain_skills",
4156
+ content: wrapXmlTag("domain_skills", params.skillsPrompt),
4157
+ cacheable: true
4158
+ });
3995
4159
  }
3996
4160
  if (params.mcpPrompt) {
3997
- sections.push(params.mcpPrompt.trim());
4161
+ blocks.push({
4162
+ tag: "mcp_servers",
4163
+ content: wrapXmlTag("mcp_servers", params.mcpPrompt),
4164
+ cacheable: true
4165
+ });
3998
4166
  }
3999
4167
  if (params.developerInstructions) {
4000
- sections.push(`## Developer Instructions
4001
- ${params.developerInstructions}`);
4168
+ blocks.push({
4169
+ tag: "developer_instructions",
4170
+ content: wrapXmlTag("developer_instructions", params.developerInstructions),
4171
+ cacheable: true
4172
+ });
4002
4173
  }
4174
+ const dynamicBlocks = [];
4003
4175
  if (params.worldStatePrompt) {
4004
- sections.push(`## Environment Context
4005
- ${params.worldStatePrompt}`);
4176
+ dynamicBlocks.push({
4177
+ tag: "runtime_environment",
4178
+ content: wrapXmlTag("runtime_environment", params.worldStatePrompt),
4179
+ cacheable: false
4180
+ });
4006
4181
  }
4007
- return sections.join(`
4182
+ const staticPrefix = blocks.map((b) => b.content).join(`
4183
+
4184
+ `);
4185
+ const dynamicSuffix = dynamicBlocks.map((b) => b.content).join(`
4008
4186
 
4009
4187
  `);
4188
+ const allBlocks = [...blocks, ...dynamicBlocks];
4189
+ const text = allBlocks.map((b) => b.content).join(`
4190
+
4191
+ `);
4192
+ return {
4193
+ text,
4194
+ staticPrefix,
4195
+ dynamicSuffix,
4196
+ blocks: allBlocks
4197
+ };
4198
+ }
4199
+ function buildSystemPrompt(params) {
4200
+ return buildStructuredSystemPrompt(params).text;
4010
4201
  }
4011
4202
  // src/context/compactor.ts
4203
+ var DEFAULT_MAX_CONTEXT_TOKENS = 256000;
4204
+ var DEFAULT_AUTO_COMPACT_THRESHOLD_TOKENS = 180000;
4012
4205
  function estimateItemTokens(item) {
4013
4206
  const text = item.type === "user_message" ? item.content : item.type === "agent_message" ? item.content : item.type === "reasoning" ? item.content : item.type === "function_call" ? JSON.stringify(item.arguments) : item.type === "function_call_output" ? item.output : "";
4014
4207
  return Math.ceil(text.length / 4) + 4;
@@ -4076,7 +4269,7 @@ async function runTurn(session, turnContext, input) {
4076
4269
  });
4077
4270
  const currentHistory = session.getHistory();
4078
4271
  const estimatedTokens = estimateTotalTokens(currentHistory);
4079
- const maxTokenLimit = 80000;
4272
+ const maxTokenLimit = DEFAULT_AUTO_COMPACT_THRESHOLD_TOKENS;
4080
4273
  if (estimatedTokens > maxTokenLimit) {
4081
4274
  const compacted = compactHistory(currentHistory);
4082
4275
  session.setHistory(compacted);
@@ -4115,6 +4308,7 @@ async function runTurn(session, turnContext, input) {
4115
4308
  let iteration = 0;
4116
4309
  let accumulatedInputTokens = 0;
4117
4310
  let accumulatedOutputTokens = 0;
4311
+ let accumulatedCachedTokens = 0;
4118
4312
  const clientSession = session.modelClient.newSession();
4119
4313
  try {
4120
4314
  while (iteration < turnContext.maxIterations) {
@@ -4131,7 +4325,8 @@ async function runTurn(session, turnContext, input) {
4131
4325
  systemPrompt: effectiveSystemPrompt,
4132
4326
  history: session.getHistory(),
4133
4327
  tools: turnContext.tools,
4134
- signal
4328
+ signal,
4329
+ enablePromptCache: true
4135
4330
  });
4136
4331
  for await (const chunk of stream) {
4137
4332
  if (signal.aborted) {
@@ -4157,6 +4352,8 @@ async function runTurn(session, turnContext, input) {
4157
4352
  iterInputTokens = chunk.inputTokens;
4158
4353
  if (chunk.outputTokens !== undefined)
4159
4354
  iterOutputTokens = chunk.outputTokens;
4355
+ if (chunk.cachedTokens !== undefined)
4356
+ accumulatedCachedTokens += chunk.cachedTokens;
4160
4357
  } else if (chunk.type === "error") {
4161
4358
  throw chunk.error;
4162
4359
  }
@@ -4268,7 +4465,10 @@ async function runTurn(session, turnContext, input) {
4268
4465
  session.addHistoryItem({
4269
4466
  id: `msg_nudge_${Date.now()}`,
4270
4467
  type: "user_message",
4271
- content: "Please proceed with executing the task. Provide your complete analysis or call the required tools now.",
4468
+ content: `[Systematic ReAct Nudge]: No tool actions or answers were produced in this iteration.
4469
+ 1. Review the user's objective and determine the immediate next action.
4470
+ 2. If more context is required, invoke an exploration tool ('read_file', 'list_dir', 'grep_search', 'find_files').
4471
+ 3. If ready to answer or implement, call the required mutating tool or deliver your full, concrete response now.`,
4272
4472
  createdAt: Date.now()
4273
4473
  });
4274
4474
  continue;
@@ -4277,13 +4477,14 @@ async function runTurn(session, turnContext, input) {
4277
4477
  break;
4278
4478
  }
4279
4479
  const totalContextTokens = estimateTotalTokens(session.getHistory()) + Math.ceil(effectiveSystemPrompt.length / 4);
4280
- const maxContextTokens = 128000;
4480
+ const maxContextTokens = DEFAULT_MAX_CONTEXT_TOKENS;
4281
4481
  session.emitEvent({
4282
4482
  type: "TurnCompleted",
4283
4483
  turnId,
4284
4484
  inputTokens: accumulatedInputTokens,
4285
4485
  outputTokens: accumulatedOutputTokens,
4286
4486
  totalTokens: accumulatedInputTokens + accumulatedOutputTokens,
4487
+ cachedTokens: accumulatedCachedTokens > 0 ? accumulatedCachedTokens : undefined,
4287
4488
  contextTokens: totalContextTokens,
4288
4489
  maxContextTokens
4289
4490
  });
@@ -4298,6 +4499,8 @@ async function runTurn(session, turnContext, input) {
4298
4499
  });
4299
4500
  } finally {
4300
4501
  session.clearActiveTurn(turnId);
4502
+ globalEphemeralWorkspace.cleanupTurn(turnId);
4503
+ globalEphemeralWorkspace.cleanRootResidue(turnContext.environment.cwd);
4301
4504
  }
4302
4505
  }
4303
4506
 
@@ -5238,8 +5441,8 @@ class McpClient {
5238
5441
  }
5239
5442
  }
5240
5443
  // src/mcp/manager.ts
5241
- import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6 } from "fs";
5242
- import { resolve as resolve12, dirname as dirname6, join as join6 } from "path";
5444
+ import { existsSync as existsSync13, readFileSync as readFileSync8, writeFileSync as writeFileSync4, mkdirSync as mkdirSync7 } from "fs";
5445
+ import { resolve as resolve12, dirname as dirname6, join as join7 } from "path";
5243
5446
  class McpManager {
5244
5447
  clients = new Map;
5245
5448
  serverConfigs = new Map;
@@ -5274,7 +5477,7 @@ class McpManager {
5274
5477
  }
5275
5478
  async loadConfigFile(filePath) {
5276
5479
  const fullPath = resolve12(filePath);
5277
- if (!existsSync12(fullPath))
5480
+ if (!existsSync13(fullPath))
5278
5481
  return;
5279
5482
  this.loadedConfigFiles.add(fullPath);
5280
5483
  try {
@@ -5529,11 +5732,11 @@ class McpManager {
5529
5732
  saveServerToConfigFile(filePath, name, config) {
5530
5733
  const fullPath = resolve12(filePath);
5531
5734
  const dir = dirname6(fullPath);
5532
- if (!existsSync12(dir)) {
5533
- mkdirSync6(dir, { recursive: true });
5735
+ if (!existsSync13(dir)) {
5736
+ mkdirSync7(dir, { recursive: true });
5534
5737
  }
5535
5738
  let existing = { mcpServers: {} };
5536
- if (existsSync12(fullPath)) {
5739
+ if (existsSync13(fullPath)) {
5537
5740
  try {
5538
5741
  const content = readFileSync8(fullPath, "utf8");
5539
5742
  existing = JSON.parse(content);
@@ -5548,7 +5751,7 @@ class McpManager {
5548
5751
  }
5549
5752
  removeServerFromConfigFile(filePath, name) {
5550
5753
  const fullPath = resolve12(filePath);
5551
- if (!existsSync12(fullPath))
5754
+ if (!existsSync13(fullPath))
5552
5755
  return false;
5553
5756
  try {
5554
5757
  const content = readFileSync8(fullPath, "utf8");
@@ -5578,11 +5781,11 @@ class McpManager {
5578
5781
  }
5579
5782
  }
5580
5783
  getDefaultConfigFile(cwd = process.cwd()) {
5581
- const workspaceConfig = join6(cwd, ".mcp.json");
5582
- if (existsSync12(workspaceConfig))
5784
+ const workspaceConfig = join7(cwd, ".mcp.json");
5785
+ if (existsSync13(workspaceConfig))
5583
5786
  return workspaceConfig;
5584
- const altConfig = join6(cwd, "mcp_config.json");
5585
- if (existsSync12(altConfig))
5787
+ const altConfig = join7(cwd, "mcp_config.json");
5788
+ if (existsSync13(altConfig))
5586
5789
  return altConfig;
5587
5790
  return workspaceConfig;
5588
5791
  }
@@ -5604,30 +5807,30 @@ class McpManager {
5604
5807
  import { resolve as resolve14 } from "path";
5605
5808
 
5606
5809
  // src/mcp/servers/chrome-devtools/launcher.ts
5607
- import { existsSync as existsSync13, mkdirSync as mkdirSync7, rmSync } from "fs";
5608
- import { join as join7 } from "path";
5609
- import { tmpdir } from "os";
5810
+ import { existsSync as existsSync14, mkdirSync as mkdirSync8, rmSync as rmSync2 } from "fs";
5811
+ import { join as join8 } from "path";
5812
+ import { tmpdir as tmpdir2 } from "os";
5610
5813
  class BrowserLauncher {
5611
5814
  proc = null;
5612
5815
  tempUserDataDir = null;
5613
5816
  wsDebuggerUrl = null;
5614
5817
  port = 0;
5615
5818
  static findBrowserExecutable() {
5616
- if (process.env.CHROME_PATH && existsSync13(process.env.CHROME_PATH)) {
5819
+ if (process.env.CHROME_PATH && existsSync14(process.env.CHROME_PATH)) {
5617
5820
  return process.env.CHROME_PATH;
5618
5821
  }
5619
5822
  if (process.platform === "win32") {
5620
5823
  const candidates = [
5621
5824
  "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
5622
5825
  "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
5623
- join7(process.env.LOCALAPPDATA || "", "Google\\Chrome\\Application\\chrome.exe"),
5826
+ join8(process.env.LOCALAPPDATA || "", "Google\\Chrome\\Application\\chrome.exe"),
5624
5827
  "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
5625
5828
  "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
5626
5829
  "C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe",
5627
- join7(process.env.LOCALAPPDATA || "", "BraveSoftware\\Brave-Browser\\Application\\brave.exe")
5830
+ join8(process.env.LOCALAPPDATA || "", "BraveSoftware\\Brave-Browser\\Application\\brave.exe")
5628
5831
  ];
5629
5832
  for (const path of candidates) {
5630
- if (path && existsSync13(path))
5833
+ if (path && existsSync14(path))
5631
5834
  return path;
5632
5835
  }
5633
5836
  } else if (process.platform === "darwin") {
@@ -5638,7 +5841,7 @@ class BrowserLauncher {
5638
5841
  "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
5639
5842
  ];
5640
5843
  for (const path of candidates) {
5641
- if (existsSync13(path))
5844
+ if (existsSync14(path))
5642
5845
  return path;
5643
5846
  }
5644
5847
  } else {
@@ -5651,7 +5854,7 @@ class BrowserLauncher {
5651
5854
  "/usr/bin/microsoft-edge"
5652
5855
  ];
5653
5856
  for (const path of candidates) {
5654
- if (existsSync13(path))
5857
+ if (existsSync14(path))
5655
5858
  return path;
5656
5859
  }
5657
5860
  }
@@ -5663,8 +5866,8 @@ class BrowserLauncher {
5663
5866
  throw new Error("No supported browser (Google Chrome, Chromium, MS Edge, Brave) found on this machine. Please install Chrome or specify CHROME_PATH.");
5664
5867
  }
5665
5868
  this.port = options.port || 9200 + Math.floor(Math.random() * 500);
5666
- this.tempUserDataDir = options.userDataDir || join7(tmpdir(), `groupy_chrome_${Date.now()}_${Math.random().toString(36).slice(2)}`);
5667
- mkdirSync7(this.tempUserDataDir, { recursive: true });
5869
+ this.tempUserDataDir = options.userDataDir || join8(tmpdir2(), `groupy_chrome_${Date.now()}_${Math.random().toString(36).slice(2)}`);
5870
+ mkdirSync8(this.tempUserDataDir, { recursive: true });
5668
5871
  const isHeadless = options.headless ?? true;
5669
5872
  const launchArgs = [
5670
5873
  executable,
@@ -5741,9 +5944,9 @@ class BrowserLauncher {
5741
5944
  }
5742
5945
  this.proc = null;
5743
5946
  }
5744
- if (this.tempUserDataDir && existsSync13(this.tempUserDataDir)) {
5947
+ if (this.tempUserDataDir && existsSync14(this.tempUserDataDir)) {
5745
5948
  try {
5746
- rmSync(this.tempUserDataDir, { recursive: true, force: true });
5949
+ rmSync2(this.tempUserDataDir, { recursive: true, force: true });
5747
5950
  } catch {}
5748
5951
  this.tempUserDataDir = null;
5749
5952
  }
@@ -6102,7 +6305,7 @@ class DomSnapshotEngine {
6102
6305
  }
6103
6306
  }
6104
6307
  // src/mcp/servers/chrome-devtools/controller.ts
6105
- import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync8 } from "fs";
6308
+ import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync9 } from "fs";
6106
6309
  import { dirname as dirname7, resolve as resolve13 } from "path";
6107
6310
  class ChromeDevToolsController {
6108
6311
  launcher = new BrowserLauncher;
@@ -6253,7 +6456,7 @@ class ChromeDevToolsController {
6253
6456
  const snapshot = await DomSnapshotEngine.captureSnapshot(cdp, params.verbose);
6254
6457
  if (params.filePath) {
6255
6458
  const fullPath = resolve13(params.filePath);
6256
- mkdirSync8(dirname7(fullPath), { recursive: true });
6459
+ mkdirSync9(dirname7(fullPath), { recursive: true });
6257
6460
  writeFileSync5(fullPath, snapshot.textSnapshot, "utf8");
6258
6461
  return `Snapshot saved to ${params.filePath} (${snapshot.elementsCount} indexed elements)`;
6259
6462
  }
@@ -6282,7 +6485,7 @@ class ChromeDevToolsController {
6282
6485
  const base64Data = res.data;
6283
6486
  if (params.filePath) {
6284
6487
  const fullPath = resolve13(params.filePath);
6285
- mkdirSync8(dirname7(fullPath), { recursive: true });
6488
+ mkdirSync9(dirname7(fullPath), { recursive: true });
6286
6489
  writeFileSync5(fullPath, Buffer.from(base64Data, "base64"));
6287
6490
  return { format, filePath: params.filePath };
6288
6491
  }
@@ -6427,7 +6630,7 @@ class ChromeDevToolsController {
6427
6630
  const value = res.result?.value;
6428
6631
  if (params.filePath) {
6429
6632
  const fullPath = resolve13(params.filePath);
6430
- mkdirSync8(dirname7(fullPath), { recursive: true });
6633
+ mkdirSync9(dirname7(fullPath), { recursive: true });
6431
6634
  writeFileSync5(fullPath, JSON.stringify(value, null, 2), "utf8");
6432
6635
  return `Script output saved to ${params.filePath}`;
6433
6636
  }
@@ -7581,7 +7784,7 @@ import { resolve as resolve17 } from "path";
7581
7784
  // src/mcp/servers/sqlite/db-engine.ts
7582
7785
  import { Database as Database2 } from "bun:sqlite";
7583
7786
  import { resolve as resolve16, isAbsolute } from "path";
7584
- import { readdirSync as readdirSync5 } from "fs";
7787
+ import { readdirSync as readdirSync6 } from "fs";
7585
7788
 
7586
7789
  class SqliteEngine {
7587
7790
  connections = new Map;
@@ -7611,7 +7814,7 @@ class SqliteEngine {
7611
7814
  }
7612
7815
  autoDiscoverDatabase() {
7613
7816
  try {
7614
- const files = readdirSync5(process.cwd());
7817
+ const files = readdirSync6(process.cwd());
7615
7818
  const dbFile = files.find((f) => f.endsWith(".sqlite") || f.endsWith(".sqlite3") || f.endsWith(".db"));
7616
7819
  return dbFile ? resolve16(process.cwd(), dbFile) : null;
7617
7820
  } catch {
@@ -8115,8 +8318,8 @@ function verifyTaskAction(assertion, payload) {
8115
8318
  }
8116
8319
  }
8117
8320
  // src/agents/roles.ts
8118
- import { existsSync as existsSync15, readdirSync as readdirSync6, readFileSync as readFileSync9 } from "fs";
8119
- import { resolve as resolve18, join as join8 } from "path";
8321
+ import { existsSync as existsSync16, readdirSync as readdirSync7, readFileSync as readFileSync9 } from "fs";
8322
+ import { resolve as resolve18, join as join9 } from "path";
8120
8323
 
8121
8324
  class AgentRoleRegistry {
8122
8325
  roles = new Map;
@@ -8201,13 +8404,13 @@ class AgentRoleRegistry {
8201
8404
  }
8202
8405
  loadRolesFromDir(dirPath) {
8203
8406
  const fullPath = resolve18(dirPath);
8204
- if (!existsSync15(fullPath))
8407
+ if (!existsSync16(fullPath))
8205
8408
  return;
8206
- const entries = readdirSync6(fullPath);
8409
+ const entries = readdirSync7(fullPath);
8207
8410
  for (const entry of entries) {
8208
8411
  if (entry.endsWith(".json")) {
8209
8412
  try {
8210
- const content = readFileSync9(join8(fullPath, entry), "utf8");
8413
+ const content = readFileSync9(join9(fullPath, entry), "utf8");
8211
8414
  const parsed = JSON.parse(content);
8212
8415
  if (parsed.name && parsed.systemPrompt) {
8213
8416
  this.registerRole(parsed);
@@ -8237,7 +8440,7 @@ class AgentRoleRegistry {
8237
8440
  // src/agents/graph-store.ts
8238
8441
  import { Database as Database3 } from "bun:sqlite";
8239
8442
  import { resolve as resolve19 } from "path";
8240
- import { existsSync as existsSync16, mkdirSync as mkdirSync9 } from "fs";
8443
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10 } from "fs";
8241
8444
  class AgentGraphStore {
8242
8445
  db;
8243
8446
  constructor(dbPathOrDb) {
@@ -8247,8 +8450,8 @@ class AgentGraphStore {
8247
8450
  const dbPath = dbPathOrDb || getAgentGraphDbPath();
8248
8451
  if (dbPath !== ":memory:") {
8249
8452
  const dir = resolve19(dbPath, "..");
8250
- if (!existsSync16(dir)) {
8251
- mkdirSync9(dir, { recursive: true });
8453
+ if (!existsSync17(dir)) {
8454
+ mkdirSync10(dir, { recursive: true });
8252
8455
  }
8253
8456
  }
8254
8457
  this.db = new Database3(dbPath);
@@ -8670,7 +8873,7 @@ function registerMultiAgentTools(router2, spawner) {
8670
8873
  }
8671
8874
  // src/storage/sqlite-store.ts
8672
8875
  import { Database as Database4 } from "bun:sqlite";
8673
- import { existsSync as existsSync17, mkdirSync as mkdirSync10 } from "fs";
8876
+ import { existsSync as existsSync18, mkdirSync as mkdirSync11 } from "fs";
8674
8877
  import { dirname as dirname8 } from "path";
8675
8878
  class SqliteThreadStore {
8676
8879
  db;
@@ -8678,8 +8881,8 @@ class SqliteThreadStore {
8678
8881
  const effectivePath = dbPath || this.getDefaultDbPath();
8679
8882
  if (effectivePath !== ":memory:") {
8680
8883
  const dir = dirname8(effectivePath);
8681
- if (!existsSync17(dir)) {
8682
- mkdirSync10(dir, { recursive: true });
8884
+ if (!existsSync18(dir)) {
8885
+ mkdirSync11(dir, { recursive: true });
8683
8886
  }
8684
8887
  }
8685
8888
  this.db = new Database4(effectivePath);
@@ -8911,8 +9114,8 @@ class SessionPersistenceManager {
8911
9114
  }
8912
9115
  }
8913
9116
  // src/skills/loader.ts
8914
- import { existsSync as existsSync18, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "fs";
8915
- import { resolve as resolve20, join as join9 } from "path";
9117
+ import { existsSync as existsSync19, readdirSync as readdirSync8, readFileSync as readFileSync10 } from "fs";
9118
+ import { resolve as resolve20, join as join10 } from "path";
8916
9119
  import { homedir as homedir3 } from "os";
8917
9120
  var __dirname = "/home/runner/work/agent-cli/agent-cli/src/skills";
8918
9121
 
@@ -8983,7 +9186,7 @@ class SkillsLoader {
8983
9186
  resolve20(cwd, "skills")
8984
9187
  ];
8985
9188
  for (const cand of candidates) {
8986
- if (existsSync18(cand) && !roots.includes(cand)) {
9189
+ if (existsSync19(cand) && !roots.includes(cand)) {
8987
9190
  roots.push(cand);
8988
9191
  }
8989
9192
  }
@@ -8992,7 +9195,7 @@ class SkillsLoader {
8992
9195
  roots.push(getGlobalSkillsDir(), resolve20(homedir3(), ".gemini", "config", "skills"));
8993
9196
  }
8994
9197
  roots.push(...this.customRoots.map((r) => resolve20(r)));
8995
- return roots.filter((r) => existsSync18(r));
9198
+ return roots.filter((r) => existsSync19(r));
8996
9199
  }
8997
9200
  discoverSkills(cwd, options) {
8998
9201
  return this.listSkills(cwd, options);
@@ -9008,12 +9211,12 @@ class SkillsLoader {
9008
9211
  const discovered = new Map;
9009
9212
  for (const root of roots) {
9010
9213
  try {
9011
- const entries = readdirSync7(root, { withFileTypes: true });
9214
+ const entries = readdirSync8(root, { withFileTypes: true });
9012
9215
  for (const entry of entries) {
9013
9216
  if (entry.isDirectory()) {
9014
- const skillDir = join9(root, entry.name);
9015
- const skillFilePath = join9(skillDir, "SKILL.md");
9016
- if (existsSync18(skillFilePath)) {
9217
+ const skillDir = join10(root, entry.name);
9218
+ const skillFilePath = join10(skillDir, "SKILL.md");
9219
+ if (existsSync19(skillFilePath)) {
9017
9220
  const meta = this.parseSkillFrontmatter(skillFilePath, entry.name, root, cwd);
9018
9221
  if (meta && !discovered.has(meta.name)) {
9019
9222
  meta.enabled = !this.isSkillDisabled(meta.name);
@@ -9026,7 +9229,7 @@ class SkillsLoader {
9026
9229
  }
9027
9230
  } catch {}
9028
9231
  }
9029
- const result = Array.from(discovered.values());
9232
+ const result = Array.from(discovered.values()).sort((a, b) => a.name.localeCompare(b.name));
9030
9233
  this.skillsCache.set(cacheKey, { timestamp: now, skills: result });
9031
9234
  return result;
9032
9235
  }
@@ -9115,10 +9318,10 @@ class SkillsLoader {
9115
9318
  const skills = this.listSkills(cwd, { includeDisabled: false });
9116
9319
  if (skills.length === 0)
9117
9320
  return "";
9118
- const workspaceSkills = skills.filter((s) => s.scope === "workspace");
9119
- const builtInSkills = skills.filter((s) => s.scope === "built-in");
9120
- const otherSkills = skills.filter((s) => s.scope !== "workspace" && s.scope !== "built-in");
9121
- const selectedSkills = [...workspaceSkills, ...builtInSkills, ...otherSkills].slice(0, 150);
9321
+ const workspaceSkills = skills.filter((s) => s.scope === "workspace").sort((a, b) => a.name.localeCompare(b.name));
9322
+ const builtInSkills = skills.filter((s) => s.scope === "built-in").sort((a, b) => a.name.localeCompare(b.name));
9323
+ const otherSkills = skills.filter((s) => s.scope !== "workspace" && s.scope !== "built-in").sort((a, b) => a.name.localeCompare(b.name));
9324
+ const selectedSkills = [...workspaceSkills, ...builtInSkills, ...otherSkills].slice(0, 300);
9122
9325
  const lines = selectedSkills.map((s) => {
9123
9326
  const desc = s.shortDescription || s.description;
9124
9327
  return `- **${s.name}**: ${desc}`;
@@ -9135,8 +9338,8 @@ When tackling complex specialized tasks that match any of these skills, autonomo
9135
9338
  }
9136
9339
  }
9137
9340
  // src/memories/store.ts
9138
- import { existsSync as existsSync19, readFileSync as readFileSync11, writeFileSync as writeFileSync6, mkdirSync as mkdirSync11, readdirSync as readdirSync8 } from "fs";
9139
- import { resolve as resolve21, join as join10, basename, dirname as dirname9 } from "path";
9341
+ import { existsSync as existsSync20, readFileSync as readFileSync11, writeFileSync as writeFileSync6, mkdirSync as mkdirSync12, readdirSync as readdirSync9 } from "fs";
9342
+ import { resolve as resolve21, join as join11, basename, dirname as dirname9 } from "path";
9140
9343
  import { createHash } from "crypto";
9141
9344
  class MemoryStore {
9142
9345
  globalPath;
@@ -9148,7 +9351,7 @@ class MemoryStore {
9148
9351
  findProjectRoot(cwd) {
9149
9352
  let current = resolve21(cwd);
9150
9353
  while (true) {
9151
- if (existsSync19(join10(current, ".git"))) {
9354
+ if (existsSync20(join11(current, ".git"))) {
9152
9355
  return current;
9153
9356
  }
9154
9357
  const parent = dirname9(current);
@@ -9167,24 +9370,24 @@ class MemoryStore {
9167
9370
  getProjectMemoryDir(cwd) {
9168
9371
  if (this.customWorkspacePath) {
9169
9372
  const dir2 = resolve21(this.customWorkspacePath);
9170
- if (!existsSync19(dir2)) {
9373
+ if (!existsSync20(dir2)) {
9171
9374
  try {
9172
- mkdirSync11(dir2, { recursive: true });
9375
+ mkdirSync12(dir2, { recursive: true });
9173
9376
  } catch {}
9174
9377
  }
9175
9378
  return dir2;
9176
9379
  }
9177
9380
  const slug = this.getProjectSlug(cwd);
9178
- const dir = join10(getProjectsDir(), slug, "memory");
9179
- if (!existsSync19(dir)) {
9381
+ const dir = join11(getProjectsDir(), slug, "memory");
9382
+ if (!existsSync20(dir)) {
9180
9383
  try {
9181
- mkdirSync11(dir, { recursive: true });
9384
+ mkdirSync12(dir, { recursive: true });
9182
9385
  } catch {}
9183
9386
  }
9184
9387
  return dir;
9185
9388
  }
9186
9389
  getMemoryIndexPath(cwd) {
9187
- return join10(this.getProjectMemoryDir(cwd), "MEMORY.md");
9390
+ return join11(this.getProjectMemoryDir(cwd), "MEMORY.md");
9188
9391
  }
9189
9392
  normalizeCategory(raw) {
9190
9393
  const cat = raw.toLowerCase().trim();
@@ -9203,7 +9406,7 @@ class MemoryStore {
9203
9406
  const sanitizedName = params.name.toLowerCase().trim().replace(/[^a-z0-9_-]/g, "_").replace(/^_+|_+$/g, "") || `note_${Date.now()}`;
9204
9407
  const memoryDir = this.getProjectMemoryDir(params.cwd);
9205
9408
  const fileName = `${type}_${sanitizedName}.md`;
9206
- const filePath = join10(memoryDir, fileName);
9409
+ const filePath = join11(memoryDir, fileName);
9207
9410
  const nowIso = new Date().toISOString();
9208
9411
  const cleanContent = params.content.trim();
9209
9412
  const desc = (params.description || cleanContent.split(`
@@ -9238,17 +9441,17 @@ class MemoryStore {
9238
9441
  }
9239
9442
  readTopicMemory(topicNameOrFile, cwd) {
9240
9443
  const memoryDir = this.getProjectMemoryDir(cwd);
9241
- let targetPath = join10(memoryDir, topicNameOrFile);
9242
- if (!existsSync19(targetPath)) {
9444
+ let targetPath = join11(memoryDir, topicNameOrFile);
9445
+ if (!existsSync20(targetPath)) {
9243
9446
  if (!topicNameOrFile.endsWith(".md")) {
9244
- targetPath = join10(memoryDir, `${topicNameOrFile}.md`);
9447
+ targetPath = join11(memoryDir, `${topicNameOrFile}.md`);
9245
9448
  }
9246
9449
  }
9247
- if (!existsSync19(targetPath)) {
9248
- const files = readdirSync8(memoryDir);
9450
+ if (!existsSync20(targetPath)) {
9451
+ const files = readdirSync9(memoryDir);
9249
9452
  const match = files.find((f) => f.includes(topicNameOrFile));
9250
9453
  if (match) {
9251
- targetPath = join10(memoryDir, match);
9454
+ targetPath = join11(memoryDir, match);
9252
9455
  } else {
9253
9456
  return null;
9254
9457
  }
@@ -9309,12 +9512,12 @@ class MemoryStore {
9309
9512
  }
9310
9513
  syncMemoryIndex(cwd) {
9311
9514
  const memoryDir = this.getProjectMemoryDir(cwd);
9312
- const indexPath = join10(memoryDir, "MEMORY.md");
9313
- const files = existsSync19(memoryDir) ? readdirSync8(memoryDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md") : [];
9515
+ const indexPath = join11(memoryDir, "MEMORY.md");
9516
+ const files = existsSync20(memoryDir) ? readdirSync9(memoryDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md") : [];
9314
9517
  const items2 = [];
9315
9518
  for (const f of files) {
9316
9519
  try {
9317
- const full = join10(memoryDir, f);
9520
+ const full = join11(memoryDir, f);
9318
9521
  const parsed = this.parseTopicFile(readFileSync11(full, "utf8"), full);
9319
9522
  items2.push({
9320
9523
  type: parsed.type,
@@ -9341,7 +9544,7 @@ class MemoryStore {
9341
9544
  }
9342
9545
  loadMemoryIndex(cwd) {
9343
9546
  const indexPath = this.getMemoryIndexPath(cwd);
9344
- if (!existsSync19(indexPath))
9547
+ if (!existsSync20(indexPath))
9345
9548
  return "";
9346
9549
  try {
9347
9550
  const raw = readFileSync11(indexPath, "utf8");
@@ -9357,13 +9560,13 @@ class MemoryStore {
9357
9560
  }
9358
9561
  listProjectMemories(cwd) {
9359
9562
  const memoryDir = this.getProjectMemoryDir(cwd);
9360
- if (!existsSync19(memoryDir))
9563
+ if (!existsSync20(memoryDir))
9361
9564
  return [];
9362
- const files = readdirSync8(memoryDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md");
9565
+ const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md");
9363
9566
  const list = [];
9364
9567
  for (const f of files) {
9365
9568
  try {
9366
- const full = join10(memoryDir, f);
9569
+ const full = join11(memoryDir, f);
9367
9570
  list.push(this.parseTopicFile(readFileSync11(full, "utf8"), full));
9368
9571
  } catch {}
9369
9572
  }
@@ -9541,8 +9744,8 @@ async function removeWorktreeGit(repoRoot, worktreePath, deleteBranch = false) {
9541
9744
  return { success: true };
9542
9745
  }
9543
9746
  // src/worktree/manager.ts
9544
- import { resolve as resolve23, join as join11 } from "path";
9545
- import { existsSync as existsSync20, mkdirSync as mkdirSync12, writeFileSync as writeFileSync7, readFileSync as readFileSync12 } from "fs";
9747
+ import { resolve as resolve23, join as join12 } from "path";
9748
+ import { existsSync as existsSync21, mkdirSync as mkdirSync13, writeFileSync as writeFileSync7, readFileSync as readFileSync12 } from "fs";
9546
9749
  var DEFAULT_WORKTREE_KEEP_COUNT = 15;
9547
9750
 
9548
9751
  class WorktreeManager {
@@ -9566,15 +9769,15 @@ class WorktreeManager {
9566
9769
  const branchName = options.branch || `groupy/${taskId}`;
9567
9770
  const targetDir = options.worktreePath || (this.baseStorageDir ? resolve23(this.baseStorageDir, branchName.replace(/\//g, "_")) : resolve23(repoRoot, ".groupy", "worktrees", branchName.replace(/\//g, "_")));
9568
9771
  const worktreeParent = resolve23(targetDir, "..");
9569
- if (!existsSync20(worktreeParent)) {
9570
- mkdirSync12(worktreeParent, { recursive: true });
9772
+ if (!existsSync21(worktreeParent)) {
9773
+ mkdirSync13(worktreeParent, { recursive: true });
9571
9774
  }
9572
9775
  const baseBranch = options.baseBranch || await getCurrentBranch(repoRoot);
9573
9776
  const result = await createWorktreeGit(repoRoot, targetDir, branchName, baseBranch);
9574
9777
  if (!result.success) {
9575
9778
  throw new Error(`Failed to create git worktree: ${result.error}`);
9576
9779
  }
9577
- const metaPath = join11(targetDir, "groupy-thread.json");
9780
+ const metaPath = join12(targetDir, "groupy-thread.json");
9578
9781
  try {
9579
9782
  writeFileSync7(metaPath, JSON.stringify({
9580
9783
  version: 1,
@@ -9600,8 +9803,8 @@ class WorktreeManager {
9600
9803
  return [];
9601
9804
  const worktrees = await listWorktreesGit(repoRoot);
9602
9805
  return worktrees.map((wt) => {
9603
- const metaPath = join11(wt.path, "groupy-thread.json");
9604
- if (existsSync20(metaPath)) {
9806
+ const metaPath = join12(wt.path, "groupy-thread.json");
9807
+ if (existsSync21(metaPath)) {
9605
9808
  try {
9606
9809
  const raw = JSON.parse(readFileSync12(metaPath, "utf8"));
9607
9810
  return { ...wt, threadId: raw.ownerThreadId || raw.threadId };
@@ -11331,6 +11534,8 @@ export {
11331
11534
  CodeModeRuntime,
11332
11535
  ContextWindowExceededError,
11333
11536
  CredentialsStore,
11537
+ DEFAULT_AUTO_COMPACT_THRESHOLD_TOKENS,
11538
+ DEFAULT_MAX_CONTEXT_TOKENS,
11334
11539
  DEFAULT_WORKTREE_KEEP_COUNT,
11335
11540
  DefaultModelClientSession,
11336
11541
  DomSnapshotEngine,
@@ -11378,6 +11583,7 @@ export {
11378
11583
  WorktreeManager,
11379
11584
  applyPatchTool,
11380
11585
  askQuestionTool,
11586
+ buildStructuredSystemPrompt,
11381
11587
  buildSystemPrompt,
11382
11588
  captureWorldState,
11383
11589
  compactHistory,