sparkecoder 0.1.56 → 0.1.58

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.
Files changed (131) hide show
  1. package/dist/agent/index.d.ts +2 -2
  2. package/dist/agent/index.js +706 -68
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +824 -186
  5. package/dist/cli.js.map +1 -1
  6. package/dist/{index-CqKMYoJv.d.ts → index-DqLDYWhb.d.ts} +1 -1
  7. package/dist/index.d.ts +3 -3
  8. package/dist/index.js +811 -173
  9. package/dist/index.js.map +1 -1
  10. package/dist/{search-CZsTAZ90.d.ts → search-DINnDTgj.d.ts} +1 -0
  11. package/dist/server/index.js +811 -173
  12. package/dist/server/index.js.map +1 -1
  13. package/dist/tools/index.d.ts +49 -3
  14. package/dist/tools/index.js +659 -60
  15. package/dist/tools/index.js.map +1 -1
  16. package/package.json +1 -1
  17. package/web/.next/BUILD_ID +1 -1
  18. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  19. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  20. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  21. package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
  22. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
  23. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
  24. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  25. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  26. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  27. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  29. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +2 -2
  34. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  35. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  36. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  37. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  38. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  39. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  40. package/web/.next/standalone/web/.next/server/app/api/config/route.js.nft.json +1 -1
  41. package/web/.next/standalone/web/.next/server/app/api/health/route.js.nft.json +1 -1
  42. package/web/.next/standalone/web/.next/server/app/docs/installation/page_client-reference-manifest.js +1 -1
  43. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  44. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +2 -2
  45. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +2 -2
  46. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +2 -2
  48. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +2 -2
  49. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  50. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  52. package/web/.next/standalone/web/.next/server/app/docs/page_client-reference-manifest.js +1 -1
  53. package/web/.next/standalone/web/.next/server/app/docs/skills/page_client-reference-manifest.js +1 -1
  54. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  55. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +2 -2
  56. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +2 -2
  57. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +2 -2
  59. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +2 -2
  60. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  61. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  62. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  63. package/web/.next/standalone/web/.next/server/app/docs/tools/page_client-reference-manifest.js +1 -1
  64. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  65. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +2 -2
  66. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +2 -2
  67. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +2 -2
  69. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +2 -2
  70. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  71. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  72. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  73. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  74. package/web/.next/standalone/web/.next/server/app/docs.rsc +2 -2
  75. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +2 -2
  76. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  77. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +2 -2
  78. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +2 -2
  79. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  80. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  81. package/web/.next/standalone/web/.next/server/app/embed/[id]/page.js.nft.json +1 -1
  82. package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +1 -1
  83. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  84. package/web/.next/standalone/web/.next/server/app/index.rsc +2 -2
  85. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
  86. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
  87. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +2 -2
  88. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  89. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
  90. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  91. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_f661d73d._.js → 2374f_076f03ec._.js} +1 -1
  92. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_e35df3d7._.js → 2374f_19289e11._.js} +1 -1
  93. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_6ced4caf._.js → 2374f_2f0d9f6f._.js} +1 -1
  94. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_aade2a6d._.js → 2374f_35475cbe._.js} +1 -1
  95. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_562d2f4f._.js → 2374f_40e35a02._.js} +1 -1
  96. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_05c00b91._.js → 2374f_4666c827._.js} +1 -1
  97. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_ac284eb3._.js → 2374f_4858a1ea._.js} +1 -1
  98. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_39f76acc._.js → 2374f_51385fed._.js} +1 -1
  99. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_ef435bac._.js → 2374f_7db22cde._.js} +1 -1
  100. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_800db4e3._.js → 2374f_90b8e4fb._.js} +1 -1
  101. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_1fa4a79a._.js → 2374f_b17fce11._.js} +1 -1
  102. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_d118a207._.js → 2374f_b4b86c1f._.js} +1 -1
  103. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_934cb548._.js → 2374f_d8b9ce38._.js} +1 -1
  104. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_c272cbb4._.js → 2374f_fb95e3c9._.js} +1 -1
  105. package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__f44222d9._.js → [root-of-the-server]__7775f784._.js} +2 -2
  106. package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__8cdc7b0b._.js → [root-of-the-server]__bd396152._.js} +4 -4
  107. package/web/.next/standalone/web/.next/server/chunks/ssr/{web_0a13adb9._.js → web_645f4b90._.js} +2 -2
  108. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  109. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  110. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  111. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  112. package/web/.next/standalone/web/.next/static/chunks/2868b007ce5163fc.css +1 -0
  113. package/web/.next/standalone/web/.next/static/chunks/{ca717ddd7c8f37e8.js → 631b023d37a08635.js} +6 -6
  114. package/web/.next/standalone/web/.next/static/static/chunks/2868b007ce5163fc.css +1 -0
  115. package/web/.next/standalone/web/.next/static/static/chunks/{ca717ddd7c8f37e8.js → 631b023d37a08635.js} +6 -6
  116. package/web/.next/standalone/web/src/components/ai-elements/code-graph-tool.tsx +202 -0
  117. package/web/.next/standalone/web/src/components/chat-interface.tsx +49 -0
  118. package/web/.next/static/chunks/2868b007ce5163fc.css +1 -0
  119. package/web/.next/static/chunks/{ca717ddd7c8f37e8.js → 631b023d37a08635.js} +6 -6
  120. package/web/.next/standalone/web/.next/static/chunks/7228b2394d1fb347.css +0 -1
  121. package/web/.next/standalone/web/.next/static/static/chunks/7228b2394d1fb347.css +0 -1
  122. package/web/.next/static/chunks/7228b2394d1fb347.css +0 -1
  123. /package/web/.next/standalone/web/.next/static/{static/yfBGAcI8gI55lwQllPu-z → TuFKgULSvgTGHxXzZoeMo}/_buildManifest.js +0 -0
  124. /package/web/.next/standalone/web/.next/static/{static/yfBGAcI8gI55lwQllPu-z → TuFKgULSvgTGHxXzZoeMo}/_clientMiddlewareManifest.json +0 -0
  125. /package/web/.next/standalone/web/.next/static/{static/yfBGAcI8gI55lwQllPu-z → TuFKgULSvgTGHxXzZoeMo}/_ssgManifest.js +0 -0
  126. /package/web/.next/standalone/web/.next/static/{yfBGAcI8gI55lwQllPu-z → static/TuFKgULSvgTGHxXzZoeMo}/_buildManifest.js +0 -0
  127. /package/web/.next/standalone/web/.next/static/{yfBGAcI8gI55lwQllPu-z → static/TuFKgULSvgTGHxXzZoeMo}/_clientMiddlewareManifest.json +0 -0
  128. /package/web/.next/standalone/web/.next/static/{yfBGAcI8gI55lwQllPu-z → static/TuFKgULSvgTGHxXzZoeMo}/_ssgManifest.js +0 -0
  129. /package/web/.next/static/{yfBGAcI8gI55lwQllPu-z → TuFKgULSvgTGHxXzZoeMo}/_buildManifest.js +0 -0
  130. /package/web/.next/static/{yfBGAcI8gI55lwQllPu-z → TuFKgULSvgTGHxXzZoeMo}/_clientMiddlewareManifest.json +0 -0
  131. /package/web/.next/static/{yfBGAcI8gI55lwQllPu-z → TuFKgULSvgTGHxXzZoeMo}/_ssgManifest.js +0 -0
@@ -1461,13 +1461,13 @@ var semantic_search_exports = {};
1461
1461
  __export(semantic_search_exports, {
1462
1462
  createSemanticSearchTool: () => createSemanticSearchTool
1463
1463
  });
1464
- import { tool as tool7 } from "ai";
1465
- import { z as z8 } from "zod";
1466
- import { existsSync as existsSync10, readFileSync as readFileSync4 } from "fs";
1464
+ import { tool as tool8 } from "ai";
1465
+ import { z as z9 } from "zod";
1466
+ import { existsSync as existsSync11, readFileSync as readFileSync4 } from "fs";
1467
1467
  import { join as join4 } from "path";
1468
1468
  import { minimatch as minimatch3 } from "minimatch";
