@pikaa-ai/pikaa 0.3.19 → 0.3.21

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
  }
@@ -3807,13 +3938,13 @@ function formatWorldStatePrompt(state) {
3807
3938
  `);
3808
3939
  }
3809
3940
  // src/prompts/loader.ts
3810
- import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
3811
- 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";
3812
3943
  import { homedir as homedir2 } from "os";
3813
3944
  class PromptTemplateLoader {
3814
3945
  builtInTemplatesDir;
3815
3946
  constructor(builtInDir) {
3816
- this.builtInTemplatesDir = builtInDir || resolve10(join4(import.meta.dir, "..", "..", "templates"));
3947
+ this.builtInTemplatesDir = builtInDir || resolve10(join5(import.meta.dir, "..", "..", "templates"));
3817
3948
  }
3818
3949
  loadTemplate(relativePath, variables = {}, cwd) {
3819
3950
  const rawContent = this.resolveTemplateContent(relativePath, cwd);
@@ -3822,27 +3953,27 @@ class PromptTemplateLoader {
3822
3953
  resolveTemplateContent(relativePath, cwd) {
3823
3954
  const normalizedRel = relativePath.replace(/^\/+/, "");
3824
3955
  if (cwd) {
3825
- const workspacePath = join4(cwd, ".agents", "templates", normalizedRel);
3826
- if (existsSync10(workspacePath)) {
3956
+ const workspacePath = join5(cwd, ".agents", "templates", normalizedRel);
3957
+ if (existsSync11(workspacePath)) {
3827
3958
  try {
3828
3959
  return readFileSync6(workspacePath, "utf-8");
3829
3960
  } catch {}
3830
3961
  }
3831
3962
  }
3832
- const globalPath = join4(getGlobalTemplatesDir(), normalizedRel);
3833
- if (existsSync10(globalPath)) {
3963
+ const globalPath = join5(getGlobalTemplatesDir(), normalizedRel);
3964
+ if (existsSync11(globalPath)) {
3834
3965
  try {
3835
3966
  return readFileSync6(globalPath, "utf-8");
3836
3967
  } catch {}
3837
3968
  }
3838
- const legacyGlobalPath = join4(homedir2(), ".groupy", "templates", normalizedRel);
3839
- if (existsSync10(legacyGlobalPath)) {
3969
+ const legacyGlobalPath = join5(homedir2(), ".groupy", "templates", normalizedRel);
3970
+ if (existsSync11(legacyGlobalPath)) {
3840
3971
  try {
3841
3972
  return readFileSync6(legacyGlobalPath, "utf-8");
3842
3973
  } catch {}
3843
3974
  }
3844
- const builtInPath = join4(this.builtInTemplatesDir, normalizedRel);
3845
- if (existsSync10(builtInPath)) {
3975
+ const builtInPath = join5(this.builtInTemplatesDir, normalizedRel);
3976
+ if (existsSync11(builtInPath)) {
3846
3977
  try {
3847
3978
  return readFileSync6(builtInPath, "utf-8");
3848
3979
  } catch {}
@@ -3859,8 +3990,8 @@ class PromptTemplateLoader {
3859
3990
  var globalPromptLoader = new PromptTemplateLoader;
3860
3991
 
3861
3992
  // src/prompts/agents-md.ts
3862
- import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
3863
- 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";
3864
3995
  var DEFAULT_AGENTS_MD_FILENAMES = [
3865
3996
  "AGENTS.override.md",
3866
3997
  "AGENTS.md",
@@ -3877,7 +4008,7 @@ class AgentsMdLoader {
3877
4008
  findProjectRoot(startDir) {
3878
4009
  let current = resolve11(startDir);
3879
4010
  while (true) {
3880
- if (existsSync11(join5(current, ".git"))) {
4011
+ if (existsSync12(join6(current, ".git"))) {
3881
4012
  return current;
3882
4013
  }
3883
4014
  const parent = dirname5(current);
@@ -3911,8 +4042,8 @@ class AgentsMdLoader {
3911
4042
  const sourcePaths = [];
3912
4043
  for (const dir of dirHierarchy) {
3913
4044
  for (const filename of fallbackFilenames) {
3914
- const filePath = join5(dir, filename);
3915
- if (existsSync11(filePath)) {
4045
+ const filePath = join6(dir, filename);
4046
+ if (existsSync12(filePath)) {
3916
4047
  try {
3917
4048
  const content = readFileSync7(filePath, "utf-8").trim();
3918
4049
  if (content) {
@@ -3936,81 +4067,141 @@ class AgentsMdLoader {
3936
4067
  var globalAgentsMdLoader = new AgentsMdLoader;
3937
4068
 
3938
4069
  // src/context/instructions.ts
3939
- function buildSystemPrompt(params) {
3940
- 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) {
3941
4077
  const cwd = params.cwd || process.cwd();
3942
4078
  const mode = params.collaborationMode || "default";
3943
- if (params.basePrompt) {
3944
- sections.push(params.basePrompt);
3945
- } else {
4079
+ const blocks = [];
4080
+ let baseContent = params.basePrompt;
4081
+ if (!baseContent) {
3946
4082
  const templateName = params.basePromptTemplate || "base/groupy_prompt.md";
3947
- const baseContent = globalPromptLoader.loadTemplate(templateName, {}, cwd);
3948
- if (baseContent) {
3949
- sections.push(baseContent.trim());
3950
- } else {
3951
- sections.push("You are Groupy, an expert autonomous AI coding assistant. You think step-by-step, act surgically, and write clean, correct code.");
3952
- }
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.";
3953
4084
  }
4085
+ blocks.push({
4086
+ tag: "system_identity",
4087
+ content: wrapXmlTag("system_identity", baseContent),
4088
+ cacheable: true
4089
+ });
3954
4090
  if (params.personality) {
3955
4091
  const personalityContent = globalPromptLoader.loadTemplate(`personalities/${params.personality}.md`, {}, cwd);
3956
4092
  if (personalityContent) {
3957
- sections.push(personalityContent.trim());
4093
+ blocks.push({
4094
+ tag: "personality",
4095
+ content: wrapXmlTag("personality", personalityContent, { kind: params.personality }),
4096
+ cacheable: true
4097
+ });
3958
4098
  }
3959
4099
  }
3960
4100
  if (params.isOrchestrator) {
3961
4101
  const orchestratorContent = globalPromptLoader.loadTemplate("agents/orchestrator.md", {}, cwd);
3962
4102
  if (orchestratorContent) {
3963
- sections.push(orchestratorContent.trim());
4103
+ blocks.push({
4104
+ tag: "orchestrator_guidelines",
4105
+ content: wrapXmlTag("orchestrator_guidelines", orchestratorContent),
4106
+ cacheable: true
4107
+ });
3964
4108
  }
3965
4109
  }
3966
- const modeTemplate = globalPromptLoader.loadTemplate(`modes/${mode}.md`, {
3967
- KNOWN_MODE_NAMES: "default, plan, review"
3968
- }, cwd);
4110
+ const modeTemplate = globalPromptLoader.loadTemplate(`modes/${mode}.md`, { KNOWN_MODE_NAMES: "default, plan, review" }, cwd);
3969
4111
  if (modeTemplate) {
3970
- sections.push(modeTemplate.trim());
4112
+ blocks.push({
4113
+ tag: "collaboration_mode",
4114
+ content: wrapXmlTag("collaboration_mode", modeTemplate, { name: mode }),
4115
+ cacheable: true
4116
+ });
3971
4117
  }
3972
4118
  if (params.sandboxMode) {
3973
- const sandboxTemplate = globalPromptLoader.loadTemplate(`permissions/sandbox_mode/${params.sandboxMode}.md`, {
3974
- network_access: params.networkAccess ? "enabled" : "disabled"
3975
- }, cwd);
4119
+ const sandboxTemplate = globalPromptLoader.loadTemplate(`permissions/sandbox_mode/${params.sandboxMode}.md`, { network_access: params.networkAccess ? "enabled" : "disabled" }, cwd);
3976
4120
  if (sandboxTemplate) {
3977
- sections.push(sandboxTemplate.trim());
4121
+ blocks.push({
4122
+ tag: "sandbox_policy",
4123
+ content: wrapXmlTag("sandbox_policy", sandboxTemplate, { mode: params.sandboxMode }),
4124
+ cacheable: true
4125
+ });
3978
4126
  }
3979
4127
  }
3980
4128
  if (params.approvalPolicy) {
3981
4129
  const approvalTemplate = globalPromptLoader.loadTemplate(`permissions/approval_policy/${params.approvalPolicy}.md`, {}, cwd);
3982
4130
  if (approvalTemplate) {
3983
- sections.push(approvalTemplate.trim());
4131
+ blocks.push({
4132
+ tag: "approval_policy",
4133
+ content: wrapXmlTag("approval_policy", approvalTemplate, { policy: params.approvalPolicy }),
4134
+ cacheable: true
4135
+ });
3984
4136
  }
3985
4137
  }
3986
4138
  const projectInstructions = globalAgentsMdLoader.loadProjectInstructions(cwd);
3987
4139
  if (projectInstructions) {
3988
- sections.push(`## Project Instructions (AGENTS.md)
3989
-
3990
- ${projectInstructions.content.trim()}`);
4140
+ blocks.push({
4141
+ tag: "project_instructions",
4142
+ content: wrapXmlTag("project_instructions", projectInstructions.content, { source: "AGENTS.md" }),
4143
+ cacheable: true
4144
+ });
3991
4145
  }
3992
4146
  if (params.memoriesPrompt) {
3993
- sections.push(params.memoriesPrompt.trim());
4147
+ blocks.push({
4148
+ tag: "persistent_memories",
4149
+ content: wrapXmlTag("persistent_memories", params.memoriesPrompt),
4150
+ cacheable: true
4151
+ });
3994
4152
  }
3995
4153
  if (params.skillsPrompt) {
3996
- sections.push(params.skillsPrompt.trim());
4154
+ blocks.push({
4155
+ tag: "domain_skills",
4156
+ content: wrapXmlTag("domain_skills", params.skillsPrompt),
4157
+ cacheable: true
4158
+ });
3997
4159
  }
3998
4160
  if (params.mcpPrompt) {
3999
- sections.push(params.mcpPrompt.trim());
4161
+ blocks.push({
4162
+ tag: "mcp_servers",
4163
+ content: wrapXmlTag("mcp_servers", params.mcpPrompt),
4164
+ cacheable: true
4165
+ });
4000
4166
  }
4001
4167
  if (params.developerInstructions) {
4002
- sections.push(`## Developer Instructions
4003
- ${params.developerInstructions}`);
4168
+ blocks.push({
4169
+ tag: "developer_instructions",
4170
+ content: wrapXmlTag("developer_instructions", params.developerInstructions),
4171
+ cacheable: true
4172
+ });
4004
4173
  }
4174
+ const dynamicBlocks = [];
4005
4175
  if (params.worldStatePrompt) {
4006
- sections.push(`## Environment Context
4007
- ${params.worldStatePrompt}`);
4176
+ dynamicBlocks.push({
4177
+ tag: "runtime_environment",
4178
+ content: wrapXmlTag("runtime_environment", params.worldStatePrompt),
4179
+ cacheable: false
4180
+ });
4008
4181
  }
4009
- return sections.join(`
4182
+ const staticPrefix = blocks.map((b) => b.content).join(`
4183
+
4184
+ `);
4185
+ const dynamicSuffix = dynamicBlocks.map((b) => b.content).join(`
4010
4186
 
4011
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;
4012
4201
  }
4013
4202
  // src/context/compactor.ts
4203
+ var DEFAULT_MAX_CONTEXT_TOKENS = 256000;
4204
+ var DEFAULT_AUTO_COMPACT_THRESHOLD_TOKENS = 180000;
4014
4205
  function estimateItemTokens(item) {
4015
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 : "";
4016
4207
  return Math.ceil(text.length / 4) + 4;
@@ -4078,7 +4269,7 @@ async function runTurn(session, turnContext, input) {
4078
4269
  });
4079
4270
  const currentHistory = session.getHistory();
4080
4271
  const estimatedTokens = estimateTotalTokens(currentHistory);
4081
- const maxTokenLimit = 80000;
4272
+ const maxTokenLimit = DEFAULT_AUTO_COMPACT_THRESHOLD_TOKENS;
4082
4273
  if (estimatedTokens > maxTokenLimit) {
4083
4274
  const compacted = compactHistory(currentHistory);
4084
4275
  session.setHistory(compacted);
@@ -4117,6 +4308,7 @@ async function runTurn(session, turnContext, input) {
4117
4308
  let iteration = 0;
4118
4309
  let accumulatedInputTokens = 0;
4119
4310
  let accumulatedOutputTokens = 0;
4311
+ let accumulatedCachedTokens = 0;
4120
4312
  const clientSession = session.modelClient.newSession();
4121
4313
  try {
4122
4314
  while (iteration < turnContext.maxIterations) {
@@ -4133,7 +4325,8 @@ async function runTurn(session, turnContext, input) {
4133
4325
  systemPrompt: effectiveSystemPrompt,
4134
4326
  history: session.getHistory(),
4135
4327
  tools: turnContext.tools,
4136
- signal
4328
+ signal,
4329
+ enablePromptCache: true
4137
4330
  });
4138
4331
  for await (const chunk of stream) {
4139
4332
  if (signal.aborted) {
@@ -4159,6 +4352,8 @@ async function runTurn(session, turnContext, input) {
4159
4352
  iterInputTokens = chunk.inputTokens;
4160
4353
  if (chunk.outputTokens !== undefined)
4161
4354
  iterOutputTokens = chunk.outputTokens;
4355
+ if (chunk.cachedTokens !== undefined)
4356
+ accumulatedCachedTokens += chunk.cachedTokens;
4162
4357
  } else if (chunk.type === "error") {
4163
4358
  throw chunk.error;
4164
4359
  }
@@ -4270,7 +4465,10 @@ async function runTurn(session, turnContext, input) {
4270
4465
  session.addHistoryItem({
4271
4466
  id: `msg_nudge_${Date.now()}`,
4272
4467
  type: "user_message",
4273
- 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.`,
4274
4472
  createdAt: Date.now()
4275
4473
  });
