@cruxy/cli 0.28.1 → 0.28.2

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.
@@ -51,9 +51,9 @@ async function driveLoop(args, renderer, routed) {
51
51
  platform: process.platform,
52
52
  date: new Date().toISOString().slice(0, 10),
53
53
  model: `${config.model.provider}/${config.model.model}`,
54
- tools: registry
55
- .list()
56
- .map((tool) => ({ name: tool.name, description: tool.description })),
54
+ // Names only: each tool's description/parameters reach the model as its wire
55
+ // schema, so the prompt's Tools section lists just the roster (see prompts.ts).
56
+ tools: registry.list().map((tool) => ({ name: tool.name })),
57
57
  git: args.git ?? null,
58
58
  projectInstructions: args.projectInstructions ?? null,
59
59
  recalledMemory: args.recalledMemory ?? null,
@@ -8,7 +8,6 @@
8
8
  */
9
9
  export interface ToolSummary {
10
10
  name: string;
11
- description: string;
12
11
  }
13
12
  export interface PromptContext {
14
13
  /** Absolute working directory the agent is rooted in. */
@@ -74,8 +74,13 @@ function renderTools(tools) {
74
74
  if (tools.length === 0) {
75
75
  return "## Tools\nNo tools are available this session; respond in text only.";
76
76
  }
77
- const list = tools.map((t) => `- ${t.name}: ${t.description}`).join("\n");
78
- return `## Tools\nYou have these tools available. Use them — don't ask the user to run things you can run yourself:\n${list}`;
77
+ // Names only. Each tool's description and parameter schema already reach the
78
+ // model as its wire spec (ToolRegistry.specs the provider's tools field), so
79
+ // repeating the descriptions here just duplicated them on every first turn (and
80
+ // every turn on uncached providers). The roster and the "use them" nudge below
81
+ // are the parts the wire schema does NOT carry.
82
+ const names = tools.map((t) => t.name).join(", ");
83
+ return `## Tools\nYou have these tools available (each one's parameters and description are in its schema). Use them — don't ask the user to run things you can run yourself:\n${names}`;
79
84
  }
80
85
  /** Assemble the full system prompt for a session. */
81
86
  export function buildSystemPrompt(ctx) {
@@ -3,7 +3,22 @@ import { z } from "zod";
3
3
  import { contextWorkspace, isEscapingPattern, labelPath, resolveReadRoots, } from "./paths.js";
4
4
  /** Cap on returned paths — beyond this we truncate with a notice. */
5
5
  const MAX_RESULTS = 200;
6
- const DEFAULT_IGNORE = ["**/node_modules/**", "**/.git/**"];
6
+ // Dependencies, VCS internals, and conventional compiled-output dirs. The last
7
+ // group keeps gitignored build artifacts (e.g. dist/mcp.js and its .d.ts) from
8
+ // crowding out the real source file a pattern like `**/*mcp*` is looking for.
9
+ // These are glob patterns, not gitignore rules: tinyglobby's `ignore` matches
10
+ // globs, so honoring an actual .gitignore would mean reusing the indexer's
11
+ // gitignore matcher per root — out of proportion for these ad-hoc tools, and the
12
+ // indexed search path already honors .gitignore.
13
+ const DEFAULT_IGNORE = [
14
+ "**/node_modules/**",
15
+ "**/.git/**",
16
+ "**/dist/**",
17
+ "**/build/**",
18
+ "**/coverage/**",
19
+ "**/.next/**",
20
+ "**/out/**",
21
+ ];
7
22
  /**
8
23
  * Find files by glob pattern within the workspace. Read-only — no approval.
9
24
  * The pattern is constrained to a root (no absolute or `..` patterns) so glob
@@ -17,7 +32,7 @@ const DEFAULT_IGNORE = ["**/node_modules/**", "**/.git/**"];
17
32
  */
18
33
  export const globTool = {
19
34
  name: "glob",
20
- description: "Find files by glob pattern (e.g. 'src/**/*.ts') within the project, ignoring node_modules and .git. Returns paths relative to the project root.",
35
+ description: "Find files by glob pattern (e.g. 'src/**/*.ts') within the project, ignoring node_modules, .git, and common build-output dirs (dist, build, coverage, .next, out). Returns paths relative to the project root.",
21
36
  parameters: z.object({
22
37
  pattern: z
23
38
  .string()
@@ -28,7 +28,8 @@ declare const parameters: z.ZodObject<{
28
28
  * run_command (which is platform-dependent and routes through the approval gate).
29
29
  *
30
30
  * Files are enumerated with the same glob mechanism as the `glob` tool (so
31
- * node_modules and .git are always ignored), binary files are skipped, and the
31
+ * node_modules, .git, and build-output dirs are always ignored), binary files
32
+ * are skipped, and the
32
33
  * search is bounded by the same root boundary as every file tool.
33
34
  *
34
35
  * Multi-repo (C.26, Funnel B): with more than one declared root and no root-
@@ -10,7 +10,18 @@ const DEFAULT_MAX_RESULTS = 100;
10
10
  const MAX_LINE_LENGTH = 200;
11
11
  /** Bytes sniffed for a NUL to decide a file is binary and skip it. */
12
12
  const BINARY_SNIFF_BYTES = 8 * 1024;
13
- const DEFAULT_IGNORE = ["**/node_modules/**", "**/.git/**"];
13
+ // Dependencies, VCS internals, and conventional compiled-output dirs — kept in
14
+ // sync with glob's DEFAULT_IGNORE so both file tools skip build artifacts (see
15
+ // glob.ts for why these are static globs rather than a parsed .gitignore).
16
+ const DEFAULT_IGNORE = [
17
+ "**/node_modules/**",
18
+ "**/.git/**",
19
+ "**/dist/**",
20
+ "**/build/**",
21
+ "**/coverage/**",
22
+ "**/.next/**",
23
+ "**/out/**",
24
+ ];
14
25
  const parameters = z.object({
15
26
  pattern: z
16
27
  .string()
@@ -49,7 +60,8 @@ function firstSegmentIsRoot(ws, p) {
49
60
  * run_command (which is platform-dependent and routes through the approval gate).
50
61
  *
51
62
  * Files are enumerated with the same glob mechanism as the `glob` tool (so
52
- * node_modules and .git are always ignored), binary files are skipped, and the
63
+ * node_modules, .git, and build-output dirs are always ignored), binary files
64
+ * are skipped, and the
53
65
  * search is bounded by the same root boundary as every file tool.
54
66
  *
55
67
  * Multi-repo (C.26, Funnel B): with more than one declared root and no root-
@@ -61,7 +73,7 @@ function firstSegmentIsRoot(ws, p) {
61
73
  */
62
74
  export const grepFilesTool = {
63
75
  name: "grep_files",
64
- description: "Search file CONTENTS for a regular expression within the project (vs `glob`, which matches file NAMES). Returns matches as 'path:line: text', ignoring node_modules and .git. Read-only and requires no approval — prefer it over shelling out to grep/rg/find via run_command.",
76
+ description: "Search file CONTENTS for a regular expression within the project (vs `glob`, which matches file NAMES). Returns matches as 'path:line: text', ignoring node_modules, .git, and common build-output dirs (dist, build, coverage, .next, out). Read-only and requires no approval — prefer it over shelling out to grep/rg/find via run_command.",
65
77
  parameters,
66
78
  async execute(input, ctx) {
67
79
  // Compile the regex up front; an invalid pattern is a clean failure, not a throw.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cruxy/cli",
3
- "version": "0.28.1",
3
+ "version": "0.28.2",
4
4
  "description": "an agentic coding CLI",
5
5
  "type": "module",
6
6
  "bin": {