codesift-mcp 0.5.24 → 0.5.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +28 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/hooks.d.ts +4 -0
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +15 -4
- package/dist/cli/hooks.js.map +1 -1
- package/dist/cli/journal-commands.d.ts +9 -0
- package/dist/cli/journal-commands.d.ts.map +1 -0
- package/dist/cli/journal-commands.js +160 -0
- package/dist/cli/journal-commands.js.map +1 -0
- package/dist/cli/wiki-commands.d.ts.map +1 -1
- package/dist/cli/wiki-commands.js +5 -0
- package/dist/cli/wiki-commands.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +41 -47
- package/dist/instructions.js.map +1 -1
- package/dist/parser/extractors/_shared.d.ts +2 -0
- package/dist/parser/extractors/_shared.d.ts.map +1 -1
- package/dist/parser/extractors/_shared.js +4 -0
- package/dist/parser/extractors/_shared.js.map +1 -1
- package/dist/parser/extractors/typescript.d.ts.map +1 -1
- package/dist/parser/extractors/typescript.js +606 -31
- package/dist/parser/extractors/typescript.js.map +1 -1
- package/dist/parser/parse-worker.d.ts +2 -0
- package/dist/parser/parse-worker.d.ts.map +1 -0
- package/dist/parser/parse-worker.js +47 -0
- package/dist/parser/parse-worker.js.map +1 -0
- package/dist/parser/parser-manager.d.ts +10 -1
- package/dist/parser/parser-manager.d.ts.map +1 -1
- package/dist/parser/parser-manager.js +40 -2
- package/dist/parser/parser-manager.js.map +1 -1
- package/dist/parser/parser-pool.d.ts +31 -0
- package/dist/parser/parser-pool.d.ts.map +1 -0
- package/dist/parser/parser-pool.js +211 -0
- package/dist/parser/parser-pool.js.map +1 -0
- package/dist/register-tools.d.ts.map +1 -1
- package/dist/register-tools.js +382 -35
- package/dist/register-tools.js.map +1 -1
- package/dist/retrieval/codebase-retrieval.d.ts.map +1 -1
- package/dist/retrieval/codebase-retrieval.js +9 -1
- package/dist/retrieval/codebase-retrieval.js.map +1 -1
- package/dist/search/chunker.d.ts +1 -0
- package/dist/search/chunker.d.ts.map +1 -1
- package/dist/search/chunker.js +8 -1
- package/dist/search/chunker.js.map +1 -1
- package/dist/server-helpers.d.ts +27 -0
- package/dist/server-helpers.d.ts.map +1 -1
- package/dist/server-helpers.js +90 -9
- package/dist/server-helpers.js.map +1 -1
- package/dist/server.js +31 -0
- package/dist/server.js.map +1 -1
- package/dist/storage/index-store.d.ts +41 -4
- package/dist/storage/index-store.d.ts.map +1 -1
- package/dist/storage/index-store.js +89 -6
- package/dist/storage/index-store.js.map +1 -1
- package/dist/storage/watcher.d.ts +33 -6
- package/dist/storage/watcher.d.ts.map +1 -1
- package/dist/storage/watcher.js +73 -34
- package/dist/storage/watcher.js.map +1 -1
- package/dist/storage/workspace-resolver.d.ts +15 -0
- package/dist/storage/workspace-resolver.d.ts.map +1 -0
- package/dist/storage/workspace-resolver.js +130 -0
- package/dist/storage/workspace-resolver.js.map +1 -0
- package/dist/tools/_helpers.d.ts +37 -0
- package/dist/tools/_helpers.d.ts.map +1 -0
- package/dist/tools/_helpers.js +31 -0
- package/dist/tools/_helpers.js.map +1 -0
- package/dist/tools/constant-resolution-tools.d.ts +8 -0
- package/dist/tools/constant-resolution-tools.d.ts.map +1 -0
- package/dist/tools/constant-resolution-tools.js +68 -0
- package/dist/tools/constant-resolution-tools.js.map +1 -0
- package/dist/tools/graph-tools.d.ts +27 -5
- package/dist/tools/graph-tools.d.ts.map +1 -1
- package/dist/tools/graph-tools.js +141 -18
- package/dist/tools/graph-tools.js.map +1 -1
- package/dist/tools/hotspot-tools.d.ts +6 -0
- package/dist/tools/hotspot-tools.d.ts.map +1 -1
- package/dist/tools/hotspot-tools.js +48 -8
- package/dist/tools/hotspot-tools.js.map +1 -1
- package/dist/tools/impact-tools.d.ts.map +1 -1
- package/dist/tools/impact-tools.js +9 -2
- package/dist/tools/impact-tools.js.map +1 -1
- package/dist/tools/index-tools.d.ts +15 -1
- package/dist/tools/index-tools.d.ts.map +1 -1
- package/dist/tools/index-tools.js +161 -16
- package/dist/tools/index-tools.js.map +1 -1
- package/dist/tools/journal-generator-helpers.d.ts +55 -0
- package/dist/tools/journal-generator-helpers.d.ts.map +1 -0
- package/dist/tools/journal-generator-helpers.js +250 -0
- package/dist/tools/journal-generator-helpers.js.map +1 -0
- package/dist/tools/journal-generator.d.ts +48 -0
- package/dist/tools/journal-generator.d.ts.map +1 -0
- package/dist/tools/journal-generator.js +204 -0
- package/dist/tools/journal-generator.js.map +1 -0
- package/dist/tools/journal-git-client.d.ts +20 -0
- package/dist/tools/journal-git-client.d.ts.map +1 -0
- package/dist/tools/journal-git-client.js +57 -0
- package/dist/tools/journal-git-client.js.map +1 -0
- package/dist/tools/journal-llm-client.d.ts +57 -0
- package/dist/tools/journal-llm-client.d.ts.map +1 -0
- package/dist/tools/journal-llm-client.js +175 -0
- package/dist/tools/journal-llm-client.js.map +1 -0
- package/dist/tools/journal-migrator.d.ts +22 -0
- package/dist/tools/journal-migrator.d.ts.map +1 -0
- package/dist/tools/journal-migrator.js +183 -0
- package/dist/tools/journal-migrator.js.map +1 -0
- package/dist/tools/journal-phase-detector.d.ts +26 -0
- package/dist/tools/journal-phase-detector.d.ts.map +1 -0
- package/dist/tools/journal-phase-detector.js +126 -0
- package/dist/tools/journal-phase-detector.js.map +1 -0
- package/dist/tools/journal-sentinel.d.ts +15 -0
- package/dist/tools/journal-sentinel.d.ts.map +1 -0
- package/dist/tools/journal-sentinel.js +110 -0
- package/dist/tools/journal-sentinel.js.map +1 -0
- package/dist/tools/journal-templates.d.ts +28 -0
- package/dist/tools/journal-templates.d.ts.map +1 -0
- package/dist/tools/journal-templates.js +93 -0
- package/dist/tools/journal-templates.js.map +1 -0
- package/dist/tools/pattern-tools.d.ts +2 -0
- package/dist/tools/pattern-tools.d.ts.map +1 -1
- package/dist/tools/pattern-tools.js +73 -0
- package/dist/tools/pattern-tools.js.map +1 -1
- package/dist/tools/perf-tools.d.ts.map +1 -1
- package/dist/tools/perf-tools.js +6 -0
- package/dist/tools/perf-tools.js.map +1 -1
- package/dist/tools/plan-turn-tools.d.ts.map +1 -1
- package/dist/tools/plan-turn-tools.js +38 -2
- package/dist/tools/plan-turn-tools.js.map +1 -1
- package/dist/tools/project-tools.d.ts +6 -0
- package/dist/tools/project-tools.d.ts.map +1 -1
- package/dist/tools/project-tools.js +65 -25
- package/dist/tools/project-tools.js.map +1 -1
- package/dist/tools/python-constants-tools.d.ts +6 -0
- package/dist/tools/python-constants-tools.d.ts.map +1 -1
- package/dist/tools/python-constants-tools.js.map +1 -1
- package/dist/tools/react-tools.d.ts +44 -1
- package/dist/tools/react-tools.d.ts.map +1 -1
- package/dist/tools/react-tools.js +142 -9
- package/dist/tools/react-tools.js.map +1 -1
- package/dist/tools/search-tools.d.ts.map +1 -1
- package/dist/tools/search-tools.js +21 -2
- package/dist/tools/search-tools.js.map +1 -1
- package/dist/tools/status-tools.d.ts +10 -0
- package/dist/tools/status-tools.d.ts.map +1 -1
- package/dist/tools/status-tools.js +53 -2
- package/dist/tools/status-tools.js.map +1 -1
- package/dist/tools/symbol-tools.d.ts +13 -0
- package/dist/tools/symbol-tools.d.ts.map +1 -1
- package/dist/tools/symbol-tools.js +38 -0
- package/dist/tools/symbol-tools.js.map +1 -1
- package/dist/tools/typescript-constants-tools.d.ts +6 -0
- package/dist/tools/typescript-constants-tools.d.ts.map +1 -0
- package/dist/tools/typescript-constants-tools.js +687 -0
- package/dist/tools/typescript-constants-tools.js.map +1 -0
- package/dist/tools/wiki-hub-ranker.d.ts +36 -0
- package/dist/tools/wiki-hub-ranker.d.ts.map +1 -0
- package/dist/tools/wiki-hub-ranker.js +72 -0
- package/dist/tools/wiki-hub-ranker.js.map +1 -0
- package/dist/tools/wiki-lint.d.ts +7 -2
- package/dist/tools/wiki-lint.d.ts.map +1 -1
- package/dist/tools/wiki-lint.js +73 -1
- package/dist/tools/wiki-lint.js.map +1 -1
- package/dist/tools/wiki-manifest.d.ts +129 -21
- package/dist/tools/wiki-manifest.d.ts.map +1 -1
- package/dist/tools/wiki-manifest.js +16 -9
- package/dist/tools/wiki-manifest.js.map +1 -1
- package/dist/tools/wiki-module-builder.d.ts +42 -0
- package/dist/tools/wiki-module-builder.d.ts.map +1 -0
- package/dist/tools/wiki-module-builder.js +449 -0
- package/dist/tools/wiki-module-builder.js.map +1 -0
- package/dist/tools/wiki-overview-sources.d.ts +26 -0
- package/dist/tools/wiki-overview-sources.d.ts.map +1 -0
- package/dist/tools/wiki-overview-sources.js +128 -0
- package/dist/tools/wiki-overview-sources.js.map +1 -0
- package/dist/tools/wiki-page-generators.d.ts +19 -3
- package/dist/tools/wiki-page-generators.d.ts.map +1 -1
- package/dist/tools/wiki-page-generators.js +156 -22
- package/dist/tools/wiki-page-generators.js.map +1 -1
- package/dist/tools/wiki-tools.d.ts +20 -0
- package/dist/tools/wiki-tools.d.ts.map +1 -1
- package/dist/tools/wiki-tools.js +181 -29
- package/dist/tools/wiki-tools.js.map +1 -1
- package/dist/tools/workspace-scope-helper.d.ts +21 -0
- package/dist/tools/workspace-scope-helper.d.ts.map +1 -0
- package/dist/tools/workspace-scope-helper.js +50 -0
- package/dist/tools/workspace-scope-helper.js.map +1 -0
- package/dist/tools/workspace-tools.d.ts +74 -0
- package/dist/tools/workspace-tools.d.ts.map +1 -0
- package/dist/tools/workspace-tools.js +366 -0
- package/dist/tools/workspace-tools.js.map +1 -0
- package/dist/types.d.ts +65 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/import-graph.d.ts +27 -0
- package/dist/utils/import-graph.d.ts.map +1 -1
- package/dist/utils/import-graph.js +331 -8
- package/dist/utils/import-graph.js.map +1 -1
- package/dist/utils/ts-imports.d.ts +30 -0
- package/dist/utils/ts-imports.d.ts.map +1 -0
- package/dist/utils/ts-imports.js +168 -0
- package/dist/utils/ts-imports.js.map +1 -0
- package/dist/utils/tsconfig-paths.d.ts +59 -0
- package/dist/utils/tsconfig-paths.d.ts.map +1 -0
- package/dist/utils/tsconfig-paths.js +176 -0
- package/dist/utils/tsconfig-paths.js.map +1 -0
- package/dist/utils/walk.d.ts.map +1 -1
- package/dist/utils/walk.js +1 -0
- package/dist/utils/walk.js.map +1 -1
- package/package.json +13 -3
- package/rules/codesift.md +19 -2
- package/rules/codesift.mdc +2 -2
- package/rules/codex.md +13 -2
- package/rules/gemini.md +13 -2
package/dist/register-tools.js
CHANGED
|
@@ -246,6 +246,71 @@ const FRAMEWORK_TOOL_GROUPS = {
|
|
|
246
246
|
"extract_kotlin_serialization_contract",
|
|
247
247
|
"trace_flow_chain",
|
|
248
248
|
],
|
|
249
|
+
// Python — detected by pyproject.toml (poetry/pdm/uv/hatch) or requirements.txt
|
|
250
|
+
"pyproject.toml": [
|
|
251
|
+
"get_model_graph",
|
|
252
|
+
"get_test_fixtures",
|
|
253
|
+
"find_framework_wiring",
|
|
254
|
+
"run_ruff",
|
|
255
|
+
"parse_pyproject",
|
|
256
|
+
"find_python_callers",
|
|
257
|
+
"analyze_django_settings",
|
|
258
|
+
"run_mypy",
|
|
259
|
+
"run_pyright",
|
|
260
|
+
"analyze_python_deps",
|
|
261
|
+
"trace_fastapi_depends",
|
|
262
|
+
"analyze_async_correctness",
|
|
263
|
+
"get_pydantic_models",
|
|
264
|
+
"python_audit",
|
|
265
|
+
],
|
|
266
|
+
"requirements.txt": [
|
|
267
|
+
"get_model_graph",
|
|
268
|
+
"get_test_fixtures",
|
|
269
|
+
"find_framework_wiring",
|
|
270
|
+
"run_ruff",
|
|
271
|
+
"find_python_callers",
|
|
272
|
+
"analyze_django_settings",
|
|
273
|
+
"run_mypy",
|
|
274
|
+
"run_pyright",
|
|
275
|
+
"analyze_python_deps",
|
|
276
|
+
"trace_fastapi_depends",
|
|
277
|
+
"analyze_async_correctness",
|
|
278
|
+
"get_pydantic_models",
|
|
279
|
+
"python_audit",
|
|
280
|
+
],
|
|
281
|
+
// TypeScript baseline — auto-enabled on any project with tsconfig.json.
|
|
282
|
+
// Promotes 3 high-value but historically dark tools so that vanilla TS /
|
|
283
|
+
// library / monorepo repos get a proper entry point beyond search_text.
|
|
284
|
+
"tsconfig.json": [
|
|
285
|
+
"dependency_audit",
|
|
286
|
+
"check_boundaries",
|
|
287
|
+
"architecture_summary",
|
|
288
|
+
],
|
|
289
|
+
// Monorepo signals — orchestration-level analysis is most useful when
|
|
290
|
+
// there are >1 packages. Each of these files alone is enough to fire.
|
|
291
|
+
"pnpm-workspace.yaml": [
|
|
292
|
+
"check_boundaries",
|
|
293
|
+
"architecture_summary",
|
|
294
|
+
],
|
|
295
|
+
"lerna.json": [
|
|
296
|
+
"check_boundaries",
|
|
297
|
+
"architecture_summary",
|
|
298
|
+
],
|
|
299
|
+
"nx.json": [
|
|
300
|
+
"check_boundaries",
|
|
301
|
+
"architecture_summary",
|
|
302
|
+
],
|
|
303
|
+
"turbo.json": [
|
|
304
|
+
"check_boundaries",
|
|
305
|
+
"architecture_summary",
|
|
306
|
+
],
|
|
307
|
+
// Prisma — root-level schema. Nested prisma/schema.prisma handled in
|
|
308
|
+
// detectAutoLoadTools after the loop. drizzle-kit dep handled in
|
|
309
|
+
// detectFromPackageJson.
|
|
310
|
+
"schema.prisma": [
|
|
311
|
+
"analyze_prisma_schema",
|
|
312
|
+
"migration_lint",
|
|
313
|
+
],
|
|
249
314
|
};
|
|
250
315
|
/**
|
|
251
316
|
* React-specific tools — auto-enabled when a React project is detected.
|
|
@@ -282,6 +347,22 @@ const HONO_TOOLS = [
|
|
|
282
347
|
"detect_hono_modules",
|
|
283
348
|
"find_dead_hono_routes",
|
|
284
349
|
];
|
|
350
|
+
/**
|
|
351
|
+
* Monorepo tools — auto-enabled when `pkg.workspaces` field is present
|
|
352
|
+
* (mirror of the file-based monorepo signals in FRAMEWORK_TOOL_GROUPS).
|
|
353
|
+
*/
|
|
354
|
+
const MONOREPO_TOOLS = [
|
|
355
|
+
"check_boundaries",
|
|
356
|
+
"architecture_summary",
|
|
357
|
+
];
|
|
358
|
+
/**
|
|
359
|
+
* Prisma tools — auto-enabled when `prisma` or `drizzle-kit` is in deps
|
|
360
|
+
* (mirror of the schema.prisma file signal in FRAMEWORK_TOOL_GROUPS).
|
|
361
|
+
*/
|
|
362
|
+
const PRISMA_TOOLS = [
|
|
363
|
+
"analyze_prisma_schema",
|
|
364
|
+
"migration_lint",
|
|
365
|
+
];
|
|
285
366
|
const AUTO_LOAD_CACHE_TTL_MS = 5_000;
|
|
286
367
|
const autoLoadToolsCache = new Map();
|
|
287
368
|
/**
|
|
@@ -290,6 +371,8 @@ const autoLoadToolsCache = new Map();
|
|
|
290
371
|
* Exported for unit testing.
|
|
291
372
|
*/
|
|
292
373
|
export async function detectAutoLoadTools(cwd) {
|
|
374
|
+
// Kill switch: spec D-FB. Skip workspace walk entirely when set.
|
|
375
|
+
const killSwitchOff = process.env.CODESIFT_DISABLE_MONOREPO !== "1";
|
|
293
376
|
const { existsSync, readFileSync, readdirSync } = await import("node:fs");
|
|
294
377
|
const { join } = await import("node:path");
|
|
295
378
|
const toEnable = [];
|
|
@@ -298,30 +381,79 @@ export async function detectAutoLoadTools(cwd) {
|
|
|
298
381
|
toEnable.push(...tools);
|
|
299
382
|
}
|
|
300
383
|
}
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
if (existsSync(
|
|
384
|
+
// Nested Prisma schema — `prisma/schema.prisma` is the more common layout
|
|
385
|
+
// than root-level. The root-level case is covered by FRAMEWORK_TOOL_GROUPS.
|
|
386
|
+
if (existsSync(join(cwd, "prisma", "schema.prisma"))) {
|
|
387
|
+
toEnable.push(...PRISMA_TOOLS);
|
|
388
|
+
}
|
|
389
|
+
const detectFromPackageJson = (pkgRoot) => {
|
|
390
|
+
const enabled = [];
|
|
391
|
+
const pkgPath = join(pkgRoot, "package.json");
|
|
392
|
+
if (!existsSync(pkgPath))
|
|
393
|
+
return enabled;
|
|
304
394
|
try {
|
|
305
395
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
306
396
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
397
|
+
const hasReact = !!(allDeps["react"] ||
|
|
398
|
+
allDeps["next"] ||
|
|
399
|
+
allDeps["@remix-run/react"] ||
|
|
400
|
+
allDeps["@xyflow/react"] ||
|
|
401
|
+
allDeps["preact"]);
|
|
402
|
+
if (hasReact && hasJsxFilesShallow(pkgRoot, readdirSync)) {
|
|
403
|
+
enabled.push(...REACT_TOOLS);
|
|
404
|
+
}
|
|
315
405
|
const hasHono = !!(allDeps["hono"] ||
|
|
316
406
|
allDeps["@hono/zod-openapi"] ||
|
|
317
407
|
allDeps["@hono/node-server"] ||
|
|
318
408
|
allDeps["hono-openapi"] ||
|
|
319
409
|
allDeps["chanfana"]);
|
|
320
|
-
if (hasHono)
|
|
321
|
-
|
|
410
|
+
if (hasHono)
|
|
411
|
+
enabled.push(...HONO_TOOLS);
|
|
412
|
+
// Prisma / Drizzle — schema-driven DB stacks. analyze_prisma_schema
|
|
413
|
+
// works for Prisma; migration_lint (squawk) works for any SQL migration
|
|
414
|
+
// dir, useful for both. We don't condition on @prisma/client because
|
|
415
|
+
// it's runtime-only — the schema work belongs to the `prisma` CLI dep.
|
|
416
|
+
const hasPrismaLike = !!(allDeps["prisma"] ||
|
|
417
|
+
allDeps["@prisma/client"] ||
|
|
418
|
+
allDeps["drizzle-kit"] ||
|
|
419
|
+
allDeps["drizzle-orm"]);
|
|
420
|
+
if (hasPrismaLike)
|
|
421
|
+
enabled.push(...PRISMA_TOOLS);
|
|
422
|
+
// npm/yarn/pnpm workspaces field — content-based monorepo signal.
|
|
423
|
+
// Complements the file-based signals (pnpm-workspace.yaml, lerna.json,
|
|
424
|
+
// nx.json, turbo.json) so plain `"workspaces": [...]` setups also fire.
|
|
425
|
+
const hasWorkspaces = Array.isArray(pkg.workspaces) ||
|
|
426
|
+
(pkg.workspaces && typeof pkg.workspaces === "object" &&
|
|
427
|
+
Array.isArray(pkg.workspaces.packages));
|
|
428
|
+
if (hasWorkspaces)
|
|
429
|
+
enabled.push(...MONOREPO_TOOLS);
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
/* malformed package.json */
|
|
433
|
+
}
|
|
434
|
+
return enabled;
|
|
435
|
+
};
|
|
436
|
+
// Root-level detection (existing behavior — unchanged for flat repos).
|
|
437
|
+
toEnable.push(...detectFromPackageJson(cwd));
|
|
438
|
+
// Monorepo workspace walk (Task 15). When monorepo detected at cwd, union
|
|
439
|
+
// each workspace's framework signals into the auto-load set. Hard cap at 50
|
|
440
|
+
// workspaces to bound startup cost (sync FS reads at module-init time);
|
|
441
|
+
// very large monorepos (>50 packages) fall back to root-only auto-load —
|
|
442
|
+
// discover_tools / describe_tools still work for any framework tool needed
|
|
443
|
+
// at query time.
|
|
444
|
+
if (killSwitchOff) {
|
|
445
|
+
try {
|
|
446
|
+
const { resolveWorkspaces } = await import("./storage/workspace-resolver.js");
|
|
447
|
+
const resolved = await resolveWorkspaces(cwd);
|
|
448
|
+
if (resolved && resolved.workspaces.length > 0 && resolved.workspaces.length <= 50) {
|
|
449
|
+
for (const ws of resolved.workspaces) {
|
|
450
|
+
toEnable.push(...detectFromPackageJson(ws.root));
|
|
451
|
+
}
|
|
322
452
|
}
|
|
323
453
|
}
|
|
324
|
-
catch {
|
|
454
|
+
catch {
|
|
455
|
+
/* monorepo resolver failure is non-fatal; flat-repo behavior preserved */
|
|
456
|
+
}
|
|
325
457
|
}
|
|
326
458
|
return toEnable;
|
|
327
459
|
}
|
|
@@ -527,11 +659,15 @@ const TOOL_DEFINITIONS = [
|
|
|
527
659
|
path: z.string().describe("Absolute path to the folder to index"),
|
|
528
660
|
incremental: zBool().describe("Only re-index changed files"),
|
|
529
661
|
include_paths: z.union([z.array(z.string()), z.string().transform((s) => JSON.parse(s))]).optional().describe("Glob patterns to include. Can be passed as JSON string."),
|
|
662
|
+
max_files: z.number().int().positive().optional().describe("Cap on files indexed. Default 50000 (or CODESIFT_MAX_FILES env). Walker stops at this count and returns partial results — protects against OOM on huge repos. Use include_paths to scope instead of raising this for large vendored trees."),
|
|
663
|
+
watch: zBool().describe("Whether to set up a chokidar file watcher for incremental updates after indexing. Default true. Pass false for bulk/CI indexing scenarios — file watchers consume system file descriptors (1+ per repo on macOS FSEvents); indexing many repos with watchers active can exhaust the system file table (ENFILE)."),
|
|
530
664
|
})),
|
|
531
665
|
handler: async (args) => {
|
|
532
666
|
const result = await indexFolder(args.path, {
|
|
533
667
|
incremental: args.incremental,
|
|
534
668
|
include_paths: args.include_paths,
|
|
669
|
+
max_files: args.max_files,
|
|
670
|
+
watch: args.watch,
|
|
535
671
|
});
|
|
536
672
|
// Auto-enable framework tools based on indexed path (not CWD)
|
|
537
673
|
try {
|
|
@@ -697,15 +833,40 @@ const TOOL_DEFINITIONS = [
|
|
|
697
833
|
auto_group: zBool().describe("Auto group_by_file when >50 matches."),
|
|
698
834
|
ranked: z.boolean().optional().describe("Classify hits by containing symbol and rank by centrality"),
|
|
699
835
|
})),
|
|
700
|
-
handler: (args) =>
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
836
|
+
handler: async (args) => {
|
|
837
|
+
const result = await searchText(args.repo, args.query, {
|
|
838
|
+
regex: args.regex,
|
|
839
|
+
context_lines: args.context_lines,
|
|
840
|
+
file_pattern: args.file_pattern,
|
|
841
|
+
max_results: args.max_results,
|
|
842
|
+
group_by_file: args.group_by_file,
|
|
843
|
+
auto_group: args.auto_group,
|
|
844
|
+
ranked: args.ranked,
|
|
845
|
+
});
|
|
846
|
+
// Zero-result hint: 41% of search_text calls return nothing in telemetry.
|
|
847
|
+
// Suggest the most likely fix based on query shape so the agent doesn't
|
|
848
|
+
// burn 2-3 follow-up turns guessing.
|
|
849
|
+
const isEmpty = (Array.isArray(result) && result.length === 0)
|
|
850
|
+
|| (typeof result === "string" && result.length === 0);
|
|
851
|
+
if (isEmpty) {
|
|
852
|
+
const q = args.query;
|
|
853
|
+
const fp = args.file_pattern;
|
|
854
|
+
const looksLikeSymbol = /::|->|\.[a-z][a-zA-Z0-9_]*\(/.test(q)
|
|
855
|
+
|| /^(class|function|def|fn|interface|type)\s+\w/.test(q)
|
|
856
|
+
|| (/^[A-Z][a-zA-Z0-9_]+$|^[a-z][a-zA-Z0-9_]+$/.test(q.trim()) && !q.includes(" "));
|
|
857
|
+
const hints = ["No matches."];
|
|
858
|
+
if (looksLikeSymbol)
|
|
859
|
+
hints.push("Query looks like a symbol — try search_symbols(query=...) instead.");
|
|
860
|
+
if (fp)
|
|
861
|
+
hints.push(`Try without file_pattern="${fp}" to widen scope.`);
|
|
862
|
+
if (args.regex === true)
|
|
863
|
+
hints.push("Try regex=false (literal) — escapes may be off.");
|
|
864
|
+
if (!fp && !looksLikeSymbol)
|
|
865
|
+
hints.push("Try a shorter substring, or add file_pattern= to scope.");
|
|
866
|
+
return { matches: [], hint: hints.join(" ") };
|
|
867
|
+
}
|
|
868
|
+
return result;
|
|
869
|
+
},
|
|
709
870
|
},
|
|
710
871
|
// --- Outline ---
|
|
711
872
|
{
|
|
@@ -793,10 +954,19 @@ const TOOL_DEFINITIONS = [
|
|
|
793
954
|
const opts = {};
|
|
794
955
|
if (args.include_related != null)
|
|
795
956
|
opts.include_related = args.include_related;
|
|
796
|
-
const
|
|
957
|
+
const symbolId = args.symbol_id;
|
|
958
|
+
const result = await getSymbol(args.repo, symbolId, opts);
|
|
797
959
|
if (!result) {
|
|
960
|
+
// Telemetry: 24% of get_symbol calls return null (hallucinated IDs).
|
|
961
|
+
// Suggest closest matches by name so the agent doesn't burn turns guessing.
|
|
962
|
+
const { findSimilarSymbols } = await import("./tools/symbol-tools.js");
|
|
963
|
+
const similar = await findSimilarSymbols(args.repo, symbolId, 3);
|
|
964
|
+
if (similar.length > 0) {
|
|
965
|
+
const suggestions = similar.map((s) => ` ${s.id} (${s.kind} ${s.name} @ ${s.file}:${s.start_line})`).join("\n");
|
|
966
|
+
return `Symbol "${symbolId}" not found. Did you mean:\n${suggestions}`;
|
|
967
|
+
}
|
|
798
968
|
const hint = await checkTextStubHint(args.repo, "get_symbol", true);
|
|
799
|
-
return hint ??
|
|
969
|
+
return hint ?? `Symbol "${symbolId}" not found. Use search_symbols(query=...) to discover available IDs.`;
|
|
800
970
|
}
|
|
801
971
|
let text = await formatSymbolCompact(result.symbol);
|
|
802
972
|
if (result.related && result.related.length > 0) {
|
|
@@ -818,10 +988,31 @@ const TOOL_DEFINITIONS = [
|
|
|
818
988
|
]).describe("Array of symbol identifiers. Can be passed as JSON string."),
|
|
819
989
|
})),
|
|
820
990
|
handler: async (args) => {
|
|
821
|
-
const
|
|
991
|
+
const ids = args.symbol_ids;
|
|
992
|
+
const syms = await getSymbols(args.repo, ids);
|
|
822
993
|
const output = await formatSymbolsCompact(syms);
|
|
994
|
+
// Surface fuzzy suggestions for missing IDs (telemetry: 26% zero rate).
|
|
995
|
+
let suggestions = "";
|
|
996
|
+
if (syms.length < ids.length) {
|
|
997
|
+
const foundIds = new Set(syms.map((s) => s.id));
|
|
998
|
+
const missing = ids.filter((id) => !foundIds.has(id));
|
|
999
|
+
if (missing.length > 0) {
|
|
1000
|
+
const { findSimilarSymbols } = await import("./tools/symbol-tools.js");
|
|
1001
|
+
const lines = [];
|
|
1002
|
+
for (const m of missing.slice(0, 5)) {
|
|
1003
|
+
const sims = await findSimilarSymbols(args.repo, m, 2);
|
|
1004
|
+
if (sims.length > 0) {
|
|
1005
|
+
lines.push(` ${m} → ${sims.map((s) => s.id).join(", ")}`);
|
|
1006
|
+
}
|
|
1007
|
+
else {
|
|
1008
|
+
lines.push(` ${m} → no similar symbols`);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
suggestions = `\n\n--- not found (${missing.length}) — suggestions ---\n${lines.join("\n")}`;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
823
1014
|
const hint = await checkTextStubHint(args.repo, "get_symbols", syms.length === 0);
|
|
824
|
-
return hint ? hint + output : output;
|
|
1015
|
+
return (hint ? hint + output : output) + suggestions;
|
|
825
1016
|
},
|
|
826
1017
|
},
|
|
827
1018
|
{
|
|
@@ -1584,6 +1775,9 @@ const TOOL_DEFINITIONS = [
|
|
|
1584
1775
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1585
1776
|
focus: z.string().optional().describe("Scope to directory (e.g., 'src/tools')"),
|
|
1586
1777
|
output_dir: z.string().optional().describe("Output directory (default: {repo_root}/.codesift/wiki)"),
|
|
1778
|
+
journal_mode: z.enum(["skip", "refresh-overview", "append", "full"]).optional().default("skip").describe("Journal integration mode (default: skip)"),
|
|
1779
|
+
journal_since_ref: z.string().optional().describe("git-relative ref for journal_mode=append (e.g., '2 weeks ago' or ISO date)"),
|
|
1780
|
+
journal_bulk_fill: z.boolean().optional().describe("Bulk-fill all phases when journal_mode=full"),
|
|
1587
1781
|
})),
|
|
1588
1782
|
handler: async (args) => {
|
|
1589
1783
|
const opts = {};
|
|
@@ -1591,10 +1785,39 @@ const TOOL_DEFINITIONS = [
|
|
|
1591
1785
|
opts.focus = args.focus;
|
|
1592
1786
|
if (args.output_dir !== undefined)
|
|
1593
1787
|
opts.output_dir = args.output_dir;
|
|
1788
|
+
if (args.journal_mode !== undefined)
|
|
1789
|
+
opts.journal_mode = args.journal_mode;
|
|
1790
|
+
if (args.journal_since_ref !== undefined)
|
|
1791
|
+
opts.journal_since_ref = args.journal_since_ref;
|
|
1792
|
+
if (args.journal_bulk_fill !== undefined)
|
|
1793
|
+
opts.journal_bulk_fill = args.journal_bulk_fill;
|
|
1594
1794
|
const result = await generateWiki(args.repo, opts);
|
|
1595
1795
|
return JSON.stringify(result, null, 2);
|
|
1596
1796
|
},
|
|
1597
1797
|
},
|
|
1798
|
+
{
|
|
1799
|
+
name: "journal_append",
|
|
1800
|
+
category: "reporting",
|
|
1801
|
+
searchHint: "journal append phases git commits since wiki journal",
|
|
1802
|
+
description: "Append new journal phases for commits since the given git ref. Dispatches to runJournalAppend.",
|
|
1803
|
+
schema: lazySchema(() => ({
|
|
1804
|
+
since: z.string().describe("git-relative string like '2 weeks ago' or ISO date"),
|
|
1805
|
+
max_cost_usd: z.number().optional().default(2.0).describe("Maximum LLM cost cap in USD (default: 2.0)"),
|
|
1806
|
+
dry_run: z.boolean().optional().default(false).describe("Plan phases without writing files (default: false)"),
|
|
1807
|
+
})),
|
|
1808
|
+
handler: async (args) => {
|
|
1809
|
+
const { runJournalAppend } = await import("./tools/journal-generator.js");
|
|
1810
|
+
const opts = {
|
|
1811
|
+
cwd: process.cwd(),
|
|
1812
|
+
outputDir: ".codesift/wiki",
|
|
1813
|
+
since: args.since,
|
|
1814
|
+
};
|
|
1815
|
+
if (args.dry_run !== undefined)
|
|
1816
|
+
opts.dryRun = args.dry_run;
|
|
1817
|
+
const r = await runJournalAppend(opts);
|
|
1818
|
+
return JSON.stringify(r, null, 2);
|
|
1819
|
+
},
|
|
1820
|
+
},
|
|
1598
1821
|
// --- Conversations ---
|
|
1599
1822
|
{
|
|
1600
1823
|
name: "index_conversations",
|
|
@@ -1651,6 +1874,85 @@ const TOOL_DEFINITIONS = [
|
|
|
1651
1874
|
return formatConversations(result);
|
|
1652
1875
|
},
|
|
1653
1876
|
},
|
|
1877
|
+
// --- Monorepo Workspaces (Tasks 8-11 of monorepo workspace intelligence plan) ---
|
|
1878
|
+
{
|
|
1879
|
+
name: "list_workspaces",
|
|
1880
|
+
category: "analysis",
|
|
1881
|
+
searchHint: "monorepo workspace list packages turbo pnpm yarn npm",
|
|
1882
|
+
description: "List workspace packages for a JS/TS monorepo (Turbo / pnpm / yarn / npm / Nx). Returns shape-stable empty result on flat repos.",
|
|
1883
|
+
schema: lazySchema(() => ({
|
|
1884
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1885
|
+
})),
|
|
1886
|
+
handler: async (args) => {
|
|
1887
|
+
const { listWorkspacesHandler } = await import("./tools/workspace-tools.js");
|
|
1888
|
+
return listWorkspacesHandler(args.repo ? { repo: args.repo } : {});
|
|
1889
|
+
},
|
|
1890
|
+
},
|
|
1891
|
+
{
|
|
1892
|
+
name: "workspace_graph",
|
|
1893
|
+
category: "analysis",
|
|
1894
|
+
searchHint: "monorepo workspace dependency graph turbo nx mermaid dot",
|
|
1895
|
+
description: "Build the workspace-to-workspace dependency DAG of a monorepo. Output formats: json (default), mermaid, dot.",
|
|
1896
|
+
schema: lazySchema(() => ({
|
|
1897
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1898
|
+
format: z.enum(["json", "mermaid", "dot"]).optional().describe("Output format (default: json)"),
|
|
1899
|
+
})),
|
|
1900
|
+
handler: async (args) => {
|
|
1901
|
+
const { workspaceGraphHandler } = await import("./tools/workspace-tools.js");
|
|
1902
|
+
const opts = {};
|
|
1903
|
+
if (args.repo)
|
|
1904
|
+
opts.repo = args.repo;
|
|
1905
|
+
if (args.format)
|
|
1906
|
+
opts.format = args.format;
|
|
1907
|
+
return workspaceGraphHandler(opts);
|
|
1908
|
+
},
|
|
1909
|
+
},
|
|
1910
|
+
{
|
|
1911
|
+
name: "affected_workspaces",
|
|
1912
|
+
category: "analysis",
|
|
1913
|
+
searchHint: "monorepo affected workspaces git diff impact transitive turbo nx",
|
|
1914
|
+
description: "Compute affected workspaces for a git diff. File changes -> containing workspace -> reverse-dep walk. Lockfile-only commits surface separately and never fan out.",
|
|
1915
|
+
schema: lazySchema(() => ({
|
|
1916
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1917
|
+
since: z.string().describe("Git ref to diff against (e.g. HEAD~1, main, <sha>)"),
|
|
1918
|
+
include_transitive: zBool().describe("Include transitive reverse-deps (default: true)"),
|
|
1919
|
+
})),
|
|
1920
|
+
handler: async (args) => {
|
|
1921
|
+
const { affectedWorkspacesHandler } = await import("./tools/workspace-tools.js");
|
|
1922
|
+
const opts = {
|
|
1923
|
+
since: args.since,
|
|
1924
|
+
};
|
|
1925
|
+
if (args.repo)
|
|
1926
|
+
opts.repo = args.repo;
|
|
1927
|
+
if (args.include_transitive !== undefined)
|
|
1928
|
+
opts.include_transitive = args.include_transitive;
|
|
1929
|
+
return affectedWorkspacesHandler(opts);
|
|
1930
|
+
},
|
|
1931
|
+
},
|
|
1932
|
+
{
|
|
1933
|
+
name: "workspace_boundaries",
|
|
1934
|
+
category: "analysis",
|
|
1935
|
+
searchHint: "monorepo boundary rules workspace import violations enforce",
|
|
1936
|
+
description: "Enforce workspace-level import boundaries. Walks ALL cross-workspace import edges (relative + bare/tsconfig-alias) and reports rule violations.",
|
|
1937
|
+
schema: lazySchema(() => ({
|
|
1938
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1939
|
+
rules: z
|
|
1940
|
+
.array(z.object({
|
|
1941
|
+
from_workspace: z.string().describe("Workspace name OR glob (e.g. 'apps/*')"),
|
|
1942
|
+
cannot_import_workspaces: z.array(z.string()).describe("Names, globs, or negation entries"),
|
|
1943
|
+
}))
|
|
1944
|
+
.describe("Workspace boundary rules"),
|
|
1945
|
+
})),
|
|
1946
|
+
handler: async (args) => {
|
|
1947
|
+
const { workspaceBoundariesHandler } = await import("./tools/workspace-tools.js");
|
|
1948
|
+
const opts = {
|
|
1949
|
+
rules: args.rules,
|
|
1950
|
+
};
|
|
1951
|
+
if (args.repo)
|
|
1952
|
+
opts.repo = args.repo;
|
|
1953
|
+
return workspaceBoundariesHandler(opts);
|
|
1954
|
+
},
|
|
1955
|
+
},
|
|
1654
1956
|
// --- Security ---
|
|
1655
1957
|
{
|
|
1656
1958
|
name: "scan_secrets",
|
|
@@ -2582,6 +2884,16 @@ const TOOL_DEFINITIONS = [
|
|
|
2582
2884
|
handler: async (args) => {
|
|
2583
2885
|
const result = await indexStatus(args.repo);
|
|
2584
2886
|
if (!result.indexed) {
|
|
2887
|
+
// Stale: index file exists but extractor_version drifted. Distinct
|
|
2888
|
+
// from "never indexed" — agents seeing "STALE" know that re-running
|
|
2889
|
+
// index_folder will fix it without wondering whether earlier indexing
|
|
2890
|
+
// attempts silently failed.
|
|
2891
|
+
if (result.stale) {
|
|
2892
|
+
return (`index_status: STALE — extractor_version_mismatch ` +
|
|
2893
|
+
`(${result.stale.language}: indexed at ${result.stale.actual_version}, ` +
|
|
2894
|
+
`current ${result.stale.expected_version}). ` +
|
|
2895
|
+
`Run index_folder to refresh.`);
|
|
2896
|
+
}
|
|
2585
2897
|
// If no repo specified, list available repos so the agent can pick one
|
|
2586
2898
|
if (!args.repo) {
|
|
2587
2899
|
const { listAllRepos } = await import("./tools/index-tools.js");
|
|
@@ -2753,15 +3065,28 @@ const TOOL_DEFINITIONS = [
|
|
|
2753
3065
|
{
|
|
2754
3066
|
name: "nest_audit",
|
|
2755
3067
|
category: "nestjs",
|
|
2756
|
-
searchHint: "nestjs audit analysis comprehensive module di guard route lifecycle pattern graphql websocket schedule typeorm microservice hook onModuleInit onApplicationBootstrap shutdown dependency graph circular import boundary injection provider constructor inject cycle interceptor pipe filter middleware chain security endpoint api map inventory list all params resolver query mutation subscription apollo gateway subscribemessage socketio realtime event cron interval timeout scheduled job task onevent listener entity relation onetomany manytoone database schema messagepattern eventpattern kafka rabbitmq nats transport request pipeline handler execution flow visualization bull bullmq queue processor process background worker scope transient singleton performance escalation swagger openapi documentation apiproperty apioperation apiresponse contract extract",
|
|
2757
|
-
description: "One-call NestJS architecture audit: modules, DI, guards, routes, lifecycle, patterns, GraphQL, WebSocket, schedule, TypeORM, microservices.",
|
|
3068
|
+
searchHint: "nestjs audit analysis comprehensive module di guard route lifecycle pattern graphql websocket schedule typeorm microservice hook onModuleInit onApplicationBootstrap shutdown dependency graph circular import boundary injection provider constructor inject cycle interceptor pipe filter middleware chain security endpoint api map inventory list all params resolver query mutation subscription apollo gateway subscribemessage socketio realtime event cron interval timeout scheduled job task onevent listener entity relation onetomany manytoone database schema messagepattern eventpattern kafka rabbitmq nats transport request pipeline handler execution flow visualization bull bullmq queue processor process background worker scope transient singleton performance escalation swagger openapi documentation apiproperty apioperation apiresponse contract extract workspace monorepo",
|
|
3069
|
+
description: "One-call NestJS architecture audit: modules, DI, guards, routes, lifecycle, patterns, GraphQL, WebSocket, schedule, TypeORM, microservices. Pass workspace=<name|path> in monorepos to scope to a single workspace.",
|
|
2758
3070
|
schema: lazySchema(() => ({
|
|
2759
3071
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3072
|
+
workspace: z.string().optional().describe("Monorepo workspace name or path. Scopes the audit to that workspace's files."),
|
|
2760
3073
|
checks: z.string().optional().describe("Comma-separated checks (default: all). Options: modules,routes,di,guards,lifecycle,patterns,graphql,websocket,schedule,typeorm,microservice"),
|
|
2761
3074
|
})),
|
|
2762
3075
|
handler: async (args) => {
|
|
3076
|
+
const { resolveWorkspaceScope } = await import("./tools/workspace-scope-helper.js");
|
|
2763
3077
|
const checks = args.checks?.split(",").map((s) => s.trim()).filter(Boolean);
|
|
2764
|
-
|
|
3078
|
+
const scope = await resolveWorkspaceScope(args.repo ?? "", args.workspace, "nestjs");
|
|
3079
|
+
if ("error" in scope) {
|
|
3080
|
+
return { error: scope.error, input: scope.input, available: scope.available };
|
|
3081
|
+
}
|
|
3082
|
+
const opts = {};
|
|
3083
|
+
if (checks)
|
|
3084
|
+
opts.checks = checks;
|
|
3085
|
+
if (scope.rootPaths.length > 0) {
|
|
3086
|
+
// Pass first matched workspace path through the existing file_pattern-style hook
|
|
3087
|
+
opts.file_pattern = `${scope.rootPaths[0]}/**`;
|
|
3088
|
+
}
|
|
3089
|
+
return nestAudit(args.repo ?? "", opts);
|
|
2765
3090
|
},
|
|
2766
3091
|
},
|
|
2767
3092
|
// --- Agent config audit ---
|
|
@@ -3100,18 +3425,27 @@ const TOOL_DEFINITIONS = [
|
|
|
3100
3425
|
{
|
|
3101
3426
|
name: "astro_audit",
|
|
3102
3427
|
category: "analysis",
|
|
3103
|
-
searchHint: "astro meta audit full health check score gates recommendations islands hydration routes config actions content migration patterns",
|
|
3104
|
-
description: "One-call Astro project health check: runs all 7 Astro tools + 13 Astro patterns in parallel, returns unified {score, gates, sections, recommendations}.
|
|
3428
|
+
searchHint: "astro meta audit full health check score gates recommendations islands hydration routes config actions content migration patterns workspace monorepo",
|
|
3429
|
+
description: "One-call Astro project health check: runs all 7 Astro tools + 13 Astro patterns in parallel, returns unified {score, gates, sections, recommendations}. Pass workspace=<name|path> in monorepos to scope to a single workspace.",
|
|
3105
3430
|
schema: lazySchema(() => ({
|
|
3106
3431
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3432
|
+
workspace: z.string().optional().describe("Monorepo workspace name or path. Scopes the audit to that workspace."),
|
|
3107
3433
|
skip: z.array(z.string()).optional().describe("Sections to skip: config, hydration, routes, actions, content, migration, patterns"),
|
|
3108
3434
|
})),
|
|
3109
3435
|
handler: async (args) => {
|
|
3436
|
+
const { resolveWorkspaceScope } = await import("./tools/workspace-scope-helper.js");
|
|
3437
|
+
const scope = await resolveWorkspaceScope(args.repo ?? "", args.workspace, "astro");
|
|
3438
|
+
if ("error" in scope) {
|
|
3439
|
+
return { error: scope.error, input: scope.input, available: scope.available };
|
|
3440
|
+
}
|
|
3110
3441
|
const opts = {};
|
|
3111
3442
|
if (args.repo != null)
|
|
3112
3443
|
opts.repo = args.repo;
|
|
3113
3444
|
if (args.skip != null)
|
|
3114
3445
|
opts.skip = args.skip;
|
|
3446
|
+
if (scope.rootPaths.length > 0) {
|
|
3447
|
+
opts.file_pattern = `${scope.rootPaths[0]}/**`;
|
|
3448
|
+
}
|
|
3115
3449
|
return await astroAudit(opts);
|
|
3116
3450
|
},
|
|
3117
3451
|
},
|
|
@@ -3141,16 +3475,29 @@ const TOOL_DEFINITIONS = [
|
|
|
3141
3475
|
{
|
|
3142
3476
|
name: "analyze_hono_app",
|
|
3143
3477
|
category: "analysis",
|
|
3144
|
-
searchHint: "hono overview analyze app routes middleware runtime env bindings rpc",
|
|
3145
|
-
description: "Complete Hono application overview: routes grouped by method/scope, middleware map, context vars, OpenAPI status, RPC exports (flags Issue #3869 slow pattern), runtime, env bindings.
|
|
3478
|
+
searchHint: "hono overview analyze app routes middleware runtime env bindings rpc workspace monorepo",
|
|
3479
|
+
description: "Complete Hono application overview: routes grouped by method/scope, middleware map, context vars, OpenAPI status, RPC exports (flags Issue #3869 slow pattern), runtime, env bindings. Pass workspace=<name|path> in monorepos to scope to a single workspace.",
|
|
3146
3480
|
schema: lazySchema(() => ({
|
|
3147
3481
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3148
3482
|
entry_file: z.string().optional().describe("Hono entry file (auto-detected if omitted)"),
|
|
3483
|
+
workspace: z.string().optional().describe("Monorepo workspace name or path (e.g. '@org/api' or 'apps/api'). Scopes Hono entry resolution to that workspace."),
|
|
3149
3484
|
force_refresh: z.boolean().optional().describe("Clear cache and rebuild"),
|
|
3150
3485
|
})),
|
|
3151
3486
|
handler: async (args) => {
|
|
3152
3487
|
const { analyzeHonoApp } = await import("./tools/hono-analyze-app.js");
|
|
3153
|
-
|
|
3488
|
+
const { resolveWorkspaceScope } = await import("./tools/workspace-scope-helper.js");
|
|
3489
|
+
const repo = args.repo;
|
|
3490
|
+
const scope = await resolveWorkspaceScope(repo, args.workspace, "hono");
|
|
3491
|
+
if ("error" in scope) {
|
|
3492
|
+
return { error: scope.error, input: scope.input, available: scope.available };
|
|
3493
|
+
}
|
|
3494
|
+
// If workspace scoping resolved to a path, prefer it as entry_file root hint.
|
|
3495
|
+
let entry = args.entry_file;
|
|
3496
|
+
if (!entry && scope.rootPaths.length === 1) {
|
|
3497
|
+
// Hono's entry resolver searches src/index.ts under the path provided
|
|
3498
|
+
entry = scope.rootPaths[0];
|
|
3499
|
+
}
|
|
3500
|
+
return await analyzeHonoApp(repo, entry, args.force_refresh);
|
|
3154
3501
|
},
|
|
3155
3502
|
},
|
|
3156
3503
|
{
|