4276
4474
  continue;
@@ -4279,13 +4477,14 @@ async function runTurn(session, turnContext, input) {
4279
4477
  break;
4280
4478
  }
4281
4479
  const totalContextTokens = estimateTotalTokens(session.getHistory()) + Math.ceil(effectiveSystemPrompt.length / 4);
4282
- const maxContextTokens = 128000;
4480
+ const maxContextTokens = DEFAULT_MAX_CONTEXT_TOKENS;
4283
4481
  session.emitEvent({
4284
4482
  type: "TurnCompleted",
4285
4483
  turnId,
4286
4484
  inputTokens: accumulatedInputTokens,
4287
4485
  outputTokens: accumulatedOutputTokens,
4288
4486
  totalTokens: accumulatedInputTokens + accumulatedOutputTokens,
4487
+ cachedTokens: accumulatedCachedTokens > 0 ? accumulatedCachedTokens : undefined,
4289
4488
  contextTokens: totalContextTokens,
4290
4489
  maxContextTokens
4291
4490
  });
@@ -4300,6 +4499,8 @@ async function runTurn(session, turnContext, input) {
4300
4499
  });
4301
4500
  } finally {
4302
4501
  session.clearActiveTurn(turnId);
4502
+ globalEphemeralWorkspace.cleanupTurn(turnId);
4503
+ globalEphemeralWorkspace.cleanRootResidue(turnContext.environment.cwd);
4303
4504
  }