1469
1469
  function createSemanticSearchTool(options) {
1470
- return tool7({
1470
+ return tool8({
1471
1471
  description: `Search the codebase using semantic similarity. This tool finds code by understanding its meaning, not just matching text.
1472
1472
 
1473
1473
  Use this tool when:
@@ -1532,7 +1532,7 @@ Returns matching code snippets with file paths, line numbers, and relevance scor
1532
1532
  continue;
1533
1533
  }
1534
1534
  const fullPath = join4(options.workingDirectory, filePath);
1535
- if (!existsSync10(fullPath)) {
1535
+ if (!existsSync11(fullPath)) {
1536
1536
  continue;
1537
1537
  }
1538
1538
  let snippet = "";
@@ -1587,11 +1587,11 @@ var init_semantic_search = __esm({
1587
1587
  "use strict";
1588
1588
  init_semantic();
1589
1589
  init_config();
1590
- semanticSearchInputSchema = z8.object({
1591
- query: z8.string().describe("Natural language search query describing what you want to find"),
1592
- topK: z8.number().optional().default(10).describe("Number of results to return (default: 10, max: 50)"),
1593
- filePattern: z8.string().optional().describe('Filter results by file glob pattern (e.g., "*.ts", "src/**/*.py")'),
1594
- language: z8.string().optional().describe('Filter by programming language (e.g., "typescript", "python")')
1590
+ semanticSearchInputSchema = z9.object({
1591
+ query: z9.string().describe("Natural language search query describing what you want to find"),
1592
+ topK: z9.number().optional().default(10).describe("Number of results to return (default: 10, max: 50)"),
1593
+ filePattern: z9.string().optional().describe('Filter results by file glob pattern (e.g., "*.ts", "src/**/*.py")'),
1594
+ language: z9.string().optional().describe('Filter by programming language (e.g., "typescript", "python")')
1595
1595
  });
1596
1596
  }
1597
1597
  });
@@ -1602,27 +1602,27 @@ import { Hono as Hono5 } from "hono";
1602
1602
  import { serve } from "@hono/node-server";
1603
1603
  import { cors } from "hono/cors";
1604
1604
  import { logger } from "hono/logger";
1605
- import { existsSync as existsSync14, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "fs";
1606
- import { resolve as resolve9, dirname as dirname7, join as join8 } from "path";
1605
+ import { existsSync as existsSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "fs";
1606
+ import { resolve as resolve10, dirname as dirname7, join as join8 } from "path";
1607
1607
  import { spawn as spawn2 } from "child_process";
1608
1608
  import { createServer as createNetServer } from "net";
1609
- import { fileURLToPath as fileURLToPath3 } from "url";
1609
+ import { fileURLToPath as fileURLToPath4 } from "url";
1610
1610
 
1611
1611
  // src/server/routes/sessions.ts
1612
1612
  init_db();
1613
1613
  import { Hono } from "hono";
1614
1614
  import { zValidator } from "@hono/zod-validator";
1615
- import { z as z12 } from "zod";
1616
- import { existsSync as existsSync12, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2, readdirSync, statSync as statSync2, unlinkSync } from "fs";
1617
- import { readdir as readdir4 } from "fs/promises";
1618
- import { join as join5, basename as basename3, extname as extname6, relative as relative8 } from "path";
1615
+ import { z as z13 } from "zod";
1616
+ import { existsSync as existsSync13, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2, readdirSync, statSync as statSync2, unlinkSync } from "fs";
1617
+ import { readdir as readdir5 } from "fs/promises";
1618
+ import { join as join5, basename as basename4, extname as extname6, relative as relative9 } from "path";
1619
1619
  import { nanoid as nanoid4 } from "nanoid";
1620
1620
 
1621
1621
  // src/agent/index.ts
1622
1622
  import {
1623
1623
  streamText as streamText2,
1624
1624
  generateText as generateText3,
1625
- tool as tool10,
1625
+ tool as tool11,
1626
1626
  stepCountIs as stepCountIs2
1627
1627
  } from "ai";
1628
1628
 
@@ -1645,7 +1645,7 @@ var SUBAGENT_MODELS = {
1645
1645
  // src/agent/index.ts
1646
1646
  init_db();
1647
1647
  init_config();
1648
- import { z as z11 } from "zod";
1648
+ import { z as z12 } from "zod";
1649
1649
  import { nanoid as nanoid3 } from "nanoid";
1650
1650
 
1651
1651
  // src/tools/bash.ts
@@ -1932,8 +1932,8 @@ async function listSessionTerminals(sessionId, workingDirectory) {
1932
1932
  const terminalsDir = join2(workingDirectory, LOG_BASE_DIR, sessionId, "terminals");
1933
1933
  const terminals2 = [];
1934
1934
  try {
1935
- const { readdir: readdir5 } = await import("fs/promises");
1936
- const entries = await readdir5(terminalsDir, { withFileTypes: true });
1935
+ const { readdir: readdir6 } = await import("fs/promises");
1936
+ const entries = await readdir6(terminalsDir, { withFileTypes: true });
1937
1937
  for (const entry of entries) {
1938
1938
  if (entry.isDirectory()) {
1939
1939
  const meta = await getMeta(entry.name, workingDirectory, sessionId);
@@ -2736,7 +2736,11 @@ async function createClient(serverId, handle, root) {
2736
2736
  dynamicRegistration: true
2737
2737
  },
2738
2738
  documentSymbol: {
2739
- dynamicRegistration: true
2739
+ dynamicRegistration: true,
2740
+ hierarchicalDocumentSymbolSupport: true,
2741
+ symbolKind: {
2742
+ valueSet: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
2743
+ }
2740
2744
  }
2741
2745
  },
2742
2746
  workspace: {
@@ -2833,7 +2837,7 @@ async function createClient(serverId, handle, root) {
2833
2837
  },
2834
2838
  async waitForDiagnostics(filePath, timeoutMs = 5e3) {
2835
2839
  const normalized = normalizePath(filePath);
2836
- return new Promise((resolve10) => {
2840
+ return new Promise((resolve11) => {
2837
2841
  const startTime = Date.now();
2838
2842
  let debounceTimer;
2839
2843
  let resolved = false;
@@ -2852,7 +2856,7 @@ async function createClient(serverId, handle, root) {
2852
2856
  if (resolved) return;
2853
2857
  resolved = true;
2854
2858
  cleanup();
2855
- resolve10(diagnostics.get(normalized) || []);
2859
+ resolve11(diagnostics.get(normalized) || []);
2856
2860
  };
2857
2861
  const onDiagnostic = () => {
2858
2862
  if (debounceTimer) clearTimeout(debounceTimer);
@@ -2878,6 +2882,100 @@ async function createClient(serverId, handle, root) {
2878
2882
  getAllDiagnostics() {
2879
2883
  return new Map(diagnostics);
2880
2884
  },
2885
+ async getDefinition(filePath, line, character) {
2886
+ const normalized = normalizePath(filePath);
2887
+ if (!fileVersions.has(normalized)) {
2888
+ await client.notifyOpen(normalized);
2889
+ }
2890
+ try {
2891
+ const result = await connection.sendRequest("textDocument/definition", {
2892
+ textDocument: { uri: pathToFileURL(normalized).href },
2893
+ position: { line, character }
2894
+ });
2895
+ if (!result) return [];
2896
+ const items = Array.isArray(result) ? result : [result];
2897
+ return items.map((r) => ({
2898
+ uri: r.targetUri || r.uri,
2899
+ range: r.targetRange || r.range
2900
+ }));
2901
+ } catch (error) {
2902
+ console.error("[lsp] Error getting definition:", error);
2903
+ return [];
2904
+ }
2905
+ },
2906
+ async getReferences(filePath, line, character, includeDeclaration = false) {
2907
+ const normalized = normalizePath(filePath);
2908
+ if (!fileVersions.has(normalized)) {
2909
+ await client.notifyOpen(normalized);
2910
+ }
2911
+ try {
2912
+ const result = await connection.sendRequest("textDocument/references", {
2913
+ textDocument: { uri: pathToFileURL(normalized).href },
2914
+ position: { line, character },
2915
+ context: { includeDeclaration }
2916
+ });
2917
+ return result || [];
2918
+ } catch (error) {
2919
+ console.error("[lsp] Error getting references:", error);
2920
+ return [];
2921
+ }
2922
+ },
2923
+ async getHover(filePath, line, character) {
2924
+ const normalized = normalizePath(filePath);
2925
+ if (!fileVersions.has(normalized)) {
2926
+ await client.notifyOpen(normalized);
2927
+ }
2928
+ try {
2929
+ const result = await connection.sendRequest("textDocument/hover", {
2930
+ textDocument: { uri: pathToFileURL(normalized).href },
2931
+ position: { line, character }
2932
+ });
2933
+ if (!result || !result.contents) return null;
2934
+ if (typeof result.contents === "string") return result.contents;
2935
+ if (result.contents.value) return result.contents.value;
2936
+ if (Array.isArray(result.contents)) {
2937
+ return result.contents.map((c) => typeof c === "string" ? c : c.value).join("\n");
2938
+ }
2939
+ return null;
2940
+ } catch (error) {
2941
+ console.error("[lsp] Error getting hover:", error);
2942
+ return null;
2943
+ }
2944
+ },
2945
+ async getDocumentSymbols(filePath) {
2946
+ const normalized = normalizePath(filePath);
2947
+ if (!fileVersions.has(normalized)) {
2948
+ await client.notifyOpen(normalized);
2949
+ }
2950
+ try {
2951
+ const result = await connection.sendRequest("textDocument/documentSymbol", {
2952
+ textDocument: { uri: pathToFileURL(normalized).href }
2953
+ });
2954
+ if (!result || result.length === 0) return [];
2955
+ if (result[0].range) {
2956
+ return result;
2957
+ }
2958
+ return result.map((si) => ({
2959
+ name: si.name,
2960
+ kind: si.kind,
2961
+ range: si.location?.range ?? { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
2962
+ selectionRange: si.location?.range ?? { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
2963
+ detail: si.containerName
2964
+ }));
2965
+ } catch (error) {
2966
+ console.error("[lsp] Error getting document symbols:", error);
2967
+ return [];
2968
+ }
2969
+ },
2970
+ async findWorkspaceSymbols(query) {
2971
+ try {
2972
+ const result = await connection.sendRequest("workspace/symbol", { query });
2973
+ return result || [];
2974
+ } catch (error) {
2975
+ console.error("[lsp] Error finding workspace symbols:", error);
2976
+ return [];
2977
+ }
2978
+ },
2881
2979
  async shutdown() {
2882
2980
  try {
2883
2981
  await connection.sendRequest("shutdown");
@@ -3000,6 +3098,24 @@ async function getAllDiagnostics() {
3000
3098
  }
3001
3099
  return results;
3002
3100
  }
3101
+ async function getReferences(filePath, line, character, includeDeclaration = false) {
3102
+ const normalized = normalizePath(filePath);
3103
+ const client = await getClientForFile(normalized);
3104
+ if (!client) return [];
3105
+ return client.getReferences(normalized, line, character, includeDeclaration);
3106
+ }
3107
+ async function getHover(filePath, line, character) {
3108
+ const normalized = normalizePath(filePath);
3109
+ const client = await getClientForFile(normalized);
3110
+ if (!client) return null;
3111
+ return client.getHover(normalized, line, character);
3112
+ }
3113
+ async function getDocumentSymbols(filePath) {
3114
+ const normalized = normalizePath(filePath);
3115
+ const client = await getClientForFile(normalized);
3116
+ if (!client) return [];
3117
+ return client.getDocumentSymbols(normalized);
3118
+ }
3003
3119
  async function formatDiagnosticsOutput(filePath, options = {}) {
3004
3120
  const diagnostics = await getDiagnostics(filePath);
3005
3121
  return formatDiagnosticsForAgent(filePath, diagnostics, options);
@@ -3095,7 +3211,7 @@ Working directory: ${options.workingDirectory}`,
3095
3211
  isChunked: true
3096
3212
  });
3097
3213
  if (chunkCount > 1) {
3098
- await new Promise((resolve10) => setTimeout(resolve10, 0));
3214
+ await new Promise((resolve11) => setTimeout(resolve11, 0));
3099
3215
  }
3100
3216
  }
3101
3217
  }
@@ -3623,8 +3739,8 @@ ${file.relativePath}:`);
3623
3739
  }
3624
3740
 
3625
3741
  // src/tools/search.ts
3626
- import { tool as tool9 } from "ai";
3627
- import { z as z10 } from "zod";
3742
+ import { tool as tool10 } from "ai";
3743
+ import { z as z11 } from "zod";
3628
3744
 
3629
3745
  // src/agent/subagent.ts
3630
3746
  import {
@@ -3796,8 +3912,8 @@ var Subagent = class {
3796
3912
  if (eventQueue.length > 0) {
3797
3913
  yield eventQueue.shift();
3798
3914
  } else if (!done) {
3799
- const event = await new Promise((resolve10) => {
3800
- resolveNext = resolve10;
3915
+ const event = await new Promise((resolve11) => {
3916
+ resolveNext = resolve11;
3801
3917
  });
3802
3918
  if (event) {
3803
3919
  yield event;
@@ -3809,14 +3925,466 @@ var Subagent = class {
3809
3925
  };
3810
3926
 
3811
3927
  // src/agent/subagents/search.ts
3812
- import { tool as tool8 } from "ai";
3813
- import { z as z9 } from "zod";
3928
+ import { tool as tool9 } from "ai";
3929
+ import { z as z10 } from "zod";
3814
3930
  import { exec as exec4 } from "child_process";
3815
3931
  import { promisify as promisify4 } from "util";
3816
- import { readFile as readFile7, stat as stat3, readdir as readdir3 } from "fs/promises";
3817
- import { resolve as resolve8, relative as relative7, isAbsolute as isAbsolute4 } from "path";
3818
- import { existsSync as existsSync11 } from "fs";
3932
+ import { readFile as readFile8, stat as stat3, readdir as readdir4 } from "fs/promises";
3933
+ import { resolve as resolve9, relative as relative8, isAbsolute as isAbsolute5 } from "path";
3934
+ import { existsSync as existsSync12 } from "fs";
3819
3935
  init_semantic();
3936
+
3937
+ // src/tools/code-graph.ts
3938
+ import { tool as tool7 } from "ai";
3939
+ import { z as z8 } from "zod";
3940
+ import { resolve as resolve8, relative as relative7, isAbsolute as isAbsolute4, basename as basename3 } from "path";
3941
+ import { readFile as readFile7, readdir as readdir3 } from "fs/promises";
3942
+ import { existsSync as existsSync10 } from "fs";
3943
+ import { fileURLToPath as fileURLToPath2 } from "url";
3944
+ import { execFileSync } from "child_process";
3945
+ var codeGraphInputSchema = z8.object({
3946
+ symbol: z8.string().describe(
3947
+ "The symbol name to inspect (function, component, class, type, variable, etc.)"
3948
+ ),
3949
+ filePath: z8.string().optional().describe(
3950
+ "File path where the symbol is defined. If omitted, searches the workspace via grep."
3951
+ ),
3952
+ depth: z8.number().optional().default(2).describe(
3953
+ "How many levels of references to traverse upward (default: 2, max: 3). Level 1 = direct usages, level 2 = usages of those usages."
3954
+ )
3955
+ });
3956
+ function isPageFile(filePath) {
3957
+ const normalized = filePath.replace(/\\/g, "/");
3958
+ if (/\/app\/(.+\/)?(page|layout|loading|error|not-found)\.(tsx?|jsx?)$/.test(normalized)) return true;
3959
+ if (/\/pages\/(?!_|api\/).+\.(tsx?|jsx?)$/.test(normalized)) return true;
3960
+ return false;
3961
+ }
3962
+ function extractRoutePath(filePath, workingDirectory) {
3963
+ const rel = relative7(workingDirectory, filePath).replace(/\\/g, "/");
3964
+ const appMatch = rel.match(/(?:src\/)?app((?:\/[^/]+)*?)\/(?:page|layout|loading|error|not-found)\.\w+$/);
3965
+ if (appMatch) return appMatch[1] || "/";
3966
+ const pagesMatch = rel.match(/(?:src\/)?pages(\/.*?)(?:\/index)?\.\w+$/);
3967
+ if (pagesMatch) return pagesMatch[1] || "/";
3968
+ return void 0;
3969
+ }
3970
+ function symbolKindName(kind) {
3971
+ const names = {
3972
+ [5 /* Class */]: "class",
3973
+ [12 /* Function */]: "function",
3974
+ [6 /* Method */]: "method",
3975
+ [7 /* Property */]: "property",
3976
+ [13 /* Variable */]: "variable",
3977
+ [11 /* Interface */]: "interface",
3978
+ [10 /* Enum */]: "enum",
3979
+ [14 /* Constant */]: "constant",
3980
+ [9 /* Constructor */]: "constructor",
3981
+ [2 /* Module */]: "module",
3982
+ [3 /* Namespace */]: "namespace",
3983
+ [26 /* TypeParameter */]: "type_param",
3984
+ [8 /* Field */]: "field",
3985
+ [22 /* EnumMember */]: "enum_member",
3986
+ [19 /* Object */]: "object"
3987
+ };
3988
+ return names[kind] || "symbol";
3989
+ }
3990
+ function findContainingSymbol(symbols, line, character) {
3991
+ for (const sym of symbols) {
3992
+ if (!sym.range) continue;
3993
+ const { start, end } = sym.range;
3994
+ const afterStart = line > start.line || line === start.line && character >= start.character;
3995
+ const beforeEnd = line < end.line || line === end.line && character < end.character;
3996
+ if (afterStart && beforeEnd) {
3997
+ if (sym.children?.length) {
3998
+ const child = findContainingSymbol(sym.children, line, character);
3999
+ if (child) return child;
4000
+ }
4001
+ return sym;
4002
+ }
4003
+ }
4004
+ return null;
4005
+ }
4006
+ function findSymbolByName(symbols, name) {
4007
+ for (const sym of symbols) {
4008
+ if (sym.name === name && sym.selectionRange) return sym;
4009
+ if (sym.children) {
4010
+ const found = findSymbolByName(sym.children, name);
4011
+ if (found) return found;
4012
+ }
4013
+ }
4014
+ return null;
4015
+ }
4016
+ function cleanHoverText(text) {
4017
+ return text.replace(/```\w*\n?/g, "").replace(/\n```/g, "").trim();
4018
+ }
4019
+ async function grepForSymbol(symbol, workingDirectory) {
4020
+ const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4021
+ const rgPatterns = [
4022
+ `(export\\s+)?(default\\s+)?(function|const|let|var|class|interface|type|enum)\\s+${escaped}\\b`,
4023
+ `(export\\s+)?(default\\s+)?\\b${escaped}\\s*[=:(]`
4024
+ ];
4025
+ for (const pattern of rgPatterns) {
4026
+ try {
4027
+ const result = execFileSync("rg", [
4028
+ "-n",
4029
+ "--no-heading",
4030
+ "-e",
4031
+ pattern,
4032
+ "--glob",
4033
+ "*.{ts,tsx,js,jsx}",
4034
+ "-m",
4035
+ "5"
4036
+ ], {
4037
+ cwd: workingDirectory,
4038
+ encoding: "utf-8",
4039
+ timeout: 5e3,
4040
+ stdio: ["pipe", "pipe", "pipe"]
4041
+ }).trim();
4042
+ if (result) {
4043
+ const firstLine = result.split("\n")[0];
4044
+ const match = firstLine.match(/^(.+?):(\d+):(.*)/);
4045
+ if (match) {
4046
+ const col = match[3].indexOf(symbol);
4047
+ return {
4048
+ filePath: resolve8(workingDirectory, match[1]),
4049
+ line: parseInt(match[2]) - 1,
4050
+ char: col >= 0 ? col : 0
4051
+ };
4052
+ }
4053
+ }
4054
+ } catch {
4055
+ }
4056
+ }
4057
+ const defPattern = new RegExp(
4058
+ `(export|function|const|let|var|class|interface|type|enum)\\s+.*\\b${escaped}\\b`
4059
+ );
4060
+ const SUPPORTED_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
4061
+ const IGNORED_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", "coverage"]);
4062
+ async function search(dir, maxFiles) {
4063
+ if (maxFiles <= 0) return null;
4064
+ let remaining = maxFiles;
4065
+ try {
4066
+ const entries = await readdir3(dir, { withFileTypes: true });
4067
+ for (const entry of entries) {
4068
+ if (remaining <= 0) return null;
4069
+ const fullPath = resolve8(dir, entry.name);
4070
+ if (entry.isDirectory()) {
4071
+ if (IGNORED_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
4072
+ const found = await search(fullPath, remaining);
4073
+ if (found) return found;
4074
+ remaining -= 10;
4075
+ } else if (entry.isFile()) {
4076
+ const ext = entry.name.substring(entry.name.lastIndexOf("."));
4077
+ if (!SUPPORTED_EXTS.has(ext)) continue;
4078
+ remaining--;
4079
+ const content = await readFile7(fullPath, "utf-8");
4080
+ const lines = content.split("\n");
4081
+ for (let i = 0; i < lines.length; i++) {
4082
+ if (defPattern.test(lines[i])) {
4083
+ const col = lines[i].indexOf(symbol);
4084
+ if (col >= 0) {
4085
+ return { filePath: fullPath, line: i, char: col };
4086
+ }
4087
+ }
4088
+ }
4089
+ }
4090
+ }
4091
+ } catch {
4092
+ }
4093
+ return null;
4094
+ }
4095
+ return search(workingDirectory, 200);
4096
+ }
4097
+ var MAX_REF_FILES = 15;
4098
+ var MAX_LEVEL2_PARENTS = 8;
4099
+ var MAX_LEVEL2_SYMBOLS_PER_PARENT = 3;
4100
+ function createCodeGraphTool(options) {
4101
+ return tool7({
4102
+ description: `Inspect a symbol's type information and usage graph using the TypeScript language server.
4103
+
4104
+ Given a symbol name (function, component, class, type, etc.), this tool will:
4105
+ 1. Find its definition and full type signature (parameters, return type)
4106
+ 2. Find all references \u2014 what components/functions/files use this symbol
4107
+ 3. Identify which pages/routes contain it in their component tree
4108
+ 4. Show the file's symbol structure for surrounding context
4109
+
4110
+ Use this to understand:
4111
+ - Component hierarchies (what renders what, which pages are affected)
4112
+ - Type signatures and parameter/return types before making changes
4113
+ - How deeply a symbol is used across the codebase
4114
+ - What will break if you change something
4115
+
4116
+ Supports TypeScript, JavaScript, TSX, JSX files.
4117
+ Working directory: ${options.workingDirectory}`,
4118
+ inputSchema: codeGraphInputSchema,
4119
+ execute: async ({ symbol, filePath, depth }) => {
4120
+ const maxDepth = Math.min(depth ?? 2, 3);
4121
+ try {
4122
+ let defFilePath;
4123
+ let defLine = 0;
4124
+ let defChar = 0;
4125
+ let defSymbol = null;
4126
+ if (filePath) {
4127
+ const absPath = isAbsolute4(filePath) ? filePath : resolve8(options.workingDirectory, filePath);
4128
+ if (!existsSync10(absPath)) {
4129
+ return { success: false, error: `File not found: ${filePath}` };
4130
+ }
4131
+ if (!isSupported(absPath)) {
4132
+ return { success: false, error: `File type not supported. Supports: ${getSupportedExtensions().join(", ")}` };
4133
+ }
4134
+ await touchFile(absPath, true);
4135
+ const symbols = await getDocumentSymbols(absPath);
4136
+ defSymbol = findSymbolByName(symbols, symbol);
4137
+ if (defSymbol) {
4138
+ defFilePath = absPath;
4139
+ defLine = defSymbol.selectionRange.start.line;
4140
+ defChar = defSymbol.selectionRange.start.character;
4141
+ } else {
4142
+ const content = await readFile7(absPath, "utf-8");
4143
+ const lines2 = content.split("\n");
4144
+ const defPattern = new RegExp(
4145
+ `(export|function|const|let|var|class|interface|type|enum)\\s+.*\\b${symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`
4146
+ );
4147
+ for (let i = 0; i < lines2.length; i++) {
4148
+ if (defPattern.test(lines2[i])) {
4149
+ const col = lines2[i].indexOf(symbol);
4150
+ if (col !== -1) {
4151
+ defFilePath = absPath;
4152
+ defLine = i;
4153
+ defChar = col;
4154
+ break;
4155
+ }
4156
+ }
4157
+ }
4158
+ if (!defFilePath) {
4159
+ for (let i = 0; i < lines2.length; i++) {
4160
+ const col = lines2[i].indexOf(symbol);
4161
+ if (col !== -1) {
4162
+ defFilePath = absPath;
4163
+ defLine = i;
4164
+ defChar = col;
4165
+ break;
4166
+ }
4167
+ }
4168
+ }
4169
+ }
4170
+ } else {
4171
+ const found = await grepForSymbol(symbol, options.workingDirectory);
4172
+ if (found) {
4173
+ defFilePath = found.filePath;
4174
+ defLine = found.line;
4175
+ defChar = found.char;
4176
+ }
4177
+ }
4178
+ if (!defFilePath) {
4179
+ return {
4180
+ success: false,
4181
+ error: `Could not find symbol "${symbol}" in the codebase. Try providing a filePath.`
4182
+ };
4183
+ }
4184
+ await touchFile(defFilePath, true);
4185
+ const rawHover = await getHover(defFilePath, defLine, defChar);
4186
+ const typeInfo = rawHover ? cleanHoverText(rawHover) : null;
4187
+ const fileSymbols = await getDocumentSymbols(defFilePath);
4188
+ if (!defSymbol && fileSymbols.length > 0) {
4189
+ defSymbol = findSymbolByName(fileSymbols, symbol);
4190
+ }
4191
+ const references = await getReferences(defFilePath, defLine, defChar, false);
4192
+ const refsByFile = /* @__PURE__ */ new Map();
4193
+ for (const ref of references) {
4194
+ const refPath = fileURLToPath2(ref.uri);
4195
+ if (!refsByFile.has(refPath)) {
4196
+ refsByFile.set(refPath, []);
4197
+ }
4198
+ refsByFile.get(refPath).push(ref);
4199
+ }
4200
+ const refFileInfos = [];
4201
+ let processed = 0;
4202
+ for (const [refPath, locs] of refsByFile) {
4203
+ if (processed >= MAX_REF_FILES) break;
4204
+ if (refPath === defFilePath) continue;
4205
+ processed++;
4206
+ const relPath = relative7(options.workingDirectory, refPath);
4207
+ const pageFile = isPageFile(refPath);
4208
+ const routePath = pageFile ? extractRoutePath(refPath, options.workingDirectory) : void 0;
4209
+ await touchFile(refPath, false);
4210
+ const refFileSymbols = await getDocumentSymbols(refPath);
4211
+ const seen = /* @__PURE__ */ new Map();
4212
+ for (const loc of locs) {
4213
+ const container = findContainingSymbol(
4214
+ refFileSymbols,
4215
+ loc.range.start.line,
4216
+ loc.range.start.character
4217
+ );
4218
+ if (container && !seen.has(container.name)) {
4219
+ let containerHover = null;
4220
+ try {
4221
+ const raw = await getHover(
4222
+ refPath,
4223
+ container.selectionRange.start.line,
4224
+ container.selectionRange.start.character
4225
+ );
4226
+ if (raw) containerHover = cleanHoverText(raw).split("\n")[0];
4227
+ } catch {
4228
+ }
4229
+ seen.set(container.name, {
4230
+ name: container.name,
4231
+ kind: symbolKindName(container.kind),
4232
+ line: container.selectionRange.start.line + 1,
4233
+ char: container.selectionRange.start.character,
4234
+ typeInfo: containerHover || void 0
4235
+ });
4236
+ }
4237
+ }
4238
+ refFileInfos.push({
4239
+ filePath: refPath,
4240
+ relativePath: relPath,
4241
+ isPage: pageFile,
4242
+ routePath,
4243
+ containingSymbols: Array.from(seen.values())
4244
+ });
4245
+ }
4246
+ const level2Refs = [];
4247
+ if (maxDepth >= 2) {
4248
+ for (const refFile of refFileInfos.slice(0, MAX_LEVEL2_PARENTS)) {
4249
+ for (const sym of refFile.containingSymbols.slice(0, MAX_LEVEL2_SYMBOLS_PER_PARENT)) {
4250
+ try {
4251
+ const symLineIdx = sym.line - 1;
4252
+ const symChar = sym.char;
4253
+ const l2Locations = await getReferences(
4254
+ refFile.filePath,
4255
+ symLineIdx,
4256
+ symChar,
4257
+ false
4258
+ );
4259
+ const l2Nodes = [];
4260
+ const seenPaths = /* @__PURE__ */ new Set();
4261
+ for (const loc of l2Locations.slice(0, 10)) {
4262
+ const l2Path = fileURLToPath2(loc.uri);
4263
+ if (l2Path === refFile.filePath || l2Path === defFilePath) continue;
4264
+ if (seenPaths.has(l2Path)) continue;
4265
+ seenPaths.add(l2Path);
4266
+ const l2Rel = relative7(options.workingDirectory, l2Path);
4267
+ const l2Page = isPageFile(l2Path);
4268
+ const l2Route = l2Page ? extractRoutePath(l2Path, options.workingDirectory) : void 0;
4269
+ let containerName;
4270
+ try {
4271
+ await touchFile(l2Path, false);
4272
+ const l2Symbols = await getDocumentSymbols(l2Path);
4273
+ const container = findContainingSymbol(l2Symbols, loc.range.start.line, loc.range.start.character);
4274
+ if (container) containerName = container.name;
4275
+ } catch {
4276
+ }
4277
+ l2Nodes.push({
4278
+ relativePath: l2Rel,
4279
+ isPage: l2Page,
4280
+ routePath: l2Route,
4281
+ containingSymbol: containerName
4282
+ });
4283
+ }
4284
+ if (l2Nodes.length > 0) {
4285
+ level2Refs.push({
4286
+ parentSymbol: sym.name,
4287
+ parentFile: refFile.relativePath,
4288
+ refs: l2Nodes
4289
+ });
4290
+ }
4291
+ } catch {
4292
+ }
4293
+ }
4294
+ }
4295
+ }
4296
+ const relDefPath = relative7(options.workingDirectory, defFilePath);
4297
+ const lines = [];
4298
+ lines.push(`=== ${symbol} ===`);
4299
+ lines.push(`File: ${relDefPath}:${defLine + 1}`);
4300
+ if (defSymbol) lines.push(`Kind: ${symbolKindName(defSymbol.kind)}`);
4301
+ if (typeInfo) lines.push(`Type: ${typeInfo}`);
4302
+ const externalRefCount = references.filter((r) => fileURLToPath2(r.uri) !== defFilePath).length;
4303
+ const externalFileCount = refsByFile.size - (refsByFile.has(defFilePath) ? 1 : 0);
4304
+ if (refFileInfos.length > 0) {
4305
+ lines.push("");
4306
+ lines.push(`=== Referenced by (${externalRefCount} usages across ${externalFileCount} files) ===`);
4307
+ const pages = refFileInfos.filter((r) => r.isPage);
4308
+ const nonPages = refFileInfos.filter((r) => !r.isPage);
4309
+ if (pages.length > 0) {
4310
+ lines.push("");
4311
+ lines.push("Pages/Routes:");
4312
+ for (const page of pages) {
4313
+ lines.push(` ${page.relativePath}${page.routePath ? ` \u2192 ${page.routePath}` : ""}`);
4314
+ for (const s of page.containingSymbols) {
4315
+ lines.push(` \u2514\u2500\u2500 ${s.name} (${s.kind}:${s.line})${s.typeInfo ? ` \u2014 ${s.typeInfo}` : ""}`);
4316
+ }
4317
+ }
4318
+ }
4319
+ if (nonPages.length > 0) {
4320
+ lines.push("");
4321
+ lines.push("Components/Functions:");
4322
+ for (const ref of nonPages) {
4323
+ lines.push(` ${ref.relativePath}`);
4324
+ for (const s of ref.containingSymbols) {
4325
+ const typePart = s.typeInfo && s.typeInfo.length < 120 ? ` \u2014 ${s.typeInfo}` : "";
4326
+ lines.push(` \u2514\u2500\u2500 ${s.name} (${s.kind}:${s.line})${typePart}`);
4327
+ }
4328
+ }
4329
+ }
4330
+ } else {
4331
+ lines.push("");
4332
+ lines.push("No external references found (symbol may be unused or only used within the same file).");
4333
+ }
4334
+ if (level2Refs.length > 0) {
4335
+ lines.push("");
4336
+ lines.push("=== Extended tree (level 2) ===");
4337
+ for (const l2 of level2Refs) {
4338
+ lines.push("");
4339
+ lines.push(`${l2.parentSymbol} (${l2.parentFile}) is used by:`);
4340
+ for (const ref of l2.refs) {
4341
+ const tag = ref.isPage ? " [PAGE]" : "";
4342
+ const route = ref.routePath ? ` \u2192 ${ref.routePath}` : "";
4343
+ const container = ref.containingSymbol ? ` in ${ref.containingSymbol}` : "";
4344
+ lines.push(` \u2514\u2500\u2500 ${ref.relativePath}${tag}${route}${container}`);
4345
+ }
4346
+ }
4347
+ }
4348
+ if (fileSymbols.length > 0) {
4349
+ lines.push("");
4350
+ lines.push(`=== File structure (${basename3(defFilePath)}) ===`);
4351
+ for (const sym of fileSymbols) {
4352
+ const marker = sym.name === symbol ? " \u2190 target" : "";
4353
+ lines.push(` ${sym.name} (${symbolKindName(sym.kind)}:${sym.selectionRange.start.line + 1})${marker}`);
4354
+ if (sym.children) {
4355
+ for (const child of sym.children.slice(0, 10)) {
4356
+ lines.push(` \u2514\u2500\u2500 ${child.name} (${symbolKindName(child.kind)}:${child.selectionRange.start.line + 1})`);
4357
+ }
4358
+ if (sym.children.length > 10) {
4359
+ lines.push(` ... and ${sym.children.length - 10} more`);
4360
+ }
4361
+ }
4362
+ }
4363
+ }
4364
+ const formattedResult = lines.join("\n");
4365
+ return {
4366
+ success: true,
4367
+ symbol,
4368
+ filePath: relDefPath,
4369
+ line: defLine + 1,
4370
+ kind: defSymbol ? symbolKindName(defSymbol.kind) : void 0,
4371
+ typeInfo: typeInfo || void 0,
4372
+ referenceCount: externalRefCount,
4373
+ referenceFiles: externalFileCount,
4374
+ pages: refFileInfos.filter((r) => r.isPage).map((r) => ({ path: r.relativePath, route: r.routePath })),
4375
+ formattedResult
4376
+ };
4377
+ } catch (error) {
4378
+ return {
4379
+ success: false,
4380
+ error: error instanceof Error ? error.message : String(error)
4381
+ };
4382
+ }
4383
+ }
4384
+ });
4385
+ }
4386
+
4387
+ // src/agent/subagents/search.ts
3820
4388
  var execAsync4 = promisify4(exec4);
3821
4389
  var MAX_OUTPUT_CHARS4 = 1e4;
3822
4390
  var MAX_FILE_SIZE3 = 1 * 1024 * 1024;
@@ -3846,17 +4414,20 @@ ${contextBlock}
3846
4414
  - **glob**: Find files matching a name pattern. Best for file discovery.
3847
4415
  - **read_file**: Read contents of a specific file. Use to examine code found in searches.
3848
4416
  - **list_dir**: List directory contents. Use to understand project structure.
4417
+ - **code_graph**: Inspect a symbol's type hierarchy, references, and usage graph via the TypeScript language server. Returns type signatures, all files that reference the symbol, and which pages/routes contain it. Best for understanding component/function relationships and impact analysis.
3849
4418
 
3850
4419
  ## Search Strategy
3851
4420
 
3852
4421
  1. **Start with semantic_search** if available - it finds code by meaning, which is the fastest way to explore
3853
4422
  2. **Use grep** for exact symbol/string matches (function names, class names, imports)
3854
- 3. **Use glob** for file discovery by name patterns
3855
- 4. **Read key files** to get actual code content and understand context
3856
- 5. **Run searches in PARALLEL** - make multiple tool calls at once to cover different angles simultaneously. This is critical for speed.
4423
+ 3. **Use code_graph** when you need to understand a symbol's type signature, what depends on it, or which pages use it. It's much more precise than grep for understanding relationships.
4424
+ 4. **Use glob** for file discovery by name patterns
4425
+ 5. **Read key files** to get actual code content and understand context
4426
+ 6. **Run searches in PARALLEL** - make multiple tool calls at once to cover different angles simultaneously. This is critical for speed.
3857
4427
 
3858
4428
  ### Tool Selection Guide
3859
4429
  - Know the exact name? Use **grep** (e.g. \`getUserById\`, \`class AuthService\`)
4430
+ - Need type info, references, or impact analysis? Use **code_graph** (e.g. \`code_graph({ symbol: "UserCard" })\`)
3860
4431
  - Exploring a concept? Use **semantic_search** (e.g. "how does authentication work")
3861
4432
  - Looking for files? Use **glob** (e.g. \`**/*.config.ts\`, \`**/auth/**\`)
3862
4433
  - Need file content? Use **read_file** with optional line ranges for large files
@@ -3893,17 +4464,17 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
3893
4464
  async getToolsAsync(options) {
3894
4465
  const workingDirectory = options.workingDirectory;
3895
4466
  const tools = {
3896
- grep: tool8({
4467
+ grep: tool9({
3897
4468
  description: "Search for patterns in files using ripgrep. Returns matching lines with file paths and line numbers.",
3898
- inputSchema: z9.object({
3899
- pattern: z9.string().describe("The regex pattern to search for"),
3900
- path: z9.string().optional().describe("Subdirectory or file to search in (relative to working directory)"),
3901
- fileType: z9.string().optional().describe('File type to filter (e.g., "ts", "js", "py")'),
3902
- maxResults: z9.number().optional().default(50).describe("Maximum number of results to return")
4469
+ inputSchema: z10.object({
4470
+ pattern: z10.string().describe("The regex pattern to search for"),
4471
+ path: z10.string().optional().describe("Subdirectory or file to search in (relative to working directory)"),
4472
+ fileType: z10.string().optional().describe('File type to filter (e.g., "ts", "js", "py")'),
4473
+ maxResults: z10.number().optional().default(50).describe("Maximum number of results to return")
3903
4474
  }),
3904
4475
  execute: async ({ pattern, path, fileType, maxResults }) => {
3905
4476
  try {
3906
- const searchPath = path ? resolve8(workingDirectory, path) : workingDirectory;
4477
+ const searchPath = path ? resolve9(workingDirectory, path) : workingDirectory;
3907
4478
  let args = ["rg", "--line-number", "--no-heading"];
3908
4479
  if (fileType) {
3909
4480
  args.push("--type", fileType);
@@ -3940,11 +4511,11 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
3940
4511
  }
3941
4512
  }
3942
4513
  }),
3943
- glob: tool8({
4514
+ glob: tool9({
3944
4515
  description: "Find files matching a glob pattern. Returns list of matching file paths.",
3945
- inputSchema: z9.object({
3946
- pattern: z9.string().describe('Glob pattern (e.g., "**/*.ts", "src/**/*.tsx", "*.json")'),
3947
- maxResults: z9.number().optional().default(100).describe("Maximum number of files to return")
4516
+ inputSchema: z10.object({
4517
+ pattern: z10.string().describe('Glob pattern (e.g., "**/*.ts", "src/**/*.tsx", "*.json")'),
4518
+ maxResults: z10.number().optional().default(100).describe("Maximum number of files to return")
3948
4519
  }),
3949
4520
  execute: async ({ pattern, maxResults }) => {
3950
4521
  try {
@@ -3971,17 +4542,17 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
3971
4542
  }
3972
4543
  }
3973
4544
  }),
3974
- read_file: tool8({
4545
+ read_file: tool9({
3975
4546
  description: "Read the contents of a file. Use this to examine specific files found in search.",
3976
- inputSchema: z9.object({
3977
- path: z9.string().describe("Path to the file (relative to working directory or absolute)"),
3978
- startLine: z9.number().optional().describe("Start reading from this line (1-indexed)"),
3979
- endLine: z9.number().optional().describe("Stop reading at this line (1-indexed, inclusive)")
4547
+ inputSchema: z10.object({
4548
+ path: z10.string().describe("Path to the file (relative to working directory or absolute)"),
4549
+ startLine: z10.number().optional().describe("Start reading from this line (1-indexed)"),
4550
+ endLine: z10.number().optional().describe("Stop reading at this line (1-indexed, inclusive)")
3980
4551
  }),
3981
4552
  execute: async ({ path, startLine, endLine }) => {
3982
4553
  try {
3983
- const absolutePath = isAbsolute4(path) ? path : resolve8(workingDirectory, path);
3984
- if (!existsSync11(absolutePath)) {
4554
+ const absolutePath = isAbsolute5(path) ? path : resolve9(workingDirectory, path);
4555
+ if (!existsSync12(absolutePath)) {
3985
4556
  return {
3986
4557
  success: false,
3987
4558
  error: `File not found: ${path}`
@@ -3994,7 +4565,7 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
3994
4565
  error: `File too large (${(stats.size / 1024 / 1024).toFixed(2)}MB). Use startLine/endLine to read portions.`
3995
4566
  };
3996
4567
  }
3997
- let content = await readFile7(absolutePath, "utf-8");
4568
+ let content = await readFile8(absolutePath, "utf-8");
3998
4569
  if (startLine !== void 0 || endLine !== void 0) {
3999
4570
  const lines = content.split("\n");
4000
4571
  const start = (startLine ?? 1) - 1;
@@ -4003,7 +4574,7 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4003
4574
  }
4004
4575
  return {
4005
4576
  success: true,
4006
- path: relative7(workingDirectory, absolutePath),
4577
+ path: relative8(workingDirectory, absolutePath),
4007
4578
  content: truncateOutput(content, MAX_OUTPUT_CHARS4),
4008
4579
  lineCount: content.split("\n").length
4009
4580
  };
@@ -4015,17 +4586,17 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4015
4586
  }
4016
4587
  }
4017
4588
  }),
4018
- list_dir: tool8({
4589
+ list_dir: tool9({
4019
4590
  description: "List contents of a directory. Shows files and subdirectories.",
4020
- inputSchema: z9.object({
4021
- path: z9.string().optional().default(".").describe("Directory path (relative to working directory)"),
4022
- recursive: z9.boolean().optional().default(false).describe("List recursively (be careful with large directories)"),
4023
- maxDepth: z9.number().optional().default(2).describe("Maximum depth for recursive listing")
4591
+ inputSchema: z10.object({
4592
+ path: z10.string().optional().default(".").describe("Directory path (relative to working directory)"),
4593
+ recursive: z10.boolean().optional().default(false).describe("List recursively (be careful with large directories)"),
4594
+ maxDepth: z10.number().optional().default(2).describe("Maximum depth for recursive listing")
4024
4595
  }),
4025
4596
  execute: async ({ path, recursive, maxDepth }) => {
4026
4597
  try {
4027
- const absolutePath = isAbsolute4(path) ? path : resolve8(workingDirectory, path);
4028
- if (!existsSync11(absolutePath)) {
4598
+ const absolutePath = isAbsolute5(path) ? path : resolve9(workingDirectory, path);
4599
+ if (!existsSync12(absolutePath)) {
4029
4600
  return {
4030
4601
  success: false,
4031
4602
  error: `Directory not found: ${path}`
@@ -4049,20 +4620,20 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4049
4620
  const files = stdout.trim().split("\n").filter(Boolean);
4050
4621
  return {
4051
4622
  success: true,
4052
- path: relative7(workingDirectory, absolutePath) || ".",
4623
+ path: relative8(workingDirectory, absolutePath) || ".",
4053
4624
  files,
4054
4625
  count: files.length,
4055
4626
  recursive: true
4056
4627
  };
4057
4628
  } else {
4058
- const entries = await readdir3(absolutePath, { withFileTypes: true });
4629
+ const entries = await readdir4(absolutePath, { withFileTypes: true });
4059
4630
  const items = entries.slice(0, 200).map((e) => ({
4060
4631
  name: e.name,
4061
4632
  type: e.isDirectory() ? "directory" : "file"
4062
4633
  }));
4063
4634
  return {
4064
4635
  success: true,
4065
- path: relative7(workingDirectory, absolutePath) || ".",
4636
+ path: relative8(workingDirectory, absolutePath) || ".",
4066
4637
  items,
4067
4638
  count: items.length
4068
4639
  };
@@ -4074,6 +4645,9 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4074
4645
  };
4075
4646
  }
4076
4647
  }
4648
+ }),
4649
+ code_graph: createCodeGraphTool({
4650
+ workingDirectory
4077
4651
  })
4078
4652
  };
4079
4653
  try {
@@ -4167,6 +4741,26 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4167
4741
  context: m.symbolName || m.language
4168
4742
  });
4169
4743
  }
4744
+ } else if (step.toolName === "code_graph" && output.success) {
4745
+ matchCount += output.referenceCount || 0;
4746
+ if (output.filePath) {
4747
+ findings.push({
4748
+ type: "file",
4749
+ path: output.filePath,
4750
+ lineNumber: output.line,
4751
+ content: output.typeInfo ? truncateOutput(output.typeInfo, 300) : void 0,
4752
+ relevance: "high",
4753
+ context: `${output.kind || "symbol"}${output.referenceCount ? `, ${output.referenceCount} refs` : ""}`
4754
+ });
4755
+ }
4756
+ for (const page of (output.pages || []).slice(0, 10)) {
4757
+ findings.push({
4758
+ type: "file",
4759
+ path: page.path,
4760
+ relevance: "high",
4761
+ context: page.route ? `route: ${page.route}` : "page"
4762
+ });
4763
+ }
4170
4764
  }
4171
4765
  }
4172
4766
  }
@@ -4188,7 +4782,7 @@ function createSearchSubagent(model) {
4188
4782
  // src/tools/search.ts
4189
4783
  var MAX_RESULT_CHARS = 1e4;
4190
4784
  function createSearchTool(options) {
4191
- return tool9({
4785
+ return tool10({
4192
4786
  description: `Delegate an explore task to the explore_agent tool. Use this when you need to:
4193
4787
  - Find files or code matching a pattern
4194
4788
  - Explore the codebase structure
@@ -4198,11 +4792,12 @@ function createSearchTool(options) {
4198
4792
  The Explore agent will explore the codebase and return a summary of findings.
4199
4793
  This is more thorough than a simple grep because it can follow references and understand context.
4200
4794
  It also has access to semantic search to find code by meaning, not just text.
4795
+ It can also use code_graph to inspect a symbol's type hierarchy, references, and which pages/routes use it.
4201
4796
 
4202
4797
  CRITICAL: The explore agent has ZERO context. It cannot see the conversation, the user's message, devtools data, or any prior context. You MUST pass ALL relevant context via the "context" parameter. If the user selected a component (component name, file path, HTML, component stack) or there is a <devtools-context> block, you MUST copy that information into the "context" field verbatim. Without it the explore agent is searching blind.`,
4203
- inputSchema: z10.object({
4204
- query: z10.string().describe("What to search for. Be specific about what you're looking for."),
4205
- context: z10.string().describe("ALL context the explore agent needs. It has ZERO context on its own - no conversation history, no devtools data, nothing. You MUST include: any selected component info (name, file path, HTML, component stack), any <devtools-context> block (page URL, path, viewport), and any other relevant details from the user message. The explore agent literally only sees the query and this context field.")
4798
+ inputSchema: z11.object({
4799
+ query: z11.string().describe("What to search for. Be specific about what you're looking for."),
4800
+ context: z11.string().describe("ALL context the explore agent needs. It has ZERO context on its own - no conversation history, no devtools data, nothing. You MUST include: any selected component info (name, file path, HTML, component stack), any <devtools-context> block (page URL, path, viewport), and any other relevant details from the user message. The explore agent literally only sees the query and this context field.")
4206
4801
  }),
4207
4802
  execute: async ({ query, context }, toolOptions) => {
4208
4803
  const toolCallId = toolOptions.toolCallId || `explore_agent_${Date.now()}`;
@@ -4346,6 +4941,9 @@ async function createTools(options) {
4346
4941
  sessionId: options.sessionId,
4347
4942
  workingDirectory: options.workingDirectory,
4348
4943
  onProgress: options.onSearchProgress
4944
+ }),
4945
+ code_graph: createCodeGraphTool({
4946
+ workingDirectory: options.workingDirectory
4349
4947
  })
4350
4948
  };
4351
4949
  if (options.enableSemanticSearch !== false) {
@@ -4437,6 +5035,7 @@ You have access to powerful tools for:
4437
5035
  - **todo**: Manage your task list to track progress on complex operations
4438
5036
  - **load_skill**: Load specialized knowledge documents for specific tasks
4439
5037
  - **explore_agent**: Explore agent for semantic discovery - for exploratory questions and finding code by meaning
5038
+ - **code_graph**: Inspect a symbol's type hierarchy and usage graph via the TypeScript language server
4440
5039
 
4441
5040
 
4442
5041
  IMPORTANT: If you have zero context of where you are working, always explore it first to understand the structure before doing things for the user.
@@ -4526,6 +5125,33 @@ linter({ paths: ["src/"] }) // Check all files in a directory
4526
5125
  \`\`\`
4527
5126
  Use this proactively after making code changes to catch errors early.
4528
5127
 
5128
+ ### Code Graph Tool
5129
+ The code_graph tool uses the TypeScript language server to inspect a symbol's type hierarchy and usage graph:
5130
+ \`\`\`
5131
+ code_graph({ symbol: "UserCard" }) // Search workspace for symbol
5132
+ code_graph({ symbol: "UserCard", filePath: "src/components.tsx" }) // Look up in a specific file
5133
+ code_graph({ symbol: "formatUser", filePath: "utils.ts", depth: 2 }) // Traverse 2 levels up the reference tree
5134
+ \`\`\`
5135
+
5136
+ **What it returns:**
5137
+ - The symbol's full type signature (parameters, return type)
5138
+ - All files/functions/components that reference it (grouped into pages vs components)
5139
+ - Which Next.js pages/routes contain it in their component tree
5140
+ - Level-2 transitive usages (who uses the things that use this symbol)
5141
+ - The file's symbol structure for surrounding context
5142
+
5143
+ **When to use code_graph:**
5144
+ - **To locate a component/function by name** when you don't have the file path \u2014 e.g. a user mentions a component from devtools but the path is missing or mangled. Just pass the symbol name and it will find the definition.
5145
+ - **Before making changes** to a function/component \u2014 understand what depends on it and what will break
5146
+ - **To understand component hierarchies** \u2014 what renders what, which pages are affected across the *entire* codebase (not just the current page)
5147
+ - **To get type signatures** (props, params, return types) without reading entire files
5148
+ - **After a devtools selection** when the task involves refactoring, changing props, or anything that could impact other consumers
5149
+
5150
+ **When NOT to use code_graph:**
5151
+ - For exploratory "how does X work?" questions \u2014 use \`explore_agent\` instead
5152
+ - For exact string searches \u2014 use grep/rg directly
5153
+ - For non-TypeScript/JavaScript files \u2014 code_graph only supports TS/JS/TSX/JSX
5154
+
4529
5155
  ### Searching and Exploration
4530
5156
 
4531
5157
  **Choose the right search approach:**
@@ -4533,7 +5159,8 @@ Use this proactively after making code changes to catch errors early.
4533
5159
  0. **Use paths to your advantage \u2014 skip searching if you already have what you need.**
4534
5160
  - If the user selected a component via devtools and you can see the component name, file path, and/or line number, you ALREADY know where the code is. Just use \`read_file\` to read that file directly \u2014 do NOT call \`explore_agent\` to "find" something you already have the location of.
4535
5161
  - If you received a **page path** (e.g. \`/dashboard\`, \`/settings/profile\`), map it to the corresponding file in the project structure. In Next.js this means \`app/dashboard/page.tsx\`, \`app/settings/profile/page.tsx\`, etc. In other frameworks, check the routing convention (e.g. \`pages/\`, \`src/routes/\`). Use \`read_file\` on the mapped path directly.
4536
- - If the file path doesn't exist or \`read_file\` fails, fall back to grep to locate it (e.g. \`rg "ComponentName" --type ts -l\`) since devtools paths can sometimes be slightly off or truncated.
5162
+ - **If the file path is missing, truncated, or doesn't exist** (common with devtools \u2014 webpack paths can be mangled), use \`code_graph({ symbol: "ComponentName" })\` to locate the component. This searches the workspace for the symbol definition AND returns its type info, references, and page locations in one call \u2014 much better than raw grep for components.
5163
+ - **After reading a devtools-selected component**, if the task involves changes that could affect other consumers (refactoring, changing props, renaming), use \`code_graph\` to see ALL files and pages that depend on it \u2014 the devtools component stack only shows the current page's hierarchy, not the full picture.
4537
5164
  - Read up and down component trees when you have the file path or page path to find what you're looking for.
4538
5165
  1. **Use the \`explore_agent\` tool (Explore agent)** for:
4539
5166
  - Semantic/exploratory questions: "How does authentication work?", "Where is user data processed?"
@@ -4551,7 +5178,14 @@ Use this proactively after making code changes to catch errors early.
4551
5178
  - If you skip the \`context\` field, the explore agent is searching completely blind and will waste time guessing.
4552
5179
  - NEVER call \`explore_agent\` with only a \`query\` and no \`context\` when the user's message contains devtools or component information.
4553
5180
 
4554
- 2. **Use direct commands (grep/rg, find)** for:
5181
+ 2. **Use the \`code_graph\` tool** for:
5182
+ - Understanding what depends on a specific symbol before changing it
5183
+ - Tracing component/function usage up to page-level routes
5184
+ - Getting type signatures (params, return types) without reading full files
5185
+ - Finding exact components usages in the codebase
5186
+ - Answering "what will break if I change this?" or "which pages use this component?"
5187
+
5188
+ 3. **Use direct commands (grep/rg, find)** for:
4555
5189
  - Exact string matches: \`rg "functionName"\`, \`rg "class MyClass"\`
4556
5190
  - Finding files by name: \`find . -name "*.config.ts"\`
4557
5191
  - Simple pattern matching when you know exactly what you're looking for
@@ -4559,7 +5193,11 @@ Use this proactively after making code changes to catch errors early.
4559
5193
 
4560
5194
  **Examples:**
4561
5195
  - User selected \`<LandingButton>\` at \`src/components/LandingButton.tsx:12\` \u2192 Just \`read_file("src/components/LandingButton.tsx")\`. Do NOT call explore_agent.
5196
+ - User selected \`<PricingCard>\` but no file path in the component stack \u2192 Use \`code_graph({ symbol: "PricingCard" })\` to find its definition, type info, and all usages at once.
5197
+ - User selected \`<UserCard>\` and says "refactor the props" \u2192 First \`read_file\` the component, then \`code_graph({ symbol: "UserCard" })\` to see every file/page that depends on it before changing the interface.
4562
5198
  - "Where is the API authentication handled?" (no file path given) \u2192 Use \`explore_agent\` tool
5199
+ - "What pages use the UserCard component?" \u2192 Use \`code_graph({ symbol: "UserCard" })\`
5200
+ - "What's the type signature of formatUser?" \u2192 Use \`code_graph({ symbol: "formatUser", filePath: "utils.ts" })\`
4563
5201
  - "Find all usages of getUserById" \u2192 Use \`rg "getUserById"\`
4564
5202
  - "How does the payment flow work?" \u2192 Use \`explore_agent\` tool
4565
5203
  - "Find files named config" \u2192 Use \`find . -name "*config*"\`
@@ -5131,9 +5769,9 @@ ${prompt}` });
5131
5769
  wrappedTools[name] = originalTool;
5132
5770
  continue;
5133
5771
  }
5134
- wrappedTools[name] = tool10({
5772
+ wrappedTools[name] = tool11({
5135
5773
  description: originalTool.description || "",
5136
- inputSchema: originalTool.inputSchema || z11.object({}),
5774
+ inputSchema: originalTool.inputSchema || z12.object({}),
5137
5775
  execute: async (input, toolOptions) => {
5138
5776
  const toolCallId = toolOptions.toolCallId || nanoid3();
5139
5777
  const execution = toolExecutionQueries.create({
@@ -5147,8 +5785,8 @@ ${prompt}` });
5147
5785
  this.pendingApprovals.set(toolCallId, await execution);
5148
5786
  options.onApprovalRequired?.(await execution);
5149
5787
  await sessionQueries.updateStatus(this.session.id, "waiting");
5150
- const approved = await new Promise((resolve10) => {
5151
- approvalResolvers.set(toolCallId, { resolve: resolve10, sessionId: this.session.id });
5788
+ const approved = await new Promise((resolve11) => {
5789
+ approvalResolvers.set(toolCallId, { resolve: resolve11, sessionId: this.session.id });
5152
5790
  });
5153
5791
  const resolverData = approvalResolvers.get(toolCallId);
5154
5792
  approvalResolvers.delete(toolCallId);
@@ -5274,18 +5912,18 @@ function cleanupPendingInputs() {
5274
5912
  }
5275
5913
  }
5276
5914
  }
5277
- var createSessionSchema = z12.object({
5278
- name: z12.string().optional(),
5279
- workingDirectory: z12.string().optional(),
5280
- model: z12.string().optional(),
5281
- toolApprovals: z12.record(z12.string(), z12.boolean()).optional()
5915
+ var createSessionSchema = z13.object({
5916
+ name: z13.string().optional(),
5917
+ workingDirectory: z13.string().optional(),
5918
+ model: z13.string().optional(),
5919
+ toolApprovals: z13.record(z13.string(), z13.boolean()).optional()
5282
5920
  });
5283
- var paginationQuerySchema = z12.object({
5284
- limit: z12.string().optional(),
5285
- offset: z12.string().optional()
5921
+ var paginationQuerySchema = z13.object({
5922
+ limit: z13.string().optional(),
5923
+ offset: z13.string().optional()
5286
5924
  });
5287
- var messagesQuerySchema = z12.object({
5288
- limit: z12.string().optional()
5925
+ var messagesQuerySchema = z13.object({
5926
+ limit: z13.string().optional()
5289
5927
  });
5290
5928
  sessions.get(
5291
5929
  "/",
@@ -5424,10 +6062,10 @@ sessions.get("/:id/tools", async (c) => {
5424
6062
  count: executions.length
5425
6063
  });
5426
6064
  });
5427
- var updateSessionSchema = z12.object({
5428
- model: z12.string().optional(),
5429
- name: z12.string().optional(),
5430
- toolApprovals: z12.record(z12.string(), z12.boolean()).optional()
6065
+ var updateSessionSchema = z13.object({
6066
+ model: z13.string().optional(),
6067
+ name: z13.string().optional(),
6068
+ toolApprovals: z13.record(z13.string(), z13.boolean()).optional()
5431
6069
  });
5432
6070
  sessions.patch(
5433
6071
  "/:id",
@@ -5497,8 +6135,8 @@ sessions.post("/:id/clear", async (c) => {
5497
6135
  await agent.clearContext();
5498
6136
  return c.json({ success: true, sessionId: id });
5499
6137
  });
5500
- var pendingInputSchema = z12.object({
5501
- text: z12.string()
6138
+ var pendingInputSchema = z13.object({
6139
+ text: z13.string()
5502
6140
  });
5503
6141
  sessions.post(
5504
6142
  "/:id/pending-input",
@@ -5529,13 +6167,13 @@ sessions.get("/:id/pending-input", async (c) => {
5529
6167
  createdAt: pending.createdAt.toISOString()
5530
6168
  });
5531
6169
  });
5532
- var devtoolsContextSchema = z12.object({
5533
- url: z12.string(),
5534
- path: z12.string(),
5535
- pageName: z12.string().optional(),
5536
- screenWidth: z12.number().optional(),
5537
- screenHeight: z12.number().optional(),
5538
- devicePixelRatio: z12.number().optional()
6170
+ var devtoolsContextSchema = z13.object({
6171
+ url: z13.string(),
6172
+ path: z13.string(),
6173
+ pageName: z13.string().optional(),
6174
+ screenWidth: z13.number().optional(),
6175
+ screenHeight: z13.number().optional(),
6176
+ devicePixelRatio: z13.number().optional()
5539
6177
  });
5540
6178
  sessions.post(
5541
6179
  "/:id/devtools-context",
@@ -5707,7 +6345,7 @@ function getAttachmentsDir(sessionId) {
5707
6345
  }
5708
6346
  function ensureAttachmentsDir(sessionId) {
5709
6347
  const dir = getAttachmentsDir(sessionId);
5710
- if (!existsSync12(dir)) {
6348
+ if (!existsSync13(dir)) {
5711
6349
  mkdirSync3(dir, { recursive: true });
5712
6350
  }
5713
6351
  return dir;
@@ -5719,7 +6357,7 @@ sessions.get("/:id/attachments", async (c) => {
5719
6357
  return c.json({ error: "Session not found" }, 404);
5720
6358
  }
5721
6359
  const dir = getAttachmentsDir(sessionId);
5722
- if (!existsSync12(dir)) {
6360
+ if (!existsSync13(dir)) {
5723
6361
  return c.json({ sessionId, attachments: [], count: 0 });
5724
6362
  }
5725
6363
  const files = readdirSync(dir);
@@ -5758,7 +6396,7 @@ sessions.post("/:id/attachments", async (c) => {
5758
6396
  const dir = ensureAttachmentsDir(sessionId);
5759
6397
  const id = nanoid4(10);
5760
6398
  const ext = extname6(file.name) || "";
5761
- const safeFilename = `${id}_${basename3(file.name).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
6399
+ const safeFilename = `${id}_${basename4(file.name).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
5762
6400
  const filePath = join5(dir, safeFilename);
5763
6401
  const arrayBuffer = await file.arrayBuffer();
5764
6402
  writeFileSync2(filePath, Buffer.from(arrayBuffer));
@@ -5784,7 +6422,7 @@ sessions.post("/:id/attachments", async (c) => {
5784
6422
  const dir = ensureAttachmentsDir(sessionId);
5785
6423
  const id = nanoid4(10);
5786
6424
  const ext = extname6(body.filename) || "";
5787
- const safeFilename = `${id}_${basename3(body.filename).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
6425
+ const safeFilename = `${id}_${basename4(body.filename).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
5788
6426
  const filePath = join5(dir, safeFilename);
5789
6427
  let base64Data = body.data;
5790
6428
  if (base64Data.includes(",")) {
@@ -5814,7 +6452,7 @@ sessions.delete("/:id/attachments/:attachmentId", async (c) => {
5814
6452
  return c.json({ error: "Session not found" }, 404);
5815
6453
  }
5816
6454
  const dir = getAttachmentsDir(sessionId);
5817
- if (!existsSync12(dir)) {
6455
+ if (!existsSync13(dir)) {
5818
6456
  return c.json({ error: "Attachment not found" }, 404);
5819
6457
  }
5820
6458
  const files = readdirSync(dir);
@@ -5826,10 +6464,10 @@ sessions.delete("/:id/attachments/:attachmentId", async (c) => {
5826
6464
  unlinkSync(filePath);
5827
6465
  return c.json({ success: true, id: attachmentId });
5828
6466
  });
5829
- var filesQuerySchema = z12.object({
5830
- query: z12.string().optional(),
6467
+ var filesQuerySchema = z13.object({
6468
+ query: z13.string().optional(),
5831
6469
  // Filter query (e.g., "src/com" to match "src/components")
5832
- limit: z12.string().optional()
6470
+ limit: z13.string().optional()
5833
6471
  // Max results (default 50)
5834
6472
  });
5835
6473
  var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
@@ -5902,11 +6540,11 @@ async function listWorkspaceFiles(baseDir, currentDir, query, limit, results = [
5902
6540
  return results;
5903
6541
  }
5904
6542
  try {
5905
- const entries = await readdir4(currentDir, { withFileTypes: true });
6543
+ const entries = await readdir5(currentDir, { withFileTypes: true });
5906
6544
  for (const entry of entries) {
5907
6545
  if (results.length >= limit * 2) break;
5908
6546
  const fullPath = join5(currentDir, entry.name);
5909
- const relativePath = relative8(baseDir, fullPath);
6547
+ const relativePath = relative9(baseDir, fullPath);
5910
6548
  if (entry.isDirectory() && IGNORED_DIRECTORIES.has(entry.name)) {
5911
6549
  continue;
5912
6550
  }
@@ -5953,7 +6591,7 @@ sessions.get(
5953
6591
  return c.json({ error: "Session not found" }, 404);
5954
6592
  }
5955
6593
  const workingDirectory = session.workingDirectory;
5956
- if (!existsSync12(workingDirectory)) {
6594
+ if (!existsSync13(workingDirectory)) {
5957
6595
  return c.json({
5958
6596
  sessionId,
5959
6597
  workingDirectory,
@@ -6007,8 +6645,8 @@ sessions.get(
6007
6645
  init_db();
6008
6646
  import { Hono as Hono2 } from "hono";
6009
6647
  import { zValidator as zValidator2 } from "@hono/zod-validator";
6010
- import { z as z13 } from "zod";
6011
- import { existsSync as existsSync13, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
6648
+ import { z as z14 } from "zod";
6649
+ import { existsSync as existsSync14, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
6012
6650
  import { join as join6 } from "path";
6013
6651
  init_config();
6014
6652
 
@@ -6149,7 +6787,7 @@ async function emitSyntheticToolStreaming(writeSSE, toolCallStarts, toolCallId,
6149
6787
  toolCallId,
6150
6788
  argsTextDelta: chunk
6151
6789
  }));
6152
- await new Promise((resolve10) => setTimeout(resolve10, 0));
6790
+ await new Promise((resolve11) => setTimeout(resolve11, 0));
6153
6791
  }
6154
6792
  }
6155
6793
  function buildDevtoolsContextXml(sessionId) {
@@ -6172,30 +6810,30 @@ function enrichPromptWithDevtoolsContext(sessionId, prompt) {
6172
6810
  ${prompt}`;
6173
6811
  }
6174
6812
  var agents = new Hono2();
6175
- var attachmentSchema = z13.object({
6176
- type: z13.enum(["image", "file"]),
6177
- data: z13.string(),
6813
+ var attachmentSchema = z14.object({
6814
+ type: z14.enum(["image", "file"]),
6815
+ data: z14.string(),
6178
6816
  // base64 data URL or raw base64
6179
- mediaType: z13.string().optional(),
6180
- filename: z13.string().optional()
6817
+ mediaType: z14.string().optional(),
6818
+ filename: z14.string().optional()
6181
6819
  });
6182
- var runPromptSchema = z13.object({
6183
- prompt: z13.string(),
6820
+ var runPromptSchema = z14.object({
6821
+ prompt: z14.string(),
6184
6822
  // Can be empty if attachments are provided
6185
- attachments: z13.array(attachmentSchema).optional()
6823
+ attachments: z14.array(attachmentSchema).optional()
6186
6824
  }).refine(
6187
6825
  (data) => data.prompt.trim().length > 0 || data.attachments && data.attachments.length > 0,
6188
6826
  { message: "Either prompt or attachments must be provided" }
6189
6827
  );
6190
- var quickStartSchema = z13.object({
6191
- prompt: z13.string().min(1),
6192
- name: z13.string().optional(),
6193
- workingDirectory: z13.string().optional(),
6194
- model: z13.string().optional(),
6195
- toolApprovals: z13.record(z13.string(), z13.boolean()).optional()
6828
+ var quickStartSchema = z14.object({
6829
+ prompt: z14.string().min(1),
6830
+ name: z14.string().optional(),
6831
+ workingDirectory: z14.string().optional(),
6832
+ model: z14.string().optional(),
6833
+ toolApprovals: z14.record(z14.string(), z14.boolean()).optional()
6196
6834
  });
6197
- var rejectSchema = z13.object({
6198
- reason: z13.string().optional()
6835
+ var rejectSchema = z14.object({
6836
+ reason: z14.string().optional()
6199
6837
  }).optional();
6200
6838
  var streamAbortControllers = /* @__PURE__ */ new Map();
6201
6839
  function getAttachmentsDirectory(sessionId) {
@@ -6204,7 +6842,7 @@ function getAttachmentsDirectory(sessionId) {
6204
6842
  }
6205
6843
  function saveAttachmentToDisk(sessionId, attachment, index) {
6206
6844
  const attachmentsDir = getAttachmentsDirectory(sessionId);
6207
- if (!existsSync13(attachmentsDir)) {
6845
+ if (!existsSync14(attachmentsDir)) {
6208
6846
  mkdirSync4(attachmentsDir, { recursive: true });
6209
6847
  }
6210
6848
  let filename = attachment.filename;
@@ -6382,7 +7020,7 @@ ${prompt}` });
6382
7020
  chunkIndex,
6383
7021
  chunkCount
6384
7022
  }));
6385
- await new Promise((resolve10) => setTimeout(resolve10, 0));
7023
+ await new Promise((resolve11) => setTimeout(resolve11, 0));
6386
7024
  }
6387
7025
  },
6388
7026
  onStepFinish: async () => {
@@ -6846,7 +7484,7 @@ agents.post(
6846
7484
  chunkIndex,
6847
7485
  chunkCount
6848
7486
  }));
6849
- await new Promise((resolve10) => setTimeout(resolve10, 0));
7487
+ await new Promise((resolve11) => setTimeout(resolve11, 0));
6850
7488
  }
6851
7489
  },
6852
7490
  onStepFinish: async () => {
@@ -6983,11 +7621,11 @@ agents.post(
6983
7621
  init_config();
6984
7622
  import { Hono as Hono3 } from "hono";
6985
7623
  import { zValidator as zValidator3 } from "@hono/zod-validator";
6986
- import { z as z14 } from "zod";
7624
+ import { z as z15 } from "zod";
6987
7625
  import { readFileSync as readFileSync5 } from "fs";
6988
- import { fileURLToPath as fileURLToPath2 } from "url";
7626
+ import { fileURLToPath as fileURLToPath3 } from "url";
6989
7627
  import { dirname as dirname6, join as join7 } from "path";
6990
- var __filename = fileURLToPath2(import.meta.url);
7628
+ var __filename = fileURLToPath3(import.meta.url);
6991
7629
  var __dirname = dirname6(__filename);
6992
7630
  var possiblePaths = [
6993
7631
  join7(__dirname, "../package.json"),
@@ -7093,9 +7731,9 @@ health.get("/api-keys", async (c) => {
7093
7731
  supportedProviders: SUPPORTED_PROVIDERS
7094
7732
  });
7095
7733
  });
7096
- var setApiKeySchema = z14.object({
7097
- provider: z14.string(),
7098
- apiKey: z14.string().min(1)
7734
+ var setApiKeySchema = z15.object({
7735
+ provider: z15.string(),
7736
+ apiKey: z15.string().min(1)
7099
7737
  });
7100
7738
  health.post(
7101
7739
  "/api-keys",
@@ -7134,13 +7772,13 @@ health.delete("/api-keys/:provider", async (c) => {
7134
7772
  // src/server/routes/terminals.ts
7135
7773
  import { Hono as Hono4 } from "hono";
7136
7774
  import { zValidator as zValidator4 } from "@hono/zod-validator";
7137
- import { z as z15 } from "zod";
7775
+ import { z as z16 } from "zod";
7138
7776
  init_db();
7139
7777
  var terminals = new Hono4();
7140
- var spawnSchema = z15.object({
7141
- command: z15.string(),
7142
- cwd: z15.string().optional(),
7143
- name: z15.string().optional()
7778
+ var spawnSchema = z16.object({
7779
+ command: z16.string(),
7780
+ cwd: z16.string().optional(),
7781
+ name: z16.string().optional()
7144
7782
  });
7145
7783
  terminals.post(
7146
7784
  "/:sessionId/terminals",
@@ -7221,8 +7859,8 @@ terminals.get("/:sessionId/terminals/:terminalId", async (c) => {
7221
7859
  // We don't track exit codes in tmux mode
7222
7860
  });
7223
7861
  });
7224
- var logsQuerySchema = z15.object({
7225
- tail: z15.string().optional().transform((v) => v ? parseInt(v, 10) : void 0)
7862
+ var logsQuerySchema = z16.object({
7863
+ tail: z16.string().optional().transform((v) => v ? parseInt(v, 10) : void 0)
7226
7864
  });
7227
7865
  terminals.get(
7228
7866
  "/:sessionId/terminals/:terminalId/logs",
@@ -7246,8 +7884,8 @@ terminals.get(
7246
7884
  });
7247
7885
  }
7248
7886
  );
7249
- var killSchema = z15.object({
7250
- signal: z15.enum(["SIGTERM", "SIGKILL"]).optional()
7887
+ var killSchema = z16.object({
7888
+ signal: z16.enum(["SIGTERM", "SIGKILL"]).optional()
7251
7889
  });
7252
7890
  terminals.post(
7253
7891
  "/:sessionId/terminals/:terminalId/kill",
@@ -7261,8 +7899,8 @@ terminals.post(
7261
7899
  return c.json({ success: true, message: "Terminal killed" });
7262
7900
  }
7263
7901
  );
7264
- var writeSchema = z15.object({
7265
- input: z15.string()
7902
+ var writeSchema = z16.object({
7903
+ input: z16.string()
7266
7904
  });
7267
7905
  terminals.post(
7268
7906
  "/:sessionId/terminals/:terminalId/write",
@@ -7531,13 +8169,13 @@ var DEFAULT_WEB_PORT = 6969;
7531
8169
  var WEB_PORT_SEQUENCE = [6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978];
7532
8170
  function getWebDirectory() {
7533
8171
  try {
7534
- const currentDir = dirname7(fileURLToPath3(import.meta.url));
7535
- const webDir = resolve9(currentDir, "..", "web");
7536
- if (existsSync14(webDir) && existsSync14(join8(webDir, "package.json"))) {
8172
+ const currentDir = dirname7(fileURLToPath4(import.meta.url));
8173
+ const webDir = resolve10(currentDir, "..", "web");
8174
+ if (existsSync15(webDir) && existsSync15(join8(webDir, "package.json"))) {
7537
8175
  return webDir;
7538
8176
  }
7539
- const altWebDir = resolve9(currentDir, "..", "..", "web");
7540
- if (existsSync14(altWebDir) && existsSync14(join8(altWebDir, "package.json"))) {
8177
+ const altWebDir = resolve10(currentDir, "..", "..", "web");
8178
+ if (existsSync15(altWebDir) && existsSync15(join8(altWebDir, "package.json"))) {
7541
8179
  return altWebDir;
7542
8180
  }
7543
8181
  return null;
@@ -7560,18 +8198,18 @@ async function isSparkcoderWebRunning(port) {
7560
8198
  }
7561
8199
  }
7562
8200
  function isPortInUse(port) {
7563
- return new Promise((resolve10) => {
8201
+ return new Promise((resolve11) => {
7564
8202
  const server = createNetServer();
7565
8203
  server.once("error", (err) => {
7566
8204
  if (err.code === "EADDRINUSE") {
7567
- resolve10(true);
8205
+ resolve11(true);
7568
8206
  } else {
7569
- resolve10(false);
8207
+ resolve11(false);
7570
8208
  }
7571
8209
  });
7572
8210
  server.once("listening", () => {
7573
8211
  server.close();
7574
- resolve10(false);
8212
+ resolve11(false);
7575
8213
  });
7576
8214
  server.listen(port, "0.0.0.0");
7577
8215
  });
@@ -7596,14 +8234,14 @@ async function findWebPort(preferredPort) {
7596
8234
  }
7597
8235
  function hasProductionBuild(webDir) {
7598
8236
  const buildIdPath = join8(webDir, ".next", "BUILD_ID");
7599
- return existsSync14(buildIdPath);
8237
+ return existsSync15(buildIdPath);
7600
8238
  }
7601
8239
  function hasSourceFiles(webDir) {
7602
8240
  const appDir = join8(webDir, "src", "app");
7603
8241
  const pagesDir = join8(webDir, "src", "pages");
7604
8242
  const rootAppDir = join8(webDir, "app");
7605
8243
  const rootPagesDir = join8(webDir, "pages");
7606
- return existsSync14(appDir) || existsSync14(pagesDir) || existsSync14(rootAppDir) || existsSync14(rootPagesDir);
8244
+ return existsSync15(appDir) || existsSync15(pagesDir) || existsSync15(rootAppDir) || existsSync15(rootPagesDir);
7607
8245
  }
7608
8246
  function getStandaloneServerPath(webDir) {
7609
8247
  const possiblePaths2 = [
@@ -7611,14 +8249,14 @@ function getStandaloneServerPath(webDir) {
7611
8249
  join8(webDir, ".next", "standalone", "web", "server.js")
7612
8250
  ];
7613
8251
  for (const serverPath of possiblePaths2) {
7614
- if (existsSync14(serverPath)) {
8252
+ if (existsSync15(serverPath)) {
7615
8253
  return serverPath;
7616
8254
  }
7617
8255
  }
7618
8256
  return null;
7619
8257
  }
7620
8258
  function runCommand(command, args, cwd, env) {
7621
- return new Promise((resolve10) => {
8259
+ return new Promise((resolve11) => {
7622
8260
  const child = spawn2(command, args, {
7623
8261
  cwd,
7624
8262
  stdio: ["ignore", "pipe", "pipe"],
@@ -7633,10 +8271,10 @@ function runCommand(command, args, cwd, env) {
7633
8271
  output += data.toString();
7634
8272
  });
7635
8273
  child.on("close", (code) => {
7636
- resolve10({ success: code === 0, output });
8274
+ resolve11({ success: code === 0, output });
7637
8275
  });
7638
8276
  child.on("error", (err) => {
7639
- resolve10({ success: false, output: err.message });
8277
+ resolve11({ success: false, output: err.message });
7640
8278
  });
7641
8279
  });
7642
8280
  }
@@ -7651,8 +8289,8 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
7651
8289
  if (!quiet) console.log(` \u2713 Web UI already running at http://localhost:${actualPort}`);
7652
8290
  return { process: null, port: actualPort };
7653
8291
  }
7654
- const usePnpm = existsSync14(join8(webDir, "pnpm-lock.yaml"));
7655
- const useNpm = !usePnpm && existsSync14(join8(webDir, "package-lock.json"));
8292
+ const usePnpm = existsSync15(join8(webDir, "pnpm-lock.yaml"));
8293
+ const useNpm = !usePnpm && existsSync15(join8(webDir, "package-lock.json"));
7656
8294
  const pkgManager = usePnpm ? "pnpm" : useNpm ? "npm" : "npx";
7657
8295
  const { NODE_OPTIONS, TSX_TSCONFIG_PATH, ...cleanEnv } = process.env;
7658
8296
  const apiUrl = publicUrl || `http://127.0.0.1:${apiPort}`;
@@ -7720,10 +8358,10 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
7720
8358
  let started = false;
7721
8359
  let exited = false;
7722
8360
  let exitCode = null;
7723
- const startedPromise = new Promise((resolve10) => {
8361
+ const startedPromise = new Promise((resolve11) => {
7724
8362
  const timeout = setTimeout(() => {
7725
8363
  if (!started && !exited) {
7726
- resolve10(false);
8364
+ resolve11(false);
7727
8365
  }
7728
8366
  }, startupTimeout);
7729
8367
  child.stdout?.on("data", (data) => {
@@ -7737,7 +8375,7 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
7737
8375
  if (!started && (output.includes("Ready") || output.includes("started") || output.includes("localhost"))) {
7738
8376
  started = true;
7739
8377
  clearTimeout(timeout);
7740
- resolve10(true);
8378
+ resolve11(true);
7741
8379
  }
7742
8380
  });
7743
8381
  child.stderr?.on("data", (data) => {
@@ -7749,14 +8387,14 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
7749
8387
  child.on("error", (err) => {
7750
8388
  if (!quiet) console.error(` \u274C Web UI spawn error: ${err.message}`);
7751
8389
  clearTimeout(timeout);
7752
- resolve10(false);
8390
+ resolve11(false);
7753
8391
  });
7754
8392
  child.on("exit", (code) => {
7755
8393
  exited = true;
7756
8394
  exitCode = code;
7757
8395
  if (!started) {
7758
8396
  clearTimeout(timeout);
7759
- resolve10(false);
8397
+ resolve11(false);
7760
8398
  }
7761
8399
  webUIProcess = null;
7762
8400
  });
@@ -7849,7 +8487,7 @@ async function startServer(options = {}) {
7849
8487
  if (options.workingDirectory) {
7850
8488
  config.resolvedWorkingDirectory = options.workingDirectory;
7851
8489
  }
7852
- if (!existsSync14(config.resolvedWorkingDirectory)) {
8490
+ if (!existsSync15(config.resolvedWorkingDirectory)) {
7853
8491
  mkdirSync5(config.resolvedWorkingDirectory, { recursive: true });
7854
8492
  if (!options.quiet) console.log(`\u{1F4C1} Created agent workspace: ${config.resolvedWorkingDirectory}`);
7855
8493
  }