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
package/dist/cli.js CHANGED
@@ -1872,7 +1872,7 @@ function formatError(error) {
1872
1872
  }
1873
1873
  }
1874
1874
  function sleep(ms) {
1875
- return new Promise((resolve11) => setTimeout(resolve11, ms));
1875
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
1876
1876
  }
1877
1877
  function isPathExcluded(relativePath, exclude) {
1878
1878
  return exclude.some((pattern) => {
@@ -1890,7 +1890,7 @@ function isPathExcluded(relativePath, exclude) {
1890
1890
  }
1891
1891
  async function walkDirectory(dir, include, exclude, baseDir) {
1892
1892
  const { readdirSync: readdirSync2 } = await import("fs");
1893
- const { join: join10, relative: relative9 } = await import("path");
1893
+ const { join: join10, relative: relative10 } = await import("path");
1894
1894
  const files = [];
1895
1895
  function walk(currentDir) {
1896
1896
  let entries;
@@ -1901,7 +1901,7 @@ async function walkDirectory(dir, include, exclude, baseDir) {
1901
1901
  }
1902
1902
  for (const entry of entries) {
1903
1903
  const fullPath = join10(currentDir, entry.name);
1904
- const relativePath = relative9(baseDir, fullPath);
1904
+ const relativePath = relative10(baseDir, fullPath);
1905
1905
  if (isPathExcluded(relativePath, exclude)) {
1906
1906
  continue;
1907
1907
  }
@@ -2267,13 +2267,13 @@ var semantic_search_exports = {};
2267
2267
  __export(semantic_search_exports, {
2268
2268
  createSemanticSearchTool: () => createSemanticSearchTool
2269
2269
  });
2270
- import { tool as tool7 } from "ai";
2271
- import { z as z8 } from "zod";
2272
- import { existsSync as existsSync10, readFileSync as readFileSync4 } from "fs";
2270
+ import { tool as tool8 } from "ai";
2271
+ import { z as z9 } from "zod";
2272
+ import { existsSync as existsSync11, readFileSync as readFileSync4 } from "fs";
2273
2273
  import { join as join4 } from "path";
2274
2274
  import { minimatch as minimatch3 } from "minimatch";
2275
2275
  function createSemanticSearchTool(options) {
2276
- return tool7({
2276
+ return tool8({
2277
2277
  description: `Search the codebase using semantic similarity. This tool finds code by understanding its meaning, not just matching text.
2278
2278
 
2279
2279
  Use this tool when:
@@ -2338,7 +2338,7 @@ Returns matching code snippets with file paths, line numbers, and relevance scor
2338
2338
  continue;
2339
2339
  }
2340
2340
  const fullPath = join4(options.workingDirectory, filePath);
2341
- if (!existsSync10(fullPath)) {
2341
+ if (!existsSync11(fullPath)) {
2342
2342
  continue;
2343
2343
  }
2344
2344
  let snippet = "";
@@ -2393,11 +2393,11 @@ var init_semantic_search = __esm({
2393
2393
  "use strict";
2394
2394
  init_semantic();
2395
2395
  init_config();
2396
- semanticSearchInputSchema = z8.object({
2397
- query: z8.string().describe("Natural language search query describing what you want to find"),
2398
- topK: z8.number().optional().default(10).describe("Number of results to return (default: 10, max: 50)"),
2399
- filePattern: z8.string().optional().describe('Filter results by file glob pattern (e.g., "*.ts", "src/**/*.py")'),
2400
- language: z8.string().optional().describe('Filter by programming language (e.g., "typescript", "python")')
2396
+ semanticSearchInputSchema = z9.object({
2397
+ query: z9.string().describe("Natural language search query describing what you want to find"),
2398
+ topK: z9.number().optional().default(10).describe("Number of results to return (default: 10, max: 50)"),
2399
+ filePattern: z9.string().optional().describe('Filter results by file glob pattern (e.g., "*.ts", "src/**/*.py")'),
2400
+ language: z9.string().optional().describe('Filter by programming language (e.g., "typescript", "python")')
2401
2401
  });
2402
2402
  }
2403
2403
  });
@@ -2415,27 +2415,27 @@ import { Hono as Hono5 } from "hono";
2415
2415
  import { serve } from "@hono/node-server";
2416
2416
  import { cors } from "hono/cors";
2417
2417
  import { logger } from "hono/logger";
2418
- import { existsSync as existsSync14, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "fs";
2419
- import { resolve as resolve9, dirname as dirname7, join as join8 } from "path";
2418
+ import { existsSync as existsSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "fs";
2419
+ import { resolve as resolve10, dirname as dirname7, join as join8 } from "path";
2420
2420
  import { spawn as spawn2 } from "child_process";
2421
2421
  import { createServer as createNetServer } from "net";
2422
- import { fileURLToPath as fileURLToPath3 } from "url";
2422
+ import { fileURLToPath as fileURLToPath4 } from "url";
2423
2423
 
2424
2424
  // src/server/routes/sessions.ts
2425
2425
  init_db();
2426
2426
  import { Hono } from "hono";
2427
2427
  import { zValidator } from "@hono/zod-validator";
2428
- import { z as z12 } from "zod";
2429
- import { existsSync as existsSync12, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2, readdirSync, statSync as statSync2, unlinkSync } from "fs";
2430
- import { readdir as readdir4 } from "fs/promises";
2431
- import { join as join5, basename as basename3, extname as extname6, relative as relative8 } from "path";
2428
+ import { z as z13 } from "zod";
2429
+ import { existsSync as existsSync13, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2, readdirSync, statSync as statSync2, unlinkSync } from "fs";
2430
+ import { readdir as readdir5 } from "fs/promises";
2431
+ import { join as join5, basename as basename4, extname as extname6, relative as relative9 } from "path";
2432
2432
  import { nanoid as nanoid4 } from "nanoid";
2433
2433
 
2434
2434
  // src/agent/index.ts
2435
2435
  import {
2436
2436
  streamText as streamText2,
2437
2437
  generateText as generateText3,
2438
- tool as tool10,
2438
+ tool as tool11,
2439
2439
  stepCountIs as stepCountIs2
2440
2440
  } from "ai";
2441
2441
 
@@ -2458,7 +2458,7 @@ var SUBAGENT_MODELS = {
2458
2458
  // src/agent/index.ts
2459
2459
  init_db();
2460
2460
  init_config();
2461
- import { z as z11 } from "zod";
2461
+ import { z as z12 } from "zod";
2462
2462
  import { nanoid as nanoid3 } from "nanoid";
2463
2463
 
2464
2464
  // src/tools/bash.ts
@@ -2745,8 +2745,8 @@ async function listSessionTerminals(sessionId, workingDirectory) {
2745
2745
  const terminalsDir = join2(workingDirectory, LOG_BASE_DIR, sessionId, "terminals");
2746
2746
  const terminals2 = [];
2747
2747
  try {
2748
- const { readdir: readdir5 } = await import("fs/promises");
2749
- const entries = await readdir5(terminalsDir, { withFileTypes: true });
2748
+ const { readdir: readdir6 } = await import("fs/promises");
2749
+ const entries = await readdir6(terminalsDir, { withFileTypes: true });
2750
2750
  for (const entry of entries) {
2751
2751
  if (entry.isDirectory()) {
2752
2752
  const meta = await getMeta(entry.name, workingDirectory, sessionId);
@@ -3549,7 +3549,11 @@ async function createClient(serverId, handle, root) {
3549
3549
  dynamicRegistration: true
3550
3550
  },
3551
3551
  documentSymbol: {
3552
- dynamicRegistration: true
3552
+ dynamicRegistration: true,
3553
+ hierarchicalDocumentSymbolSupport: true,
3554
+ symbolKind: {
3555
+ 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]
3556
+ }
3553
3557
  }
3554
3558
  },
3555
3559
  workspace: {
@@ -3646,7 +3650,7 @@ async function createClient(serverId, handle, root) {
3646
3650
  },
3647
3651
  async waitForDiagnostics(filePath, timeoutMs = 5e3) {
3648
3652
  const normalized = normalizePath(filePath);
3649
- return new Promise((resolve11) => {
3653
+ return new Promise((resolve12) => {
3650
3654
  const startTime = Date.now();
3651
3655
  let debounceTimer;
3652
3656
  let resolved = false;
@@ -3665,7 +3669,7 @@ async function createClient(serverId, handle, root) {
3665
3669
  if (resolved) return;
3666
3670
  resolved = true;
3667
3671
  cleanup();
3668
- resolve11(diagnostics.get(normalized) || []);
3672
+ resolve12(diagnostics.get(normalized) || []);
3669
3673
  };
3670
3674
  const onDiagnostic = () => {
3671
3675
  if (debounceTimer) clearTimeout(debounceTimer);
@@ -3691,6 +3695,100 @@ async function createClient(serverId, handle, root) {
3691
3695
  getAllDiagnostics() {
3692
3696
  return new Map(diagnostics);
3693
3697
  },
3698
+ async getDefinition(filePath, line, character) {
3699
+ const normalized = normalizePath(filePath);
3700
+ if (!fileVersions.has(normalized)) {
3701
+ await client.notifyOpen(normalized);
3702
+ }
3703
+ try {
3704
+ const result = await connection.sendRequest("textDocument/definition", {
3705
+ textDocument: { uri: pathToFileURL(normalized).href },
3706
+ position: { line, character }
3707
+ });
3708
+ if (!result) return [];
3709
+ const items = Array.isArray(result) ? result : [result];
3710
+ return items.map((r) => ({
3711
+ uri: r.targetUri || r.uri,
3712
+ range: r.targetRange || r.range
3713
+ }));
3714
+ } catch (error) {
3715
+ console.error("[lsp] Error getting definition:", error);
3716
+ return [];
3717
+ }
3718
+ },
3719
+ async getReferences(filePath, line, character, includeDeclaration = false) {
3720
+ const normalized = normalizePath(filePath);
3721
+ if (!fileVersions.has(normalized)) {
3722
+ await client.notifyOpen(normalized);
3723
+ }
3724
+ try {
3725
+ const result = await connection.sendRequest("textDocument/references", {
3726
+ textDocument: { uri: pathToFileURL(normalized).href },
3727
+ position: { line, character },
3728
+ context: { includeDeclaration }
3729
+ });
3730
+ return result || [];
3731
+ } catch (error) {
3732
+ console.error("[lsp] Error getting references:", error);
3733
+ return [];
3734
+ }
3735
+ },
3736
+ async getHover(filePath, line, character) {
3737
+ const normalized = normalizePath(filePath);
3738
+ if (!fileVersions.has(normalized)) {
3739
+ await client.notifyOpen(normalized);
3740
+ }
3741
+ try {
3742
+ const result = await connection.sendRequest("textDocument/hover", {
3743
+ textDocument: { uri: pathToFileURL(normalized).href },
3744
+ position: { line, character }
3745
+ });
3746
+ if (!result || !result.contents) return null;
3747
+ if (typeof result.contents === "string") return result.contents;
3748
+ if (result.contents.value) return result.contents.value;
3749
+ if (Array.isArray(result.contents)) {
3750
+ return result.contents.map((c) => typeof c === "string" ? c : c.value).join("\n");
3751
+ }
3752
+ return null;
3753
+ } catch (error) {
3754
+ console.error("[lsp] Error getting hover:", error);
3755
+ return null;
3756
+ }
3757
+ },
3758
+ async getDocumentSymbols(filePath) {
3759
+ const normalized = normalizePath(filePath);
3760
+ if (!fileVersions.has(normalized)) {
3761
+ await client.notifyOpen(normalized);
3762
+ }
3763
+ try {
3764
+ const result = await connection.sendRequest("textDocument/documentSymbol", {
3765
+ textDocument: { uri: pathToFileURL(normalized).href }
3766
+ });
3767
+ if (!result || result.length === 0) return [];
3768
+ if (result[0].range) {
3769
+ return result;
3770
+ }
3771
+ return result.map((si) => ({
3772
+ name: si.name,
3773
+ kind: si.kind,
3774
+ range: si.location?.range ?? { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
3775
+ selectionRange: si.location?.range ?? { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
3776
+ detail: si.containerName
3777
+ }));
3778
+ } catch (error) {
3779
+ console.error("[lsp] Error getting document symbols:", error);
3780
+ return [];
3781
+ }
3782
+ },
3783
+ async findWorkspaceSymbols(query) {
3784
+ try {
3785
+ const result = await connection.sendRequest("workspace/symbol", { query });
3786
+ return result || [];
3787
+ } catch (error) {
3788
+ console.error("[lsp] Error finding workspace symbols:", error);
3789
+ return [];
3790
+ }
3791
+ },
3694
3792
  async shutdown() {
3695
3793
  try {
3696
3794
  await connection.sendRequest("shutdown");
@@ -3813,6 +3911,24 @@ async function getAllDiagnostics() {
3813
3911
  }
3814
3912
  return results;
3815
3913
  }
3914
+ async function getReferences(filePath, line, character, includeDeclaration = false) {
3915
+ const normalized = normalizePath(filePath);
3916
+ const client = await getClientForFile(normalized);
3917
+ if (!client) return [];
3918
+ return client.getReferences(normalized, line, character, includeDeclaration);
3919
+ }
3920
+ async function getHover(filePath, line, character) {
3921
+ const normalized = normalizePath(filePath);
3922
+ const client = await getClientForFile(normalized);
3923
+ if (!client) return null;
3924
+ return client.getHover(normalized, line, character);
3925
+ }
3926
+ async function getDocumentSymbols(filePath) {
3927
+ const normalized = normalizePath(filePath);
3928
+ const client = await getClientForFile(normalized);
3929
+ if (!client) return [];
3930
+ return client.getDocumentSymbols(normalized);
3931
+ }
3816
3932
  async function formatDiagnosticsOutput(filePath, options = {}) {
3817
3933
  const diagnostics = await getDiagnostics(filePath);
3818
3934
  return formatDiagnosticsForAgent(filePath, diagnostics, options);
@@ -3908,7 +4024,7 @@ Working directory: ${options.workingDirectory}`,
3908
4024
  isChunked: true
3909
4025
  });
3910
4026
  if (chunkCount > 1) {
3911
- await new Promise((resolve11) => setTimeout(resolve11, 0));
4027
+ await new Promise((resolve12) => setTimeout(resolve12, 0));
3912
4028
  }
3913
4029
  }
3914
4030
  }
@@ -4436,8 +4552,8 @@ ${file.relativePath}:`);
4436
4552
  }
4437
4553
 
4438
4554
  // src/tools/search.ts
4439
- import { tool as tool9 } from "ai";
4440
- import { z as z10 } from "zod";
4555
+ import { tool as tool10 } from "ai";
4556
+ import { z as z11 } from "zod";
4441
4557
 
4442
4558
  // src/agent/subagent.ts
4443
4559
  import {
@@ -4609,8 +4725,8 @@ var Subagent = class {
4609
4725
  if (eventQueue.length > 0) {
4610
4726
  yield eventQueue.shift();
4611
4727
  } else if (!done) {
4612
- const event = await new Promise((resolve11) => {
4613
- resolveNext = resolve11;
4728
+ const event = await new Promise((resolve12) => {
4729
+ resolveNext = resolve12;
4614
4730
  });
4615
4731
  if (event) {
4616
4732
  yield event;
@@ -4622,14 +4738,466 @@ var Subagent = class {
4622
4738
  };
4623
4739
 
4624
4740
  // src/agent/subagents/search.ts
4625
- import { tool as tool8 } from "ai";
4626
- import { z as z9 } from "zod";
4741
+ import { tool as tool9 } from "ai";
4742
+ import { z as z10 } from "zod";
4627
4743
  import { exec as exec4 } from "child_process";
4628
4744
  import { promisify as promisify4 } from "util";
4629
- import { readFile as readFile7, stat as stat3, readdir as readdir3 } from "fs/promises";
4630
- import { resolve as resolve8, relative as relative7, isAbsolute as isAbsolute4 } from "path";
4631
- import { existsSync as existsSync11 } from "fs";
4745
+ import { readFile as readFile8, stat as stat3, readdir as readdir4 } from "fs/promises";
4746
+ import { resolve as resolve9, relative as relative8, isAbsolute as isAbsolute5 } from "path";
4747
+ import { existsSync as existsSync12 } from "fs";
4632
4748
  init_semantic();
4749
+
4750
+ // src/tools/code-graph.ts
4751
+ import { tool as tool7 } from "ai";
4752
+ import { z as z8 } from "zod";
4753
+ import { resolve as resolve8, relative as relative7, isAbsolute as isAbsolute4, basename as basename3 } from "path";
4754
+ import { readFile as readFile7, readdir as readdir3 } from "fs/promises";
4755
+ import { existsSync as existsSync10 } from "fs";
4756
+ import { fileURLToPath as fileURLToPath2 } from "url";
4757
+ import { execFileSync } from "child_process";
4758
+ var codeGraphInputSchema = z8.object({
4759
+ symbol: z8.string().describe(
4760
+ "The symbol name to inspect (function, component, class, type, variable, etc.)"
4761
+ ),
4762
+ filePath: z8.string().optional().describe(
4763
+ "File path where the symbol is defined. If omitted, searches the workspace via grep."
4764
+ ),
4765
+ depth: z8.number().optional().default(2).describe(
4766
+ "How many levels of references to traverse upward (default: 2, max: 3). Level 1 = direct usages, level 2 = usages of those usages."
4767
+ )
4768
+ });
4769
+ function isPageFile(filePath) {
4770
+ const normalized = filePath.replace(/\\/g, "/");
4771
+ if (/\/app\/(.+\/)?(page|layout|loading|error|not-found)\.(tsx?|jsx?)$/.test(normalized)) return true;
4772
+ if (/\/pages\/(?!_|api\/).+\.(tsx?|jsx?)$/.test(normalized)) return true;
4773
+ return false;
4774
+ }
4775
+ function extractRoutePath(filePath, workingDirectory) {
4776
+ const rel = relative7(workingDirectory, filePath).replace(/\\/g, "/");
4777
+ const appMatch = rel.match(/(?:src\/)?app((?:\/[^/]+)*?)\/(?:page|layout|loading|error|not-found)\.\w+$/);
4778
+ if (appMatch) return appMatch[1] || "/";
4779
+ const pagesMatch = rel.match(/(?:src\/)?pages(\/.*?)(?:\/index)?\.\w+$/);
4780
+ if (pagesMatch) return pagesMatch[1] || "/";
4781
+ return void 0;
4782
+ }
4783
+ function symbolKindName(kind) {
4784
+ const names = {
4785
+ [5 /* Class */]: "class",
4786
+ [12 /* Function */]: "function",
4787
+ [6 /* Method */]: "method",
4788
+ [7 /* Property */]: "property",
4789
+ [13 /* Variable */]: "variable",
4790
+ [11 /* Interface */]: "interface",
4791
+ [10 /* Enum */]: "enum",
4792
+ [14 /* Constant */]: "constant",
4793
+ [9 /* Constructor */]: "constructor",
4794
+ [2 /* Module */]: "module",
4795
+ [3 /* Namespace */]: "namespace",
4796
+ [26 /* TypeParameter */]: "type_param",
4797
+ [8 /* Field */]: "field",
4798
+ [22 /* EnumMember */]: "enum_member",
4799
+ [19 /* Object */]: "object"
4800
+ };
4801
+ return names[kind] || "symbol";
4802
+ }
4803
+ function findContainingSymbol(symbols, line, character) {
4804
+ for (const sym of symbols) {
4805
+ if (!sym.range) continue;
4806
+ const { start, end } = sym.range;
4807
+ const afterStart = line > start.line || line === start.line && character >= start.character;
4808
+ const beforeEnd = line < end.line || line === end.line && character < end.character;
4809
+ if (afterStart && beforeEnd) {
4810
+ if (sym.children?.length) {
4811
+ const child = findContainingSymbol(sym.children, line, character);
4812
+ if (child) return child;
4813
+ }
4814
+ return sym;
4815
+ }
4816
+ }
4817
+ return null;
4818
+ }
4819
+ function findSymbolByName(symbols, name) {
4820
+ for (const sym of symbols) {
4821
+ if (sym.name === name && sym.selectionRange) return sym;
4822
+ if (sym.children) {
4823
+ const found = findSymbolByName(sym.children, name);
4824
+ if (found) return found;
4825
+ }
4826
+ }
4827
+ return null;
4828
+ }
4829
+ function cleanHoverText(text) {
4830
+ return text.replace(/```\w*\n?/g, "").replace(/\n```/g, "").trim();
4831
+ }
4832
+ async function grepForSymbol(symbol, workingDirectory) {
4833
+ const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4834
+ const rgPatterns = [
4835
+ `(export\\s+)?(default\\s+)?(function|const|let|var|class|interface|type|enum)\\s+${escaped}\\b`,
4836
+ `(export\\s+)?(default\\s+)?\\b${escaped}\\s*[=:(]`
4837
+ ];
4838
+ for (const pattern of rgPatterns) {
4839
+ try {
4840
+ const result = execFileSync("rg", [
4841
+ "-n",
4842
+ "--no-heading",
4843
+ "-e",
4844
+ pattern,
4845
+ "--glob",
4846
+ "*.{ts,tsx,js,jsx}",
4847
+ "-m",
4848
+ "5"
4849
+ ], {
4850
+ cwd: workingDirectory,
4851
+ encoding: "utf-8",
4852
+ timeout: 5e3,
4853
+ stdio: ["pipe", "pipe", "pipe"]
4854
+ }).trim();
4855
+ if (result) {
4856
+ const firstLine = result.split("\n")[0];
4857
+ const match = firstLine.match(/^(.+?):(\d+):(.*)/);
4858
+ if (match) {
4859
+ const col = match[3].indexOf(symbol);
4860
+ return {
4861
+ filePath: resolve8(workingDirectory, match[1]),
4862
+ line: parseInt(match[2]) - 1,
4863
+ char: col >= 0 ? col : 0
4864
+ };
4865
+ }
4866
+ }
4867
+ } catch {
4868
+ }
4869
+ }
4870
+ const defPattern = new RegExp(
4871
+ `(export|function|const|let|var|class|interface|type|enum)\\s+.*\\b${escaped}\\b`
4872
+ );
4873
+ const SUPPORTED_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
4874
+ const IGNORED_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", "coverage"]);
4875
+ async function search(dir, maxFiles) {
4876
+ if (maxFiles <= 0) return null;
4877
+ let remaining = maxFiles;
4878
+ try {
4879
+ const entries = await readdir3(dir, { withFileTypes: true });
4880
+ for (const entry of entries) {
4881
+ if (remaining <= 0) return null;
4882
+ const fullPath = resolve8(dir, entry.name);
4883
+ if (entry.isDirectory()) {
4884
+ if (IGNORED_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
4885
+ const found = await search(fullPath, remaining);
4886
+ if (found) return found;
4887
+ remaining -= 10;
4888
+ } else if (entry.isFile()) {
4889
+ const ext = entry.name.substring(entry.name.lastIndexOf("."));
4890
+ if (!SUPPORTED_EXTS.has(ext)) continue;
4891
+ remaining--;
4892
+ const content = await readFile7(fullPath, "utf-8");
4893
+ const lines = content.split("\n");
4894
+ for (let i = 0; i < lines.length; i++) {
4895
+ if (defPattern.test(lines[i])) {
4896
+ const col = lines[i].indexOf(symbol);
4897
+ if (col >= 0) {
4898
+ return { filePath: fullPath, line: i, char: col };
4899
+ }
4900
+ }
4901
+ }
4902
+ }
4903
+ }
4904
+ } catch {
4905
+ }
4906
+ return null;
4907
+ }
4908
+ return search(workingDirectory, 200);
4909
+ }
4910
+ var MAX_REF_FILES = 15;
4911
+ var MAX_LEVEL2_PARENTS = 8;
4912
+ var MAX_LEVEL2_SYMBOLS_PER_PARENT = 3;
4913
+ function createCodeGraphTool(options) {
4914
+ return tool7({
4915
+ description: `Inspect a symbol's type information and usage graph using the TypeScript language server.
4916
+
4917
+ Given a symbol name (function, component, class, type, etc.), this tool will:
4918
+ 1. Find its definition and full type signature (parameters, return type)
4919
+ 2. Find all references \u2014 what components/functions/files use this symbol
4920
+ 3. Identify which pages/routes contain it in their component tree
4921
+ 4. Show the file's symbol structure for surrounding context
4922
+
4923
+ Use this to understand:
4924
+ - Component hierarchies (what renders what, which pages are affected)
4925
+ - Type signatures and parameter/return types before making changes
4926
+ - How deeply a symbol is used across the codebase
4927
+ - What will break if you change something
4928
+
4929
+ Supports TypeScript, JavaScript, TSX, JSX files.
4930
+ Working directory: ${options.workingDirectory}`,
4931
+ inputSchema: codeGraphInputSchema,
4932
+ execute: async ({ symbol, filePath, depth }) => {
4933
+ const maxDepth = Math.min(depth ?? 2, 3);
4934
+ try {
4935
+ let defFilePath;
4936
+ let defLine = 0;
4937
+ let defChar = 0;
4938
+ let defSymbol = null;
4939
+ if (filePath) {
4940
+ const absPath = isAbsolute4(filePath) ? filePath : resolve8(options.workingDirectory, filePath);
4941
+ if (!existsSync10(absPath)) {
4942
+ return { success: false, error: `File not found: ${filePath}` };
4943
+ }
4944
+ if (!isSupported(absPath)) {
4945
+ return { success: false, error: `File type not supported. Supports: ${getSupportedExtensions().join(", ")}` };
4946
+ }
4947
+ await touchFile(absPath, true);
4948
+ const symbols = await getDocumentSymbols(absPath);
4949
+ defSymbol = findSymbolByName(symbols, symbol);
4950
+ if (defSymbol) {
4951
+ defFilePath = absPath;
4952
+ defLine = defSymbol.selectionRange.start.line;
4953
+ defChar = defSymbol.selectionRange.start.character;
4954
+ } else {
4955
+ const content = await readFile7(absPath, "utf-8");
4956
+ const lines2 = content.split("\n");
4957
+ const defPattern = new RegExp(
4958
+ `(export|function|const|let|var|class|interface|type|enum)\\s+.*\\b${symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`
4959
+ );
4960
+ for (let i = 0; i < lines2.length; i++) {
4961
+ if (defPattern.test(lines2[i])) {
4962
+ const col = lines2[i].indexOf(symbol);
4963
+ if (col !== -1) {
4964
+ defFilePath = absPath;
4965
+ defLine = i;
4966
+ defChar = col;
4967
+ break;
4968
+ }
4969
+ }
4970
+ }
4971
+ if (!defFilePath) {
4972
+ for (let i = 0; i < lines2.length; i++) {
4973
+ const col = lines2[i].indexOf(symbol);
4974
+ if (col !== -1) {
4975
+ defFilePath = absPath;
4976
+ defLine = i;
4977
+ defChar = col;
4978
+ break;
4979
+ }
4980
+ }
4981
+ }
4982
+ }
4983
+ } else {
4984
+ const found = await grepForSymbol(symbol, options.workingDirectory);
4985
+ if (found) {
4986
+ defFilePath = found.filePath;
4987
+ defLine = found.line;
4988
+ defChar = found.char;
4989
+ }
4990
+ }
4991
+ if (!defFilePath) {
4992
+ return {
4993
+ success: false,
4994
+ error: `Could not find symbol "${symbol}" in the codebase. Try providing a filePath.`
4995
+ };
4996
+ }
4997
+ await touchFile(defFilePath, true);
4998
+ const rawHover = await getHover(defFilePath, defLine, defChar);
4999
+ const typeInfo = rawHover ? cleanHoverText(rawHover) : null;
5000
+ const fileSymbols = await getDocumentSymbols(defFilePath);
5001
+ if (!defSymbol && fileSymbols.length > 0) {
5002
+ defSymbol = findSymbolByName(fileSymbols, symbol);
5003
+ }
5004
+ const references = await getReferences(defFilePath, defLine, defChar, false);
5005
+ const refsByFile = /* @__PURE__ */ new Map();
5006
+ for (const ref of references) {
5007
+ const refPath = fileURLToPath2(ref.uri);
5008
+ if (!refsByFile.has(refPath)) {
5009
+ refsByFile.set(refPath, []);
5010
+ }
5011
+ refsByFile.get(refPath).push(ref);
5012
+ }
5013
+ const refFileInfos = [];
5014
+ let processed = 0;
5015
+ for (const [refPath, locs] of refsByFile) {
5016
+ if (processed >= MAX_REF_FILES) break;
5017
+ if (refPath === defFilePath) continue;
5018
+ processed++;
5019
+ const relPath = relative7(options.workingDirectory, refPath);
5020
+ const pageFile = isPageFile(refPath);
5021
+ const routePath = pageFile ? extractRoutePath(refPath, options.workingDirectory) : void 0;
5022
+ await touchFile(refPath, false);
5023
+ const refFileSymbols = await getDocumentSymbols(refPath);
5024
+ const seen = /* @__PURE__ */ new Map();
5025
+ for (const loc of locs) {
5026
+ const container = findContainingSymbol(
5027
+ refFileSymbols,
5028
+ loc.range.start.line,
5029
+ loc.range.start.character
5030
+ );
5031
+ if (container && !seen.has(container.name)) {
5032
+ let containerHover = null;
5033
+ try {
5034
+ const raw = await getHover(
5035
+ refPath,
5036
+ container.selectionRange.start.line,
5037
+ container.selectionRange.start.character
5038
+ );
5039
+ if (raw) containerHover = cleanHoverText(raw).split("\n")[0];
5040
+ } catch {
5041
+ }
5042
+ seen.set(container.name, {
5043
+ name: container.name,
5044
+ kind: symbolKindName(container.kind),
5045
+ line: container.selectionRange.start.line + 1,
5046
+ char: container.selectionRange.start.character,
5047
+ typeInfo: containerHover || void 0
5048
+ });
5049
+ }
5050
+ }
5051
+ refFileInfos.push({
5052
+ filePath: refPath,
5053
+ relativePath: relPath,
5054
+ isPage: pageFile,
5055
+ routePath,
5056
+ containingSymbols: Array.from(seen.values())
5057
+ });
5058
+ }
5059
+ const level2Refs = [];
5060
+ if (maxDepth >= 2) {
5061
+ for (const refFile of refFileInfos.slice(0, MAX_LEVEL2_PARENTS)) {
5062
+ for (const sym of refFile.containingSymbols.slice(0, MAX_LEVEL2_SYMBOLS_PER_PARENT)) {
5063
+ try {
5064
+ const symLineIdx = sym.line - 1;
5065
+ const symChar = sym.char;
5066
+ const l2Locations = await getReferences(
5067
+ refFile.filePath,
5068
+ symLineIdx,
5069
+ symChar,
5070
+ false
5071
+ );
5072
+ const l2Nodes = [];
5073
+ const seenPaths = /* @__PURE__ */ new Set();
5074
+ for (const loc of l2Locations.slice(0, 10)) {
5075
+ const l2Path = fileURLToPath2(loc.uri);
5076
+ if (l2Path === refFile.filePath || l2Path === defFilePath) continue;
5077
+ if (seenPaths.has(l2Path)) continue;
5078
+ seenPaths.add(l2Path);
5079
+ const l2Rel = relative7(options.workingDirectory, l2Path);
5080
+ const l2Page = isPageFile(l2Path);
5081
+ const l2Route = l2Page ? extractRoutePath(l2Path, options.workingDirectory) : void 0;
5082
+ let containerName;
5083
+ try {
5084
+ await touchFile(l2Path, false);
5085
+ const l2Symbols = await getDocumentSymbols(l2Path);
5086
+ const container = findContainingSymbol(l2Symbols, loc.range.start.line, loc.range.start.character);
5087
+ if (container) containerName = container.name;
5088
+ } catch {
5089
+ }
5090
+ l2Nodes.push({
5091
+ relativePath: l2Rel,
5092
+ isPage: l2Page,
5093
+ routePath: l2Route,
5094
+ containingSymbol: containerName
5095
+ });
5096
+ }
5097
+ if (l2Nodes.length > 0) {
5098
+ level2Refs.push({
5099
+ parentSymbol: sym.name,
5100
+ parentFile: refFile.relativePath,
5101
+ refs: l2Nodes
5102
+ });
5103
+ }
5104
+ } catch {
5105
+ }
5106
+ }
5107
+ }
5108
+ }
5109
+ const relDefPath = relative7(options.workingDirectory, defFilePath);
5110
+ const lines = [];
5111
+ lines.push(`=== ${symbol} ===`);
5112
+ lines.push(`File: ${relDefPath}:${defLine + 1}`);
5113
+ if (defSymbol) lines.push(`Kind: ${symbolKindName(defSymbol.kind)}`);
5114
+ if (typeInfo) lines.push(`Type: ${typeInfo}`);
5115
+ const externalRefCount = references.filter((r) => fileURLToPath2(r.uri) !== defFilePath).length;
5116
+ const externalFileCount = refsByFile.size - (refsByFile.has(defFilePath) ? 1 : 0);
5117
+ if (refFileInfos.length > 0) {
5118
+ lines.push("");
5119
+ lines.push(`=== Referenced by (${externalRefCount} usages across ${externalFileCount} files) ===`);
5120
+ const pages = refFileInfos.filter((r) => r.isPage);
5121
+ const nonPages = refFileInfos.filter((r) => !r.isPage);
5122
+ if (pages.length > 0) {
5123
+ lines.push("");
5124
+ lines.push("Pages/Routes:");
5125
+ for (const page of pages) {
5126
+ lines.push(` ${page.relativePath}${page.routePath ? ` \u2192 ${page.routePath}` : ""}`);
5127
+ for (const s of page.containingSymbols) {
5128
+ lines.push(` \u2514\u2500\u2500 ${s.name} (${s.kind}:${s.line})${s.typeInfo ? ` \u2014 ${s.typeInfo}` : ""}`);
5129
+ }
5130
+ }
5131
+ }
5132
+ if (nonPages.length > 0) {
5133
+ lines.push("");
5134
+ lines.push("Components/Functions:");
5135
+ for (const ref of nonPages) {
5136
+ lines.push(` ${ref.relativePath}`);
5137
+ for (const s of ref.containingSymbols) {
5138
+ const typePart = s.typeInfo && s.typeInfo.length < 120 ? ` \u2014 ${s.typeInfo}` : "";
5139
+ lines.push(` \u2514\u2500\u2500 ${s.name} (${s.kind}:${s.line})${typePart}`);
5140
+ }
5141
+ }
5142
+ }
5143
+ } else {
5144
+ lines.push("");
5145
+ lines.push("No external references found (symbol may be unused or only used within the same file).");
5146
+ }
5147
+ if (level2Refs.length > 0) {
5148
+ lines.push("");
5149
+ lines.push("=== Extended tree (level 2) ===");
5150
+ for (const l2 of level2Refs) {
5151
+ lines.push("");
5152
+ lines.push(`${l2.parentSymbol} (${l2.parentFile}) is used by:`);
5153
+ for (const ref of l2.refs) {
5154
+ const tag = ref.isPage ? " [PAGE]" : "";
5155
+ const route = ref.routePath ? ` \u2192 ${ref.routePath}` : "";
5156
+ const container = ref.containingSymbol ? ` in ${ref.containingSymbol}` : "";
5157
+ lines.push(` \u2514\u2500\u2500 ${ref.relativePath}${tag}${route}${container}`);
5158
+ }
5159
+ }
5160
+ }
5161
+ if (fileSymbols.length > 0) {
5162
+ lines.push("");
5163
+ lines.push(`=== File structure (${basename3(defFilePath)}) ===`);
5164
+ for (const sym of fileSymbols) {
5165
+ const marker = sym.name === symbol ? " \u2190 target" : "";
5166
+ lines.push(` ${sym.name} (${symbolKindName(sym.kind)}:${sym.selectionRange.start.line + 1})${marker}`);
5167
+ if (sym.children) {
5168
+ for (const child of sym.children.slice(0, 10)) {
5169
+ lines.push(` \u2514\u2500\u2500 ${child.name} (${symbolKindName(child.kind)}:${child.selectionRange.start.line + 1})`);
5170
+ }
5171
+ if (sym.children.length > 10) {
5172
+ lines.push(` ... and ${sym.children.length - 10} more`);
5173
+ }
5174
+ }
5175
+ }
5176
+ }
5177
+ const formattedResult = lines.join("\n");
5178
+ return {
5179
+ success: true,
5180
+ symbol,
5181
+ filePath: relDefPath,
5182
+ line: defLine + 1,
5183
+ kind: defSymbol ? symbolKindName(defSymbol.kind) : void 0,
5184
+ typeInfo: typeInfo || void 0,
5185
+ referenceCount: externalRefCount,
5186
+ referenceFiles: externalFileCount,
5187
+ pages: refFileInfos.filter((r) => r.isPage).map((r) => ({ path: r.relativePath, route: r.routePath })),
5188
+ formattedResult
5189
+ };
5190
+ } catch (error) {
5191
+ return {
5192
+ success: false,
5193
+ error: error instanceof Error ? error.message : String(error)
5194
+ };
5195
+ }
5196
+ }
5197
+ });
5198
+ }
5199
+
5200
+ // src/agent/subagents/search.ts
4633
5201
  var execAsync4 = promisify4(exec4);
4634
5202
  var MAX_OUTPUT_CHARS4 = 1e4;
4635
5203
  var MAX_FILE_SIZE3 = 1 * 1024 * 1024;
@@ -4659,17 +5227,20 @@ ${contextBlock}
4659
5227
  - **glob**: Find files matching a name pattern. Best for file discovery.
4660
5228
  - **read_file**: Read contents of a specific file. Use to examine code found in searches.
4661
5229
  - **list_dir**: List directory contents. Use to understand project structure.
5230
+ - **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.
4662
5231
 
4663
5232
  ## Search Strategy
4664
5233
 
4665
5234
  1. **Start with semantic_search** if available - it finds code by meaning, which is the fastest way to explore
4666
5235
  2. **Use grep** for exact symbol/string matches (function names, class names, imports)
4667
- 3. **Use glob** for file discovery by name patterns
4668
- 4. **Read key files** to get actual code content and understand context
4669
- 5. **Run searches in PARALLEL** - make multiple tool calls at once to cover different angles simultaneously. This is critical for speed.
5236
+ 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.
5237
+ 4. **Use glob** for file discovery by name patterns
5238
+ 5. **Read key files** to get actual code content and understand context
5239
+ 6. **Run searches in PARALLEL** - make multiple tool calls at once to cover different angles simultaneously. This is critical for speed.
4670
5240
 
4671
5241
  ### Tool Selection Guide
4672
5242
  - Know the exact name? Use **grep** (e.g. \`getUserById\`, \`class AuthService\`)
5243
+ - Need type info, references, or impact analysis? Use **code_graph** (e.g. \`code_graph({ symbol: "UserCard" })\`)
4673
5244
  - Exploring a concept? Use **semantic_search** (e.g. "how does authentication work")
4674
5245
  - Looking for files? Use **glob** (e.g. \`**/*.config.ts\`, \`**/auth/**\`)
4675
5246
  - Need file content? Use **read_file** with optional line ranges for large files
@@ -4706,17 +5277,17 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4706
5277
  async getToolsAsync(options) {
4707
5278
  const workingDirectory = options.workingDirectory;
4708
5279
  const tools = {
4709
- grep: tool8({
5280
+ grep: tool9({
4710
5281
  description: "Search for patterns in files using ripgrep. Returns matching lines with file paths and line numbers.",
4711
- inputSchema: z9.object({
4712
- pattern: z9.string().describe("The regex pattern to search for"),
4713
- path: z9.string().optional().describe("Subdirectory or file to search in (relative to working directory)"),
4714
- fileType: z9.string().optional().describe('File type to filter (e.g., "ts", "js", "py")'),
4715
- maxResults: z9.number().optional().default(50).describe("Maximum number of results to return")
5282
+ inputSchema: z10.object({
5283
+ pattern: z10.string().describe("The regex pattern to search for"),
5284
+ path: z10.string().optional().describe("Subdirectory or file to search in (relative to working directory)"),
5285
+ fileType: z10.string().optional().describe('File type to filter (e.g., "ts", "js", "py")'),
5286
+ maxResults: z10.number().optional().default(50).describe("Maximum number of results to return")
4716
5287
  }),
4717
5288
  execute: async ({ pattern, path, fileType, maxResults }) => {
4718
5289
  try {
4719
- const searchPath = path ? resolve8(workingDirectory, path) : workingDirectory;
5290
+ const searchPath = path ? resolve9(workingDirectory, path) : workingDirectory;
4720
5291
  let args = ["rg", "--line-number", "--no-heading"];
4721
5292
  if (fileType) {
4722
5293
  args.push("--type", fileType);
@@ -4753,11 +5324,11 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4753
5324
  }
4754
5325
  }
4755
5326
  }),
4756
- glob: tool8({
5327
+ glob: tool9({
4757
5328
  description: "Find files matching a glob pattern. Returns list of matching file paths.",
4758
- inputSchema: z9.object({
4759
- pattern: z9.string().describe('Glob pattern (e.g., "**/*.ts", "src/**/*.tsx", "*.json")'),
4760
- maxResults: z9.number().optional().default(100).describe("Maximum number of files to return")
5329
+ inputSchema: z10.object({
5330
+ pattern: z10.string().describe('Glob pattern (e.g., "**/*.ts", "src/**/*.tsx", "*.json")'),
5331
+ maxResults: z10.number().optional().default(100).describe("Maximum number of files to return")
4761
5332
  }),
4762
5333
  execute: async ({ pattern, maxResults }) => {
4763
5334
  try {
@@ -4784,17 +5355,17 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4784
5355
  }
4785
5356
  }
4786
5357
  }),
4787
- read_file: tool8({
5358
+ read_file: tool9({
4788
5359
  description: "Read the contents of a file. Use this to examine specific files found in search.",
4789
- inputSchema: z9.object({
4790
- path: z9.string().describe("Path to the file (relative to working directory or absolute)"),
4791
- startLine: z9.number().optional().describe("Start reading from this line (1-indexed)"),
4792
- endLine: z9.number().optional().describe("Stop reading at this line (1-indexed, inclusive)")
5360
+ inputSchema: z10.object({
5361
+ path: z10.string().describe("Path to the file (relative to working directory or absolute)"),
5362
+ startLine: z10.number().optional().describe("Start reading from this line (1-indexed)"),
5363
+ endLine: z10.number().optional().describe("Stop reading at this line (1-indexed, inclusive)")
4793
5364
  }),
4794
5365
  execute: async ({ path, startLine, endLine }) => {
4795
5366
  try {
4796
- const absolutePath = isAbsolute4(path) ? path : resolve8(workingDirectory, path);
4797
- if (!existsSync11(absolutePath)) {
5367
+ const absolutePath = isAbsolute5(path) ? path : resolve9(workingDirectory, path);
5368
+ if (!existsSync12(absolutePath)) {
4798
5369
  return {
4799
5370
  success: false,
4800
5371
  error: `File not found: ${path}`
@@ -4807,7 +5378,7 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4807
5378
  error: `File too large (${(stats.size / 1024 / 1024).toFixed(2)}MB). Use startLine/endLine to read portions.`
4808
5379
  };
4809
5380
  }
4810
- let content = await readFile7(absolutePath, "utf-8");
5381
+ let content = await readFile8(absolutePath, "utf-8");
4811
5382
  if (startLine !== void 0 || endLine !== void 0) {
4812
5383
  const lines = content.split("\n");
4813
5384
  const start = (startLine ?? 1) - 1;
@@ -4816,7 +5387,7 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4816
5387
  }
4817
5388
  return {
4818
5389
  success: true,
4819
- path: relative7(workingDirectory, absolutePath),
5390
+ path: relative8(workingDirectory, absolutePath),
4820
5391
  content: truncateOutput(content, MAX_OUTPUT_CHARS4),
4821
5392
  lineCount: content.split("\n").length
4822
5393
  };
@@ -4828,17 +5399,17 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4828
5399
  }
4829
5400
  }
4830
5401
  }),
4831
- list_dir: tool8({
5402
+ list_dir: tool9({
4832
5403
  description: "List contents of a directory. Shows files and subdirectories.",
4833
- inputSchema: z9.object({
4834
- path: z9.string().optional().default(".").describe("Directory path (relative to working directory)"),
4835
- recursive: z9.boolean().optional().default(false).describe("List recursively (be careful with large directories)"),
4836
- maxDepth: z9.number().optional().default(2).describe("Maximum depth for recursive listing")
5404
+ inputSchema: z10.object({
5405
+ path: z10.string().optional().default(".").describe("Directory path (relative to working directory)"),
5406
+ recursive: z10.boolean().optional().default(false).describe("List recursively (be careful with large directories)"),
5407
+ maxDepth: z10.number().optional().default(2).describe("Maximum depth for recursive listing")
4837
5408
  }),
4838
5409
  execute: async ({ path, recursive, maxDepth }) => {
4839
5410
  try {
4840
- const absolutePath = isAbsolute4(path) ? path : resolve8(workingDirectory, path);
4841
- if (!existsSync11(absolutePath)) {
5411
+ const absolutePath = isAbsolute5(path) ? path : resolve9(workingDirectory, path);
5412
+ if (!existsSync12(absolutePath)) {
4842
5413
  return {
4843
5414
  success: false,
4844
5415
  error: `Directory not found: ${path}`
@@ -4862,20 +5433,20 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4862
5433
  const files = stdout.trim().split("\n").filter(Boolean);
4863
5434
  return {
4864
5435
  success: true,
4865
- path: relative7(workingDirectory, absolutePath) || ".",
5436
+ path: relative8(workingDirectory, absolutePath) || ".",
4866
5437
  files,
4867
5438
  count: files.length,
4868
5439
  recursive: true
4869
5440
  };
4870
5441
  } else {
4871
- const entries = await readdir3(absolutePath, { withFileTypes: true });
5442
+ const entries = await readdir4(absolutePath, { withFileTypes: true });
4872
5443
  const items = entries.slice(0, 200).map((e) => ({
4873
5444
  name: e.name,
4874
5445
  type: e.isDirectory() ? "directory" : "file"
4875
5446
  }));
4876
5447
  return {
4877
5448
  success: true,
4878
- path: relative7(workingDirectory, absolutePath) || ".",
5449
+ path: relative8(workingDirectory, absolutePath) || ".",
4879
5450
  items,
4880
5451
  count: items.length
4881
5452
  };
@@ -4887,6 +5458,9 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4887
5458
  };
4888
5459
  }
4889
5460
  }
5461
+ }),
5462
+ code_graph: createCodeGraphTool({
5463
+ workingDirectory
4890
5464
  })
4891
5465
  };
4892
5466
  try {
@@ -4980,6 +5554,26 @@ Keep it concise but INCLUDE THE ACTUAL DATA.`;
4980
5554
  context: m.symbolName || m.language
4981
5555
  });
4982
5556
  }
5557
+ } else if (step.toolName === "code_graph" && output.success) {
5558
+ matchCount += output.referenceCount || 0;
5559
+ if (output.filePath) {
5560
+ findings.push({
5561
+ type: "file",
5562
+ path: output.filePath,
5563
+ lineNumber: output.line,
5564
+ content: output.typeInfo ? truncateOutput(output.typeInfo, 300) : void 0,
5565
+ relevance: "high",
5566
+ context: `${output.kind || "symbol"}${output.referenceCount ? `, ${output.referenceCount} refs` : ""}`
5567
+ });
5568
+ }
5569
+ for (const page of (output.pages || []).slice(0, 10)) {
5570
+ findings.push({
5571
+ type: "file",
5572
+ path: page.path,
5573
+ relevance: "high",
5574
+ context: page.route ? `route: ${page.route}` : "page"
5575
+ });
5576
+ }
4983
5577
  }
4984
5578
  }
4985
5579
  }
@@ -5001,7 +5595,7 @@ function createSearchSubagent(model) {
5001
5595
  // src/tools/search.ts
5002
5596
  var MAX_RESULT_CHARS = 1e4;
5003
5597
  function createSearchTool(options) {
5004
- return tool9({
5598
+ return tool10({
5005
5599
  description: `Delegate an explore task to the explore_agent tool. Use this when you need to:
5006
5600
  - Find files or code matching a pattern
5007
5601
  - Explore the codebase structure
@@ -5011,11 +5605,12 @@ function createSearchTool(options) {
5011
5605
  The Explore agent will explore the codebase and return a summary of findings.
5012
5606
  This is more thorough than a simple grep because it can follow references and understand context.
5013
5607
  It also has access to semantic search to find code by meaning, not just text.
5608
+ It can also use code_graph to inspect a symbol's type hierarchy, references, and which pages/routes use it.
5014
5609
 
5015
5610
  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.`,
5016
- inputSchema: z10.object({
5017
- query: z10.string().describe("What to search for. Be specific about what you're looking for."),
5018
- 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.")
5611
+ inputSchema: z11.object({
5612
+ query: z11.string().describe("What to search for. Be specific about what you're looking for."),
5613
+ 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.")
5019
5614
  }),
5020
5615
  execute: async ({ query, context }, toolOptions) => {
5021
5616
  const toolCallId = toolOptions.toolCallId || `explore_agent_${Date.now()}`;
@@ -5159,6 +5754,9 @@ async function createTools(options) {
5159
5754
  sessionId: options.sessionId,
5160
5755
  workingDirectory: options.workingDirectory,
5161
5756
  onProgress: options.onSearchProgress
5757
+ }),
5758
+ code_graph: createCodeGraphTool({
5759
+ workingDirectory: options.workingDirectory
5162
5760
  })
5163
5761
  };
5164
5762
  if (options.enableSemanticSearch !== false) {
@@ -5250,6 +5848,7 @@ You have access to powerful tools for:
5250
5848
  - **todo**: Manage your task list to track progress on complex operations
5251
5849
  - **load_skill**: Load specialized knowledge documents for specific tasks
5252
5850
  - **explore_agent**: Explore agent for semantic discovery - for exploratory questions and finding code by meaning
5851
+ - **code_graph**: Inspect a symbol's type hierarchy and usage graph via the TypeScript language server
5253
5852
 
5254
5853
 
5255
5854
  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.
@@ -5339,6 +5938,33 @@ linter({ paths: ["src/"] }) // Check all files in a directory
5339
5938
  \`\`\`
5340
5939
  Use this proactively after making code changes to catch errors early.
5341
5940
 
5941
+ ### Code Graph Tool
5942
+ The code_graph tool uses the TypeScript language server to inspect a symbol's type hierarchy and usage graph:
5943
+ \`\`\`
5944
+ code_graph({ symbol: "UserCard" }) // Search workspace for symbol
5945
+ code_graph({ symbol: "UserCard", filePath: "src/components.tsx" }) // Look up in a specific file
5946
+ code_graph({ symbol: "formatUser", filePath: "utils.ts", depth: 2 }) // Traverse 2 levels up the reference tree
5947
+ \`\`\`
5948
+
5949
+ **What it returns:**
5950
+ - The symbol's full type signature (parameters, return type)
5951
+ - All files/functions/components that reference it (grouped into pages vs components)
5952
+ - Which Next.js pages/routes contain it in their component tree
5953
+ - Level-2 transitive usages (who uses the things that use this symbol)
5954
+ - The file's symbol structure for surrounding context
5955
+
5956
+ **When to use code_graph:**
5957
+ - **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.
5958
+ - **Before making changes** to a function/component \u2014 understand what depends on it and what will break
5959
+ - **To understand component hierarchies** \u2014 what renders what, which pages are affected across the *entire* codebase (not just the current page)
5960
+ - **To get type signatures** (props, params, return types) without reading entire files
5961
+ - **After a devtools selection** when the task involves refactoring, changing props, or anything that could impact other consumers
5962
+
5963
+ **When NOT to use code_graph:**
5964
+ - For exploratory "how does X work?" questions \u2014 use \`explore_agent\` instead
5965
+ - For exact string searches \u2014 use grep/rg directly
5966
+ - For non-TypeScript/JavaScript files \u2014 code_graph only supports TS/JS/TSX/JSX
5967
+
5342
5968
  ### Searching and Exploration
5343
5969
 
5344
5970
  **Choose the right search approach:**
@@ -5346,7 +5972,8 @@ Use this proactively after making code changes to catch errors early.
5346
5972
  0. **Use paths to your advantage \u2014 skip searching if you already have what you need.**
5347
5973
  - 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.
5348
5974
  - 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.
5349
- - 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.
5975
+ - **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.
5976
+ - **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.
5350
5977
  - Read up and down component trees when you have the file path or page path to find what you're looking for.
5351
5978
  1. **Use the \`explore_agent\` tool (Explore agent)** for:
5352
5979
  - Semantic/exploratory questions: "How does authentication work?", "Where is user data processed?"
@@ -5364,7 +5991,14 @@ Use this proactively after making code changes to catch errors early.
5364
5991
  - If you skip the \`context\` field, the explore agent is searching completely blind and will waste time guessing.
5365
5992
  - NEVER call \`explore_agent\` with only a \`query\` and no \`context\` when the user's message contains devtools or component information.
5366
5993
 
5367
- 2. **Use direct commands (grep/rg, find)** for:
5994
+ 2. **Use the \`code_graph\` tool** for:
5995
+ - Understanding what depends on a specific symbol before changing it
5996
+ - Tracing component/function usage up to page-level routes
5997
+ - Getting type signatures (params, return types) without reading full files
5998
+ - Finding exact components usages in the codebase
5999
+ - Answering "what will break if I change this?" or "which pages use this component?"
6000
+
6001
+ 3. **Use direct commands (grep/rg, find)** for:
5368
6002
  - Exact string matches: \`rg "functionName"\`, \`rg "class MyClass"\`
5369
6003
  - Finding files by name: \`find . -name "*.config.ts"\`
5370
6004
  - Simple pattern matching when you know exactly what you're looking for
@@ -5372,7 +6006,11 @@ Use this proactively after making code changes to catch errors early.
5372
6006
 
5373
6007
  **Examples:**
5374
6008
  - User selected \`<LandingButton>\` at \`src/components/LandingButton.tsx:12\` \u2192 Just \`read_file("src/components/LandingButton.tsx")\`. Do NOT call explore_agent.
6009
+ - 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.
6010
+ - 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.
5375
6011
  - "Where is the API authentication handled?" (no file path given) \u2192 Use \`explore_agent\` tool
6012
+ - "What pages use the UserCard component?" \u2192 Use \`code_graph({ symbol: "UserCard" })\`
6013
+ - "What's the type signature of formatUser?" \u2192 Use \`code_graph({ symbol: "formatUser", filePath: "utils.ts" })\`
5376
6014
  - "Find all usages of getUserById" \u2192 Use \`rg "getUserById"\`
5377
6015
  - "How does the payment flow work?" \u2192 Use \`explore_agent\` tool
5378
6016
  - "Find files named config" \u2192 Use \`find . -name "*config*"\`
@@ -5944,9 +6582,9 @@ ${prompt}` });
5944
6582
  wrappedTools[name] = originalTool;
5945
6583
  continue;
5946
6584
  }
5947
- wrappedTools[name] = tool10({
6585
+ wrappedTools[name] = tool11({
5948
6586
  description: originalTool.description || "",
5949
- inputSchema: originalTool.inputSchema || z11.object({}),
6587
+ inputSchema: originalTool.inputSchema || z12.object({}),
5950
6588
  execute: async (input, toolOptions) => {
5951
6589
  const toolCallId = toolOptions.toolCallId || nanoid3();
5952
6590
  const execution = toolExecutionQueries.create({
@@ -5960,8 +6598,8 @@ ${prompt}` });
5960
6598
  this.pendingApprovals.set(toolCallId, await execution);
5961
6599
  options.onApprovalRequired?.(await execution);
5962
6600
  await sessionQueries.updateStatus(this.session.id, "waiting");
5963
- const approved = await new Promise((resolve11) => {
5964
- approvalResolvers.set(toolCallId, { resolve: resolve11, sessionId: this.session.id });
6601
+ const approved = await new Promise((resolve12) => {
6602
+ approvalResolvers.set(toolCallId, { resolve: resolve12, sessionId: this.session.id });
5965
6603
  });
5966
6604
  const resolverData = approvalResolvers.get(toolCallId);
5967
6605
  approvalResolvers.delete(toolCallId);
@@ -6087,18 +6725,18 @@ function cleanupPendingInputs() {
6087
6725
  }
6088
6726
  }
6089
6727
  }
6090
- var createSessionSchema = z12.object({
6091
- name: z12.string().optional(),
6092
- workingDirectory: z12.string().optional(),
6093
- model: z12.string().optional(),
6094
- toolApprovals: z12.record(z12.string(), z12.boolean()).optional()
6728
+ var createSessionSchema = z13.object({
6729
+ name: z13.string().optional(),
6730
+ workingDirectory: z13.string().optional(),
6731
+ model: z13.string().optional(),
6732
+ toolApprovals: z13.record(z13.string(), z13.boolean()).optional()
6095
6733
  });
6096
- var paginationQuerySchema = z12.object({
6097
- limit: z12.string().optional(),
6098
- offset: z12.string().optional()
6734
+ var paginationQuerySchema = z13.object({
6735
+ limit: z13.string().optional(),
6736
+ offset: z13.string().optional()
6099
6737
  });
6100
- var messagesQuerySchema = z12.object({
6101
- limit: z12.string().optional()
6738
+ var messagesQuerySchema = z13.object({
6739
+ limit: z13.string().optional()
6102
6740
  });
6103
6741
  sessions.get(
6104
6742
  "/",
@@ -6237,10 +6875,10 @@ sessions.get("/:id/tools", async (c) => {
6237
6875
  count: executions.length
6238
6876
  });
6239
6877
  });
6240
- var updateSessionSchema = z12.object({
6241
- model: z12.string().optional(),
6242
- name: z12.string().optional(),
6243
- toolApprovals: z12.record(z12.string(), z12.boolean()).optional()
6878
+ var updateSessionSchema = z13.object({
6879
+ model: z13.string().optional(),
6880
+ name: z13.string().optional(),
6881
+ toolApprovals: z13.record(z13.string(), z13.boolean()).optional()
6244
6882
  });
6245
6883
  sessions.patch(
6246
6884
  "/:id",
@@ -6310,8 +6948,8 @@ sessions.post("/:id/clear", async (c) => {
6310
6948
  await agent.clearContext();
6311
6949
  return c.json({ success: true, sessionId: id });
6312
6950
  });
6313
- var pendingInputSchema = z12.object({
6314
- text: z12.string()
6951
+ var pendingInputSchema = z13.object({
6952
+ text: z13.string()
6315
6953
  });
6316
6954
  sessions.post(
6317
6955
  "/:id/pending-input",
@@ -6342,13 +6980,13 @@ sessions.get("/:id/pending-input", async (c) => {
6342
6980
  createdAt: pending.createdAt.toISOString()
6343
6981
  });
6344
6982
  });
6345
- var devtoolsContextSchema = z12.object({
6346
- url: z12.string(),
6347
- path: z12.string(),
6348
- pageName: z12.string().optional(),
6349
- screenWidth: z12.number().optional(),
6350
- screenHeight: z12.number().optional(),
6351
- devicePixelRatio: z12.number().optional()
6983
+ var devtoolsContextSchema = z13.object({
6984
+ url: z13.string(),
6985
+ path: z13.string(),
6986
+ pageName: z13.string().optional(),
6987
+ screenWidth: z13.number().optional(),
6988
+ screenHeight: z13.number().optional(),
6989
+ devicePixelRatio: z13.number().optional()
6352
6990
  });
6353
6991
  sessions.post(
6354
6992
  "/:id/devtools-context",
@@ -6520,7 +7158,7 @@ function getAttachmentsDir(sessionId) {
6520
7158
  }
6521
7159
  function ensureAttachmentsDir(sessionId) {
6522
7160
  const dir = getAttachmentsDir(sessionId);
6523
- if (!existsSync12(dir)) {
7161
+ if (!existsSync13(dir)) {
6524
7162
  mkdirSync3(dir, { recursive: true });
6525
7163
  }
6526
7164
  return dir;
@@ -6532,7 +7170,7 @@ sessions.get("/:id/attachments", async (c) => {
6532
7170
  return c.json({ error: "Session not found" }, 404);
6533
7171
  }
6534
7172
  const dir = getAttachmentsDir(sessionId);
6535
- if (!existsSync12(dir)) {
7173
+ if (!existsSync13(dir)) {
6536
7174
  return c.json({ sessionId, attachments: [], count: 0 });
6537
7175
  }
6538
7176
  const files = readdirSync(dir);
@@ -6571,7 +7209,7 @@ sessions.post("/:id/attachments", async (c) => {
6571
7209
  const dir = ensureAttachmentsDir(sessionId);
6572
7210
  const id = nanoid4(10);
6573
7211
  const ext = extname6(file.name) || "";
6574
- const safeFilename = `${id}_${basename3(file.name).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
7212
+ const safeFilename = `${id}_${basename4(file.name).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
6575
7213
  const filePath = join5(dir, safeFilename);
6576
7214
  const arrayBuffer = await file.arrayBuffer();
6577
7215
  writeFileSync2(filePath, Buffer.from(arrayBuffer));
@@ -6597,7 +7235,7 @@ sessions.post("/:id/attachments", async (c) => {
6597
7235
  const dir = ensureAttachmentsDir(sessionId);
6598
7236
  const id = nanoid4(10);
6599
7237
  const ext = extname6(body.filename) || "";
6600
- const safeFilename = `${id}_${basename3(body.filename).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
7238
+ const safeFilename = `${id}_${basename4(body.filename).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
6601
7239
  const filePath = join5(dir, safeFilename);
6602
7240
  let base64Data = body.data;
6603
7241
  if (base64Data.includes(",")) {
@@ -6627,7 +7265,7 @@ sessions.delete("/:id/attachments/:attachmentId", async (c) => {
6627
7265
  return c.json({ error: "Session not found" }, 404);
6628
7266
  }
6629
7267
  const dir = getAttachmentsDir(sessionId);
6630
- if (!existsSync12(dir)) {
7268
+ if (!existsSync13(dir)) {
6631
7269
  return c.json({ error: "Attachment not found" }, 404);
6632
7270
  }
6633
7271
  const files = readdirSync(dir);
@@ -6639,10 +7277,10 @@ sessions.delete("/:id/attachments/:attachmentId", async (c) => {
6639
7277
  unlinkSync(filePath);
6640
7278
  return c.json({ success: true, id: attachmentId });
6641
7279
  });
6642
- var filesQuerySchema = z12.object({
6643
- query: z12.string().optional(),
7280
+ var filesQuerySchema = z13.object({
7281
+ query: z13.string().optional(),
6644
7282
  // Filter query (e.g., "src/com" to match "src/components")
6645
- limit: z12.string().optional()
7283
+ limit: z13.string().optional()
6646
7284
  // Max results (default 50)
6647
7285
  });
6648
7286
  var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
@@ -6715,11 +7353,11 @@ async function listWorkspaceFiles(baseDir, currentDir, query, limit, results = [
6715
7353
  return results;
6716
7354
  }
6717
7355
  try {
6718
- const entries = await readdir4(currentDir, { withFileTypes: true });
7356
+ const entries = await readdir5(currentDir, { withFileTypes: true });
6719
7357
  for (const entry of entries) {
6720
7358
  if (results.length >= limit * 2) break;
6721
7359
  const fullPath = join5(currentDir, entry.name);
6722
- const relativePath = relative8(baseDir, fullPath);
7360
+ const relativePath = relative9(baseDir, fullPath);
6723
7361
  if (entry.isDirectory() && IGNORED_DIRECTORIES.has(entry.name)) {
6724
7362
  continue;
6725
7363
  }
@@ -6766,7 +7404,7 @@ sessions.get(
6766
7404
  return c.json({ error: "Session not found" }, 404);
6767
7405
  }
6768
7406
  const workingDirectory = session.workingDirectory;
6769
- if (!existsSync12(workingDirectory)) {
7407
+ if (!existsSync13(workingDirectory)) {
6770
7408
  return c.json({
6771
7409
  sessionId,
6772
7410
  workingDirectory,
@@ -6820,8 +7458,8 @@ sessions.get(
6820
7458
  init_db();
6821
7459
  import { Hono as Hono2 } from "hono";
6822
7460
  import { zValidator as zValidator2 } from "@hono/zod-validator";
6823
- import { z as z13 } from "zod";
6824
- import { existsSync as existsSync13, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
7461
+ import { z as z14 } from "zod";
7462
+ import { existsSync as existsSync14, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
6825
7463
  import { join as join6 } from "path";
6826
7464
  init_config();
6827
7465
 
@@ -6962,7 +7600,7 @@ async function emitSyntheticToolStreaming(writeSSE, toolCallStarts, toolCallId,
6962
7600
  toolCallId,
6963
7601
  argsTextDelta: chunk
6964
7602
  }));
6965
- await new Promise((resolve11) => setTimeout(resolve11, 0));
7603
+ await new Promise((resolve12) => setTimeout(resolve12, 0));
6966
7604
  }
6967
7605
  }
6968
7606
  function buildDevtoolsContextXml(sessionId) {
@@ -6985,30 +7623,30 @@ function enrichPromptWithDevtoolsContext(sessionId, prompt) {
6985
7623
  ${prompt}`;
6986
7624
  }
6987
7625
  var agents = new Hono2();
6988
- var attachmentSchema = z13.object({
6989
- type: z13.enum(["image", "file"]),
6990
- data: z13.string(),
7626
+ var attachmentSchema = z14.object({
7627
+ type: z14.enum(["image", "file"]),
7628
+ data: z14.string(),
6991
7629
  // base64 data URL or raw base64
6992
- mediaType: z13.string().optional(),
6993
- filename: z13.string().optional()
7630
+ mediaType: z14.string().optional(),
7631
+ filename: z14.string().optional()
6994
7632
  });
6995
- var runPromptSchema = z13.object({
6996
- prompt: z13.string(),
7633
+ var runPromptSchema = z14.object({
7634
+ prompt: z14.string(),
6997
7635
  // Can be empty if attachments are provided
6998
- attachments: z13.array(attachmentSchema).optional()
7636
+ attachments: z14.array(attachmentSchema).optional()
6999
7637
  }).refine(
7000
7638
  (data) => data.prompt.trim().length > 0 || data.attachments && data.attachments.length > 0,
7001
7639
  { message: "Either prompt or attachments must be provided" }
7002
7640
  );
7003
- var quickStartSchema = z13.object({
7004
- prompt: z13.string().min(1),
7005
- name: z13.string().optional(),
7006
- workingDirectory: z13.string().optional(),
7007
- model: z13.string().optional(),
7008
- toolApprovals: z13.record(z13.string(), z13.boolean()).optional()
7641
+ var quickStartSchema = z14.object({
7642
+ prompt: z14.string().min(1),
7643
+ name: z14.string().optional(),
7644
+ workingDirectory: z14.string().optional(),
7645
+ model: z14.string().optional(),
7646
+ toolApprovals: z14.record(z14.string(), z14.boolean()).optional()
7009
7647
  });
7010
- var rejectSchema = z13.object({
7011
- reason: z13.string().optional()
7648
+ var rejectSchema = z14.object({
7649
+ reason: z14.string().optional()
7012
7650
  }).optional();
7013
7651
  var streamAbortControllers = /* @__PURE__ */ new Map();
7014
7652
  function getAttachmentsDirectory(sessionId) {
@@ -7017,7 +7655,7 @@ function getAttachmentsDirectory(sessionId) {
7017
7655
  }
7018
7656
  function saveAttachmentToDisk(sessionId, attachment, index) {
7019
7657
  const attachmentsDir = getAttachmentsDirectory(sessionId);
7020
- if (!existsSync13(attachmentsDir)) {
7658
+ if (!existsSync14(attachmentsDir)) {
7021
7659
  mkdirSync4(attachmentsDir, { recursive: true });
7022
7660
  }
7023
7661
  let filename = attachment.filename;
@@ -7195,7 +7833,7 @@ ${prompt}` });
7195
7833
  chunkIndex,
7196
7834
  chunkCount
7197
7835
  }));
7198
- await new Promise((resolve11) => setTimeout(resolve11, 0));
7836
+ await new Promise((resolve12) => setTimeout(resolve12, 0));
7199
7837
  }
7200
7838
  },
7201
7839
  onStepFinish: async () => {
@@ -7659,7 +8297,7 @@ agents.post(
7659
8297
  chunkIndex,
7660
8298
  chunkCount
7661
8299
  }));
7662
- await new Promise((resolve11) => setTimeout(resolve11, 0));
8300
+ await new Promise((resolve12) => setTimeout(resolve12, 0));
7663
8301
  }
7664
8302
  },
7665
8303
  onStepFinish: async () => {
@@ -7796,11 +8434,11 @@ agents.post(
7796
8434
  init_config();
7797
8435
  import { Hono as Hono3 } from "hono";
7798
8436
  import { zValidator as zValidator3 } from "@hono/zod-validator";
7799
- import { z as z14 } from "zod";
8437
+ import { z as z15 } from "zod";
7800
8438
  import { readFileSync as readFileSync5 } from "fs";
7801
- import { fileURLToPath as fileURLToPath2 } from "url";
8439
+ import { fileURLToPath as fileURLToPath3 } from "url";
7802
8440
  import { dirname as dirname6, join as join7 } from "path";
7803
- var __filename = fileURLToPath2(import.meta.url);
8441
+ var __filename = fileURLToPath3(import.meta.url);
7804
8442
  var __dirname = dirname6(__filename);
7805
8443
  var possiblePaths = [
7806
8444
  join7(__dirname, "../package.json"),
@@ -7906,9 +8544,9 @@ health.get("/api-keys", async (c) => {
7906
8544
  supportedProviders: SUPPORTED_PROVIDERS
7907
8545
  });
7908
8546
  });
7909
- var setApiKeySchema = z14.object({
7910
- provider: z14.string(),
7911
- apiKey: z14.string().min(1)
8547
+ var setApiKeySchema = z15.object({
8548
+ provider: z15.string(),
8549
+ apiKey: z15.string().min(1)
7912
8550
  });
7913
8551
  health.post(
7914
8552
  "/api-keys",
@@ -7947,13 +8585,13 @@ health.delete("/api-keys/:provider", async (c) => {
7947
8585
  // src/server/routes/terminals.ts
7948
8586
  import { Hono as Hono4 } from "hono";
7949
8587
  import { zValidator as zValidator4 } from "@hono/zod-validator";
7950
- import { z as z15 } from "zod";
8588
+ import { z as z16 } from "zod";
7951
8589
  init_db();
7952
8590
  var terminals = new Hono4();
7953
- var spawnSchema = z15.object({
7954
- command: z15.string(),
7955
- cwd: z15.string().optional(),
7956
- name: z15.string().optional()
8591
+ var spawnSchema = z16.object({
8592
+ command: z16.string(),
8593
+ cwd: z16.string().optional(),
8594
+ name: z16.string().optional()
7957
8595
  });
7958
8596
  terminals.post(
7959
8597
  "/:sessionId/terminals",
@@ -8034,8 +8672,8 @@ terminals.get("/:sessionId/terminals/:terminalId", async (c) => {
8034
8672
  // We don't track exit codes in tmux mode
8035
8673
  });
8036
8674
  });
8037
- var logsQuerySchema = z15.object({
8038
- tail: z15.string().optional().transform((v) => v ? parseInt(v, 10) : void 0)
8675
+ var logsQuerySchema = z16.object({
8676
+ tail: z16.string().optional().transform((v) => v ? parseInt(v, 10) : void 0)
8039
8677
  });
8040
8678
  terminals.get(
8041
8679
  "/:sessionId/terminals/:terminalId/logs",
@@ -8059,8 +8697,8 @@ terminals.get(
8059
8697
  });
8060
8698
  }
8061
8699
  );
8062
- var killSchema = z15.object({
8063
- signal: z15.enum(["SIGTERM", "SIGKILL"]).optional()
8700
+ var killSchema = z16.object({
8701
+ signal: z16.enum(["SIGTERM", "SIGKILL"]).optional()
8064
8702
  });
8065
8703
  terminals.post(
8066
8704
  "/:sessionId/terminals/:terminalId/kill",
@@ -8074,8 +8712,8 @@ terminals.post(
8074
8712
  return c.json({ success: true, message: "Terminal killed" });
8075
8713
  }
8076
8714
  );
8077
- var writeSchema = z15.object({
8078
- input: z15.string()
8715
+ var writeSchema = z16.object({
8716
+ input: z16.string()
8079
8717
  });
8080
8718
  terminals.post(
8081
8719
  "/:sessionId/terminals/:terminalId/write",
@@ -8399,13 +9037,13 @@ var DEFAULT_WEB_PORT = 6969;
8399
9037
  var WEB_PORT_SEQUENCE = [6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978];
8400
9038
  function getWebDirectory() {
8401
9039
  try {
8402
- const currentDir = dirname7(fileURLToPath3(import.meta.url));
8403
- const webDir = resolve9(currentDir, "..", "web");
8404
- if (existsSync14(webDir) && existsSync14(join8(webDir, "package.json"))) {
9040
+ const currentDir = dirname7(fileURLToPath4(import.meta.url));
9041
+ const webDir = resolve10(currentDir, "..", "web");
9042
+ if (existsSync15(webDir) && existsSync15(join8(webDir, "package.json"))) {
8405
9043
  return webDir;
8406
9044
  }
8407
- const altWebDir = resolve9(currentDir, "..", "..", "web");
8408
- if (existsSync14(altWebDir) && existsSync14(join8(altWebDir, "package.json"))) {
9045
+ const altWebDir = resolve10(currentDir, "..", "..", "web");
9046
+ if (existsSync15(altWebDir) && existsSync15(join8(altWebDir, "package.json"))) {
8409
9047
  return altWebDir;
8410
9048
  }
8411
9049
  return null;
@@ -8428,18 +9066,18 @@ async function isSparkcoderWebRunning(port) {
8428
9066
  }
8429
9067
  }
8430
9068
  function isPortInUse(port) {
8431
- return new Promise((resolve11) => {
9069
+ return new Promise((resolve12) => {
8432
9070
  const server = createNetServer();
8433
9071
  server.once("error", (err) => {
8434
9072
  if (err.code === "EADDRINUSE") {
8435
- resolve11(true);
9073
+ resolve12(true);
8436
9074
  } else {
8437
- resolve11(false);
9075
+ resolve12(false);
8438
9076
  }
8439
9077
  });
8440
9078
  server.once("listening", () => {
8441
9079
  server.close();
8442
- resolve11(false);
9080
+ resolve12(false);
8443
9081
  });
8444
9082
  server.listen(port, "0.0.0.0");
8445
9083
  });
@@ -8464,14 +9102,14 @@ async function findWebPort(preferredPort) {
8464
9102
  }
8465
9103
  function hasProductionBuild(webDir) {
8466
9104
  const buildIdPath = join8(webDir, ".next", "BUILD_ID");
8467
- return existsSync14(buildIdPath);
9105
+ return existsSync15(buildIdPath);
8468
9106
  }
8469
9107
  function hasSourceFiles(webDir) {
8470
9108
  const appDir = join8(webDir, "src", "app");
8471
9109
  const pagesDir = join8(webDir, "src", "pages");
8472
9110
  const rootAppDir = join8(webDir, "app");
8473
9111
  const rootPagesDir = join8(webDir, "pages");
8474
- return existsSync14(appDir) || existsSync14(pagesDir) || existsSync14(rootAppDir) || existsSync14(rootPagesDir);
9112
+ return existsSync15(appDir) || existsSync15(pagesDir) || existsSync15(rootAppDir) || existsSync15(rootPagesDir);
8475
9113
  }
8476
9114
  function getStandaloneServerPath(webDir) {
8477
9115
  const possiblePaths2 = [
@@ -8479,14 +9117,14 @@ function getStandaloneServerPath(webDir) {
8479
9117
  join8(webDir, ".next", "standalone", "web", "server.js")
8480
9118
  ];
8481
9119
  for (const serverPath of possiblePaths2) {
8482
- if (existsSync14(serverPath)) {
9120
+ if (existsSync15(serverPath)) {
8483
9121
  return serverPath;
8484
9122
  }
8485
9123
  }
8486
9124
  return null;
8487
9125
  }
8488
9126
  function runCommand(command, args, cwd, env) {
8489
- return new Promise((resolve11) => {
9127
+ return new Promise((resolve12) => {
8490
9128
  const child = spawn2(command, args, {
8491
9129
  cwd,
8492
9130
  stdio: ["ignore", "pipe", "pipe"],
@@ -8501,10 +9139,10 @@ function runCommand(command, args, cwd, env) {
8501
9139
  output += data.toString();
8502
9140
  });
8503
9141
  child.on("close", (code) => {
8504
- resolve11({ success: code === 0, output });
9142
+ resolve12({ success: code === 0, output });
8505
9143
  });
8506
9144
  child.on("error", (err) => {
8507
- resolve11({ success: false, output: err.message });
9145
+ resolve12({ success: false, output: err.message });
8508
9146
  });
8509
9147
  });
8510
9148
  }
@@ -8519,8 +9157,8 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
8519
9157
  if (!quiet) console.log(` \u2713 Web UI already running at http://localhost:${actualPort}`);
8520
9158
  return { process: null, port: actualPort };
8521
9159
  }
8522
- const usePnpm = existsSync14(join8(webDir, "pnpm-lock.yaml"));
8523
- const useNpm = !usePnpm && existsSync14(join8(webDir, "package-lock.json"));
9160
+ const usePnpm = existsSync15(join8(webDir, "pnpm-lock.yaml"));
9161
+ const useNpm = !usePnpm && existsSync15(join8(webDir, "package-lock.json"));
8524
9162
  const pkgManager = usePnpm ? "pnpm" : useNpm ? "npm" : "npx";
8525
9163
  const { NODE_OPTIONS, TSX_TSCONFIG_PATH, ...cleanEnv } = process.env;
8526
9164
  const apiUrl = publicUrl || `http://127.0.0.1:${apiPort}`;
@@ -8588,10 +9226,10 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
8588
9226
  let started = false;
8589
9227
  let exited = false;
8590
9228
  let exitCode = null;
8591
- const startedPromise = new Promise((resolve11) => {
9229
+ const startedPromise = new Promise((resolve12) => {
8592
9230
  const timeout = setTimeout(() => {
8593
9231
  if (!started && !exited) {
8594
- resolve11(false);
9232
+ resolve12(false);
8595
9233
  }
8596
9234
  }, startupTimeout);
8597
9235
  child.stdout?.on("data", (data) => {
@@ -8605,7 +9243,7 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
8605
9243
  if (!started && (output.includes("Ready") || output.includes("started") || output.includes("localhost"))) {
8606
9244
  started = true;
8607
9245
  clearTimeout(timeout);
8608
- resolve11(true);
9246
+ resolve12(true);
8609
9247
  }
8610
9248
  });
8611
9249
  child.stderr?.on("data", (data) => {
@@ -8617,14 +9255,14 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
8617
9255
  child.on("error", (err) => {
8618
9256
  if (!quiet) console.error(` \u274C Web UI spawn error: ${err.message}`);
8619
9257
  clearTimeout(timeout);
8620
- resolve11(false);
9258
+ resolve12(false);
8621
9259
  });
8622
9260
  child.on("exit", (code) => {
8623
9261
  exited = true;
8624
9262
  exitCode = code;
8625
9263
  if (!started) {
8626
9264
  clearTimeout(timeout);
8627
- resolve11(false);
9265
+ resolve12(false);
8628
9266
  }
8629
9267
  webUIProcess = null;
8630
9268
  });
@@ -8717,7 +9355,7 @@ async function startServer(options = {}) {
8717
9355
  if (options.workingDirectory) {
8718
9356
  config.resolvedWorkingDirectory = options.workingDirectory;
8719
9357
  }
8720
- if (!existsSync14(config.resolvedWorkingDirectory)) {
9358
+ if (!existsSync15(config.resolvedWorkingDirectory)) {
8721
9359
  mkdirSync5(config.resolvedWorkingDirectory, { recursive: true });
8722
9360
  if (!options.quiet) console.log(`\u{1F4C1} Created agent workspace: ${config.resolvedWorkingDirectory}`);
8723
9361
  }
@@ -9234,8 +9872,8 @@ function generateOpenAPISpec() {
9234
9872
  init_config();
9235
9873
  init_semantic();
9236
9874
  init_db();
9237
- import { writeFileSync as writeFileSync5, existsSync as existsSync15 } from "fs";
9238
- import { resolve as resolve10, join as join9 } from "path";
9875
+ import { writeFileSync as writeFileSync5, existsSync as existsSync16 } from "fs";
9876
+ import { resolve as resolve11, join as join9 } from "path";
9239
9877
  async function apiRequest(baseUrl, path, options = {}) {
9240
9878
  const url = `${baseUrl}${path}`;
9241
9879
  const init = {
@@ -9270,13 +9908,13 @@ async function getActiveStream(baseUrl, sessionId) {
9270
9908
  return { hasActiveStream: false };
9271
9909
  }
9272
9910
  function promptApproval(rl, toolName, input) {
9273
- return new Promise((resolve11) => {
9911
+ return new Promise((resolve12) => {
9274
9912
  const inputStr = JSON.stringify(input);
9275
9913
  const truncatedInput = inputStr.length > 100 ? inputStr.slice(0, 100) + "..." : inputStr;
9276
9914
  console.log(chalk.dim(` Command: ${truncatedInput}`));
9277
9915
  rl.question(chalk.yellow(` Approve? [y/n]: `), (answer) => {
9278
9916
  const approved = answer.toLowerCase().startsWith("y");
9279
- resolve11(approved);
9917
+ resolve12(approved);
9280
9918
  });
9281
9919
  });
9282
9920
  }
@@ -9459,9 +10097,9 @@ async function runChat(options) {
9459
10097
  input: process.stdin,
9460
10098
  output: process.stdout
9461
10099
  });
9462
- const apiKey = await new Promise((resolve11) => {
10100
+ const apiKey = await new Promise((resolve12) => {
9463
10101
  keyRl.question(chalk.cyan("Enter your AI Gateway API key: "), (answer) => {
9464
- resolve11(answer.trim());
10102
+ resolve12(answer.trim());
9465
10103
  });
9466
10104
  });
9467
10105
  keyRl.close();
@@ -9795,10 +10433,10 @@ program.command("init").description("Create a sparkecoder.config.json file").opt
9795
10433
  configPath = join9(appDataDir, "sparkecoder.config.json");
9796
10434
  configLocation = "global";
9797
10435
  } else {
9798
- configPath = resolve10(process.cwd(), "sparkecoder.config.json");
10436
+ configPath = resolve11(process.cwd(), "sparkecoder.config.json");
9799
10437
  configLocation = "local";
9800
10438
  }
9801
- if (existsSync15(configPath) && !options.force) {
10439
+ if (existsSync16(configPath) && !options.force) {
9802
10440
  console.log(chalk.yellow("Config file already exists. Use --force to overwrite."));
9803
10441
  console.log(chalk.dim(` ${configPath}`));
9804
10442
  return;
@@ -9861,7 +10499,7 @@ program.command("config").description("Show current configuration").option("-c,
9861
10499
  });
9862
10500
  program.command("index").description("Index repository for semantic search").option("--status", "Show index status instead of indexing").option("--full", "Force full re-index (ignore existing embeddings)").option("-w, --working-dir <path>", "Working directory (defaults to current directory)").option("-c, --config <path>", "Path to config file").option("-v, --verbose", "Show detailed progress").action(async (options) => {
9863
10501
  try {
9864
- const workingDir = options.workingDir ? resolve10(options.workingDir) : process.cwd();
10502
+ const workingDir = options.workingDir ? resolve11(options.workingDir) : process.cwd();
9865
10503
  let config = loadConfig(options.config, workingDir);
9866
10504
  const remoteUrl = config.resolvedRemoteServer.url;
9867
10505
  if (!remoteUrl) {
@@ -9995,7 +10633,7 @@ Indexing ${chalk.cyan(namespace)}...
9995
10633
  });
9996
10634
  program.command("search").description("Search indexed repository using semantic search").argument("<query>", "Search query").option("-n, --num <count>", "Number of results to show", "5").option("-w, --working-dir <path>", "Working directory (defaults to current directory)").option("-c, --config <path>", "Path to config file").action(async (query, options) => {
9997
10635
  try {
9998
- const workingDir = options.workingDir ? resolve10(options.workingDir) : process.cwd();
10636
+ const workingDir = options.workingDir ? resolve11(options.workingDir) : process.cwd();
9999
10637
  const config = loadConfig(options.config, workingDir);
10000
10638
  const remoteUrl = config.resolvedRemoteServer.url;
10001
10639
  if (!remoteUrl) {