4304
4505
  }
4305
4506
 
@@ -5240,8 +5441,8 @@ class McpClient {
5240
5441
  }
5241
5442
  }
5242
5443
  // src/mcp/manager.ts
5243
- import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6 } from "fs";
5244
- 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";
5245
5446
  class McpManager {
5246
5447
  clients = new Map;
5247
5448
  serverConfigs = new Map;
@@ -5276,7 +5477,7 @@ class McpManager {
5276
5477
  }
5277
5478
  async loadConfigFile(filePath) {
5278
5479
  const fullPath = resolve12(filePath);
5279
- if (!existsSync12(fullPath))
5480
+ if (!existsSync13(fullPath))
5280
5481
  return;
5281
5482
  this.loadedConfigFiles.add(fullPath);
5282
5483
  try {
@@ -5531,11 +5732,11 @@ class McpManager {
5531
5732
  saveServerToConfigFile(filePath, name, config) {
5532
5733
  const fullPath = resolve12(filePath);
5533
5734
  const dir = dirname6(fullPath);
5534
- if (!existsSync12(dir)) {
5535
- mkdirSync6(dir, { recursive: true });
5735
+ if (!existsSync13(dir)) {
5736
+ mkdirSync7(dir, { recursive: true });
5536
5737
  }
5537
5738
  let existing = { mcpServers: {} };
5538
- if (existsSync12(fullPath)) {
5739
+ if (existsSync13(fullPath)) {
5539
5740
  try {
5540
5741
  const content = readFileSync8(fullPath, "utf8");
5541
5742
  existing = JSON.parse(content);
@@ -5550,7 +5751,7 @@ class McpManager {
5550
5751
  }
5551
5752
  removeServerFromConfigFile(filePath, name) {
5552
5753
  const fullPath = resolve12(filePath);
5553
- if (!existsSync12(fullPath))
5754
+ if (!existsSync13(fullPath))
5554
5755
  return false;
5555
5756
  try {
5556
5757
  const content = readFileSync8(fullPath, "utf8");
@@ -5580,11 +5781,11 @@ class McpManager {
5580
5781
  }
5581
5782
  }
5582
5783
  getDefaultConfigFile(cwd = process.cwd()) {
5583
- const workspaceConfig = join6(cwd, ".mcp.json");
5584
- if (existsSync12(workspaceConfig))
5784
+ const workspaceConfig = join7(cwd, ".mcp.json");
5785
+ if (existsSync13(workspaceConfig))
5585
5786
  return workspaceConfig;
5586
- const altConfig = join6(cwd, "mcp_config.json");
5587
- if (existsSync12(altConfig))
5787
+ const altConfig = join7(cwd, "mcp_config.json");
5788
+ if (existsSync13(altConfig))
5588
5789
  return altConfig;
5589
5790
  return workspaceConfig;
5590
5791
  }
@@ -5606,30 +5807,30 @@ class McpManager {
5606
5807
  import { resolve as resolve14 } from "path";
5607
5808
 
5608
5809
  // src/mcp/servers/chrome-devtools/launcher.ts
5609
- import { existsSync as existsSync13, mkdirSync as mkdirSync7, rmSync } from "fs";
5610
- import { join as join7 } from "path";
5611
- 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";
5612
5813
  class BrowserLauncher {
5613
5814
  proc = null;
5614
5815
  tempUserDataDir = null;
5615
5816
  wsDebuggerUrl = null;
5616
5817
  port = 0;
5617
5818
  static findBrowserExecutable() {
5618
- if (process.env.CHROME_PATH && existsSync13(process.env.CHROME_PATH)) {
5819
+ if (process.env.CHROME_PATH && existsSync14(process.env.CHROME_PATH)) {
5619
5820
  return process.env.CHROME_PATH;
5620
5821
  }
5621
5822
  if (process.platform === "win32") {
5622
5823
  const candidates = [
5623
5824
  "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
5624
5825
  "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
5625
- join7(process.env.LOCALAPPDATA || "", "Google\\Chrome\\Application\\chrome.exe"),
5826
+ join8(process.env.LOCALAPPDATA || "", "Google\\Chrome\\Application\\chrome.exe"),
5626
5827
  "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
5627
5828
  "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
5628
5829
  "C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe",
5629
- join7(process.env.LOCALAPPDATA || "", "BraveSoftware\\Brave-Browser\\Application\\brave.exe")
5830
+ join8(process.env.LOCALAPPDATA || "", "BraveSoftware\\Brave-Browser\\Application\\brave.exe")
5630
5831
  ];
5631
5832
  for (const path of candidates) {
5632
- if (path && existsSync13(path))
5833
+ if (path && existsSync14(path))
5633
5834
  return path;
5634
5835
  }
5635
5836
  } else if (process.platform === "darwin") {
@@ -5640,7 +5841,7 @@ class BrowserLauncher {
5640
5841
  "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
5641
5842
  ];
5642
5843
  for (const path of candidates) {
5643
- if (existsSync13(path))
5844
+ if (existsSync14(path))
5644
5845
  return path;
5645
5846
  }
5646
5847
  } else {
@@ -5653,7 +5854,7 @@ class BrowserLauncher {
5653
5854
  "/usr/bin/microsoft-edge"
5654
5855
  ];
5655
5856
  for (const path of candidates) {
5656
- if (existsSync13(path))
5857
+ if (existsSync14(path))
5657
5858
  return path;
5658
5859
  }
5659
5860
  }
@@ -5665,8 +5866,8 @@ class BrowserLauncher {
5665
5866
  throw new Error("No supported browser (Google Chrome, Chromium, MS Edge, Brave) found on this machine. Please install Chrome or specify CHROME_PATH.");
5666
5867
  }
5667
5868
  this.port = options.port || 9200 + Math.floor(Math.random() * 500);
5668
- this.tempUserDataDir = options.userDataDir || join7(tmpdir(), `groupy_chrome_${Date.now()}_${Math.random().toString(36).slice(2)}`);
5669
- 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 });
5670
5871
  const isHeadless = options.headless ?? true;
5671
5872
  const launchArgs = [
5672
5873
  executable,
@@ -5743,9 +5944,9 @@ class BrowserLauncher {
5743
5944
  }
5744
5945
  this.proc = null;
5745
5946
  }
5746
- if (this.tempUserDataDir && existsSync13(this.tempUserDataDir)) {
5947
+ if (this.tempUserDataDir && existsSync14(this.tempUserDataDir)) {
5747
5948
  try {
5748
- rmSync(this.tempUserDataDir, { recursive: true, force: true });
5949
+ rmSync2(this.tempUserDataDir, { recursive: true, force: true });
5749
5950
  } catch {}
5750
5951
  this.tempUserDataDir = null;
5751
5952
  }
@@ -6104,7 +6305,7 @@ class DomSnapshotEngine {
6104
6305
  }
6105
6306
  }
6106
6307
  // src/mcp/servers/chrome-devtools/controller.ts
6107
- import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync8 } from "fs";
6308
+ import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync9 } from "fs";
6108
6309
  import { dirname as dirname7, resolve as resolve13 } from "path";
6109
6310
  class ChromeDevToolsController {
6110
6311
  launcher = new BrowserLauncher;
@@ -6255,7 +6456,7 @@ class ChromeDevToolsController {
6255
6456
  const snapshot = await DomSnapshotEngine.captureSnapshot(cdp, params.verbose);
6256
6457
  if (params.filePath) {
6257
6458
  const fullPath = resolve13(params.filePath);
6258
- mkdirSync8(dirname7(fullPath), { recursive: true });
6459
+ mkdirSync9(dirname7(fullPath), { recursive: true });
6259
6460
  writeFileSync5(fullPath, snapshot.textSnapshot, "utf8");
6260
6461
  return `Snapshot saved to ${params.filePath} (${snapshot.elementsCount} indexed elements)`;
6261
6462
  }
@@ -6284,7 +6485,7 @@ class ChromeDevToolsController {
6284
6485
  const base64Data = res.data;
6285
6486
  if (params.filePath) {
6286
6487
  const fullPath = resolve13(params.filePath);
6287
- mkdirSync8(dirname7(fullPath), { recursive: true });
6488
+ mkdirSync9(dirname7(fullPath), { recursive: true });
6288
6489
  writeFileSync5(fullPath, Buffer.from(base64Data, "base64"));
6289
6490
  return { format, filePath: params.filePath };
6290
6491
  }
@@ -6429,7 +6630,7 @@ class ChromeDevToolsController {
6429
6630
  const value = res.result?.value;
6430
6631
  if (params.filePath) {
6431
6632
  const fullPath = resolve13(params.filePath);
6432
- mkdirSync8(dirname7(fullPath), { recursive: true });
6633
+ mkdirSync9(dirname7(fullPath), { recursive: true });
6433
6634
  writeFileSync5(fullPath, JSON.stringify(value, null, 2), "utf8");
6434
6635
  return `Script output saved to ${params.filePath}`;
6435
6636
  }
@@ -7583,7 +7784,7 @@ import { resolve as resolve17 } from "path";
7583
7784
  // src/mcp/servers/sqlite/db-engine.ts
7584
7785
  import { Database as Database2 } from "bun:sqlite";
7585
7786
  import { resolve as resolve16, isAbsolute } from "path";
7586
- import { readdirSync as readdirSync5 } from "fs";
7787
+ import { readdirSync as readdirSync6 } from "fs";
7587
7788
 
7588
7789
  class SqliteEngine {
7589
7790
  connections = new Map;
@@ -7613,7 +7814,7 @@ class SqliteEngine {
7613
7814
  }
7614
7815
  autoDiscoverDatabase() {
7615
7816
  try {
7616
- const files = readdirSync5(process.cwd());
7817
+ const files = readdirSync6(process.cwd());
7617
7818
  const dbFile = files.find((f) => f.endsWith(".sqlite") || f.endsWith(".sqlite3") || f.endsWith(".db"));
7618
7819
  return dbFile ? resolve16(process.cwd(), dbFile) : null;
7619
7820
  } catch {
@@ -8117,8 +8318,8 @@ function verifyTaskAction(assertion, payload) {
8117
8318
  }
8118
8319
  }
8119
8320
  // src/agents/roles.ts
8120
- import { existsSync as existsSync15, readdirSync as readdirSync6, readFileSync as readFileSync9 } from "fs";
8121
- 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";
8122
8323
 
8123
8324
  class AgentRoleRegistry {
8124
8325
  roles = new Map;
@@ -8203,13 +8404,13 @@ class AgentRoleRegistry {
8203
8404
  }
8204
8405
  loadRolesFromDir(dirPath) {
8205
8406
  const fullPath = resolve18(dirPath);
8206
- if (!existsSync15(fullPath))
8407
+ if (!existsSync16(fullPath))
8207
8408
  return;
8208
- const entries = readdirSync6(fullPath);
8409
+ const entries = readdirSync7(fullPath);
8209
8410
  for (const entry of entries) {
8210
8411
  if (entry.endsWith(".json")) {
8211
8412
  try {
8212
- const content = readFileSync9(join8(fullPath, entry), "utf8");
8413
+ const content = readFileSync9(join9(fullPath, entry), "utf8");
8213
8414
  const parsed = JSON.parse(content);
8214
8415
  if (parsed.name && parsed.systemPrompt) {
8215
8416
  this.registerRole(parsed);
@@ -8239,7 +8440,7 @@ class AgentRoleRegistry {
8239
8440
  // src/agents/graph-store.ts
8240
8441
  import { Database as Database3 } from "bun:sqlite";
8241
8442
  import { resolve as resolve19 } from "path";
8242
- import { existsSync as existsSync16, mkdirSync as mkdirSync9 } from "fs";
8443
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10 } from "fs";
8243
8444
  class AgentGraphStore {
8244
8445
  db;
8245
8446
  constructor(dbPathOrDb) {
@@ -8249,8 +8450,8 @@ class AgentGraphStore {
8249
8450
  const dbPath = dbPathOrDb || getAgentGraphDbPath();
8250
8451
  if (dbPath !== ":memory:") {
8251
8452
  const dir = resolve19(dbPath, "..");
8252
- if (!existsSync16(dir)) {
8253
- mkdirSync9(dir, { recursive: true });
8453
+ if (!existsSync17(dir)) {
8454
+ mkdirSync10(dir, { recursive: true });
8254
8455
  }
8255
8456
  }
8256
8457
  this.db = new Database3(dbPath);
@@ -8672,7 +8873,7 @@ function registerMultiAgentTools(router2, spawner) {
8672
8873
  }
8673
8874
  // src/storage/sqlite-store.ts
8674
8875
  import { Database as Database4 } from "bun:sqlite";
8675
- import { existsSync as existsSync17, mkdirSync as mkdirSync10 } from "fs";
8876
+ import { existsSync as existsSync18, mkdirSync as mkdirSync11 } from "fs";
8676
8877
  import { dirname as dirname8 } from "path";
8677
8878
  class SqliteThreadStore {
8678
8879
  db;
@@ -8680,8 +8881,8 @@ class SqliteThreadStore {
8680
8881
  const effectivePath = dbPath || this.getDefaultDbPath();
8681
8882
  if (effectivePath !== ":memory:") {
8682
8883
  const dir = dirname8(effectivePath);
8683
- if (!existsSync17(dir)) {
8684
- mkdirSync10(dir, { recursive: true });
8884
+ if (!existsSync18(dir)) {
8885
+ mkdirSync11(dir, { recursive: true });
8685
8886
  }
8686
8887
  }
8687
8888
  this.db = new Database4(effectivePath);
@@ -8913,8 +9114,8 @@ class SessionPersistenceManager {
8913
9114
  }
8914
9115
  }
8915
9116
  // src/skills/loader.ts
8916
- import { existsSync as existsSync18, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "fs";
8917
- 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";
8918
9119
  import { homedir as homedir3 } from "os";
8919
9120
  var __dirname = "/home/runner/work/agent-cli/agent-cli/src/skills";
8920
9121
 
@@ -8985,7 +9186,7 @@ class SkillsLoader {
8985
9186
  resolve20(cwd, "skills")
8986
9187
  ];
8987
9188
  for (const cand of candidates) {
8988
- if (existsSync18(cand) && !roots.includes(cand)) {
9189
+ if (existsSync19(cand) && !roots.includes(cand)) {
8989
9190
  roots.push(cand);
8990
9191
  }
8991
9192
  }
@@ -8994,7 +9195,7 @@ class SkillsLoader {
8994
9195
  roots.push(getGlobalSkillsDir(), resolve20(homedir3(), ".gemini", "config", "skills"));
8995
9196
  }
8996
9197
  roots.push(...this.customRoots.map((r) => resolve20(r)));
8997
- return roots.filter((r) => existsSync18(r));
9198
+ return roots.filter((r) => existsSync19(r));
8998
9199
  }
8999
9200
  discoverSkills(cwd, options) {
9000
9201
  return this.listSkills(cwd, options);
@@ -9010,12 +9211,12 @@ class SkillsLoader {
9010
9211
  const discovered = new Map;
9011
9212
  for (const root of roots) {
9012
9213
  try {
9013
- const entries = readdirSync7(root, { withFileTypes: true });
9214
+ const entries = readdirSync8(root, { withFileTypes: true });
9014
9215
  for (const entry of entries) {
9015
9216
  if (entry.isDirectory()) {
9016
- const skillDir = join9(root, entry.name);
9017
- const skillFilePath = join9(skillDir, "SKILL.md");
9018
- if (existsSync18(skillFilePath)) {
9217
+ const skillDir = join10(root, entry.name);
9218
+ const skillFilePath = join10(skillDir, "SKILL.md");
9219
+ if (existsSync19(skillFilePath)) {
9019
9220
  const meta = this.parseSkillFrontmatter(skillFilePath, entry.name, root, cwd);
9020
9221
  if (meta && !discovered.has(meta.name)) {
9021
9222
  meta.enabled = !this.isSkillDisabled(meta.name);
@@ -9028,7 +9229,7 @@ class SkillsLoader {
9028
9229
  }
9029
9230
  } catch {}
9030
9231
  }
9031
- const result = Array.from(discovered.values());
9232
+ const result = Array.from(discovered.values()).sort((a, b) => a.name.localeCompare(b.name));
9032
9233
  this.skillsCache.set(cacheKey, { timestamp: now, skills: result });
9033
9234
  return result;
9034
9235
  }
@@ -9117,10 +9318,10 @@ class SkillsLoader {
9117
9318
  const skills = this.listSkills(cwd, { includeDisabled: false });
9118
9319
  if (skills.length === 0)
9119
9320
  return "";
9120
- const workspaceSkills = skills.filter((s) => s.scope === "workspace");
9121
- const builtInSkills = skills.filter((s) => s.scope === "built-in");
9122
- const otherSkills = skills.filter((s) => s.scope !== "workspace" && s.scope !== "built-in");
9123
- 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);
9124
9325
  const lines = selectedSkills.map((s) => {
9125
9326
  const desc = s.shortDescription || s.description;
9126
9327
  return `- **${s.name}**: ${desc}`;
@@ -9137,8 +9338,8 @@ When tackling complex specialized tasks that match any of these skills, autonomo
9137
9338
  }
9138
9339
  }
9139
9340
  // src/memories/store.ts
9140
- import { existsSync as existsSync19, readFileSync as readFileSync11, writeFileSync as writeFileSync6, mkdirSync as mkdirSync11, readdirSync as readdirSync8 } from "fs";
9141
- 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";
9142
9343
  import { createHash } from "crypto";
9143
9344
  class MemoryStore {
9144
9345
  globalPath;
@@ -9150,7 +9351,7 @@ class MemoryStore {
9150
9351
  findProjectRoot(cwd) {
9151
9352
  let current = resolve21(cwd);
9152
9353
  while (true) {
9153
- if (existsSync19(join10(current, ".git"))) {
9354
+ if (existsSync20(join11(current, ".git"))) {
9154
9355
  return current;
9155
9356
  }
9156
9357
  const parent = dirname9(current);
@@ -9169,24 +9370,24 @@ class MemoryStore {
9169
9370
  getProjectMemoryDir(cwd) {
9170
9371
  if (this.customWorkspacePath) {
9171
9372
  const dir2 = resolve21(this.customWorkspacePath);
9172
- if (!existsSync19(dir2)) {
9373
+ if (!existsSync20(dir2)) {
9173
9374
  try {
9174
- mkdirSync11(dir2, { recursive: true });
9375
+ mkdirSync12(dir2, { recursive: true });
9175
9376
  } catch {}
9176
9377
  }
9177
9378
  return dir2;
9178
9379
  }
9179
9380
  const slug = this.getProjectSlug(cwd);
9180
- const dir = join10(getProjectsDir(), slug, "memory");
9181
- if (!existsSync19(dir)) {
9381
+ const dir = join11(getProjectsDir(), slug, "memory");
9382
+ if (!existsSync20(dir)) {
9182
9383
  try {
9183
- mkdirSync11(dir, { recursive: true });
9384
+ mkdirSync12(dir, { recursive: true });
9184
9385
  } catch {}
9185
9386
  }
9186
9387
  return dir;
9187
9388
  }
9188
9389
  getMemoryIndexPath(cwd) {
9189
- return join10(this.getProjectMemoryDir(cwd), "MEMORY.md");
9390
+ return join11(this.getProjectMemoryDir(cwd), "MEMORY.md");
9190
9391
  }
9191
9392
  normalizeCategory(raw) {
9192
9393
  const cat = raw.toLowerCase().trim();
@@ -9205,7 +9406,7 @@ class MemoryStore {
9205
9406
  const sanitizedName = params.name.toLowerCase().trim().replace(/[^a-z0-9_-]/g, "_").replace(/^_+|_+$/g, "") || `note_${Date.now()}`;
9206
9407
  const memoryDir = this.getProjectMemoryDir(params.cwd);
9207
9408
  const fileName = `${type}_${sanitizedName}.md`;
9208
- const filePath = join10(memoryDir, fileName);
9409
+ const filePath = join11(memoryDir, fileName);
9209
9410
  const nowIso = new Date().toISOString();
9210
9411
  const cleanContent = params.content.trim();
9211
9412
  const desc = (params.description || cleanContent.split(`
@@ -9240,17 +9441,17 @@ class MemoryStore {
9240
9441
  }
9241
9442
  readTopicMemory(topicNameOrFile, cwd) {
9242
9443
  const memoryDir = this.getProjectMemoryDir(cwd);
9243
- let targetPath = join10(memoryDir, topicNameOrFile);
9244
- if (!existsSync19(targetPath)) {
9444
+ let targetPath = join11(memoryDir, topicNameOrFile);
9445
+ if (!existsSync20(targetPath)) {
9245
9446
  if (!topicNameOrFile.endsWith(".md")) {
9246
- targetPath = join10(memoryDir, `${topicNameOrFile}.md`);
9447
+ targetPath = join11(memoryDir, `${topicNameOrFile}.md`);
9247
9448
  }
9248
9449
  }
9249
- if (!existsSync19(targetPath)) {
9250
- const files = readdirSync8(memoryDir);
9450
+ if (!existsSync20(targetPath)) {
9451
+ const files = readdirSync9(memoryDir);
9251
9452
  const match = files.find((f) => f.includes(topicNameOrFile));
9252
9453
  if (match) {
9253
- targetPath = join10(memoryDir, match);
9454
+ targetPath = join11(memoryDir, match);
9254
9455
  } else {
9255
9456
  return null;
9256
9457
  }
@@ -9311,12 +9512,12 @@ class MemoryStore {
9311
9512
  }
9312
9513
  syncMemoryIndex(cwd) {
9313
9514
  const memoryDir = this.getProjectMemoryDir(cwd);
9314
- const indexPath = join10(memoryDir, "MEMORY.md");
9315
- 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") : [];
9316
9517
  const items2 = [];
9317
9518
  for (const f of files) {
9318
9519
  try {
9319
- const full = join10(memoryDir, f);
9520
+ const full = join11(memoryDir, f);
9320
9521
  const parsed = this.parseTopicFile(readFileSync11(full, "utf8"), full);
9321
9522
  items2.push({
9322
9523
  type: parsed.type,
@@ -9343,7 +9544,7 @@ class MemoryStore {
9343
9544
  }
9344
9545
  loadMemoryIndex(cwd) {
9345
9546
  const indexPath = this.getMemoryIndexPath(cwd);
9346
- if (!existsSync19(indexPath))
9547
+ if (!existsSync20(indexPath))
9347
9548
  return "";
9348
9549
  try {
9349
9550
  const raw = readFileSync11(indexPath, "utf8");
@@ -9359,13 +9560,13 @@ class MemoryStore {
9359
9560
  }
9360
9561
  listProjectMemories(cwd) {
9361
9562
  const memoryDir = this.getProjectMemoryDir(cwd);
9362
- if (!existsSync19(memoryDir))
9563
+ if (!existsSync20(memoryDir))
9363
9564
  return [];
9364
- 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");
9365
9566
  const list = [];
9366
9567
  for (const f of files) {
9367
9568
  try {
9368
- const full = join10(memoryDir, f);
9569
+ const full = join11(memoryDir, f);
9369
9570
  list.push(this.parseTopicFile(readFileSync11(full, "utf8"), full));
9370
9571
  } catch {}
9371
9572
  }
@@ -9543,8 +9744,8 @@ async function removeWorktreeGit(repoRoot, worktreePath, deleteBranch = false) {
9543
9744
  return { success: true };
9544
9745
  }
9545
9746
  // src/worktree/manager.ts
9546
- import { resolve as resolve23, join as join11 } from "path";
9547
- 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";
9548
9749
  var DEFAULT_WORKTREE_KEEP_COUNT = 15;
9549
9750
 
9550
9751
  class WorktreeManager {
@@ -9568,15 +9769,15 @@ class WorktreeManager {
9568
9769
  const branchName = options.branch || `groupy/${taskId}`;
9569
9770
  const targetDir = options.worktreePath || (this.baseStorageDir ? resolve23(this.baseStorageDir, branchName.replace(/\//g, "_")) : resolve23(repoRoot, ".groupy", "worktrees", branchName.replace(/\//g, "_")));
9570
9771
  const worktreeParent = resolve23(targetDir, "..");
9571
- if (!existsSync20(worktreeParent)) {
9572
- mkdirSync12(worktreeParent, { recursive: true });
9772
+ if (!existsSync21(worktreeParent)) {
9773
+ mkdirSync13(worktreeParent, { recursive: true });
9573
9774
  }
9574
9775
  const baseBranch = options.baseBranch || await getCurrentBranch(repoRoot);
9575
9776
  const result = await createWorktreeGit(repoRoot, targetDir, branchName, baseBranch);
9576
9777
  if (!result.success) {
9577
9778
  throw new Error(`Failed to create git worktree: ${result.error}`);
9578
9779
  }
9579
- const metaPath = join11(targetDir, "groupy-thread.json");
9780
+ const metaPath = join12(targetDir, "groupy-thread.json");
9580
9781
  try {
9581
9782
  writeFileSync7(metaPath, JSON.stringify({
9582
9783
  version: 1,
@@ -9602,8 +9803,8 @@ class WorktreeManager {
9602
9803
  return [];
9603
9804
  const worktrees = await listWorktreesGit(repoRoot);
9604
9805
  return worktrees.map((wt) => {
9605
- const metaPath = join11(wt.path, "groupy-thread.json");
9606
- if (existsSync20(metaPath)) {
9806
+ const metaPath = join12(wt.path, "groupy-thread.json");
9807
+ if (existsSync21(metaPath)) {
9607
9808
  try {
9608
9809
  const raw = JSON.parse(readFileSync12(metaPath, "utf8"));
9609
9810
  return { ...wt, threadId: raw.ownerThreadId || raw.threadId };
@@ -11333,6 +11534,8 @@ export {
11333
11534
  CodeModeRuntime,
11334
11535
  ContextWindowExceededError,
11335
11536
  CredentialsStore,
11537
+ DEFAULT_AUTO_COMPACT_THRESHOLD_TOKENS,
11538
+ DEFAULT_MAX_CONTEXT_TOKENS,
11336
11539
  DEFAULT_WORKTREE_KEEP_COUNT,
11337
11540
  DefaultModelClientSession,
11338
11541
  DomSnapshotEngine,
@@ -11380,6 +11583,7 @@ export {
11380
11583
  WorktreeManager,
11381
11584
  applyPatchTool,
11382
11585
  askQuestionTool,
11586
+ buildStructuredSystemPrompt,
11383
11587
  buildSystemPrompt,
11384
11588
  captureWorldState,
11385
11589
  compactHistory,