pi-lean-ctx 3.8.1 → 3.8.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.
@@ -6,6 +6,9 @@ import type {
6
6
  } from "@earendil-works/pi-coding-agent";
7
7
  import {
8
8
  createBashToolDefinition,
9
+ createFindToolDefinition,
10
+ createGrepToolDefinition,
11
+ createLsToolDefinition,
9
12
  createReadToolDefinition,
10
13
  DEFAULT_MAX_LINES,
11
14
  getLanguageFromPath,
@@ -65,20 +68,24 @@ const readSchema = Type.Object({
65
68
  mode: Type.Optional(readModeSchema),
66
69
  });
67
70
 
71
+ // `path` is REQUIRED on ls/find/grep (#395): with an optional path these tools
72
+ // silently fell back to the extension's cwd — an agent working in a different
73
+ // directory got results from the wrong tree and was derailed. Forcing the
74
+ // parameter makes the scope an explicit, visible part of every call.
68
75
  const lsSchema = Type.Object({
69
- path: Type.Optional(Type.String({ description: "Directory to list (default: current directory)" })),
76
+ path: Type.String({ description: "Directory to list. Pass the directory you are working in — there is no cwd fallback." }),
70
77
  limit: Type.Optional(Type.Number({ description: "Maximum number of entries to return (default: 500)" })),
71
78
  });
72
79
 
73
80
  const findSchema = Type.Object({
74
81
  pattern: Type.String({ description: "Glob pattern to match files" }),
75
- path: Type.Optional(Type.String({ description: "Directory to search in (default: current directory)" })),
82
+ path: Type.String({ description: "Directory to search in. Pass the directory you are working in — there is no cwd fallback." }),
76
83
  limit: Type.Optional(Type.Number({ description: "Maximum number of results (default: 1000)" })),
77
84
  });
78
85
 
79
86
  const grepSchema = Type.Object({
80
87
  pattern: Type.String({ description: "Search pattern (regex or literal string)" }),
81
- path: Type.Optional(Type.String({ description: "Directory or file to search (default: current directory)" })),
88
+ path: Type.String({ description: "Directory or file to search. Pass the directory you are working in — there is no cwd fallback." }),
82
89
  glob: Type.Optional(Type.String({ description: "Filter files by glob pattern, e.g. '*.ts'" })),
83
90
  ignoreCase: Type.Optional(Type.Boolean({ description: "Case-insensitive search (default: false)" })),
84
91
  literal: Type.Optional(Type.Boolean({ description: "Treat pattern as literal string (default: false)" })),
@@ -611,15 +618,28 @@ export default async function (pi: ExtensionAPI) {
611
618
  },
612
619
  });
613
620
 
621
+ // Native tool definitions are reused purely for their renderCall: Pi then
622
+ // shows the invocation with its arguments ("grep /pattern/ in dir") instead
623
+ // of a bare tool name, making the searched directory visible at a glance
624
+ // (#395). The args shapes are supersets of the native ones.
625
+ const nativeLsTool = createLsToolDefinition(process.cwd());
626
+ const nativeFindTool = createFindToolDefinition(process.cwd());
627
+ const nativeGrepTool = createGrepToolDefinition(process.cwd());
628
+
614
629
  // ── ctx_ls (replaces ls) ──────────────────────────────────────────────
615
630
  registerTool({
616
631
  name: "ctx_ls",
617
632
  label: "ctx_ls",
618
- description: "List a directory. Prefer over native ls (compact, summarized). Use limit to reduce output size.",
633
+ description: "List a directory. Prefer over native ls (compact, summarized). `path` is required — pass the directory you are working in. Use limit to reduce output size.",
619
634
  promptSnippet: "List directory contents",
620
635
  parameters: lsSchema,
636
+ renderCall(args, theme, context) {
637
+ return nativeLsTool.renderCall
638
+ ? nativeLsTool.renderCall(args, theme, context)
639
+ : (context.lastComponent ?? new Text("", 0, 0));
640
+ },
621
641
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
622
- const requestedPath = normalizePathArg(params.path || ".");
642
+ const requestedPath = normalizePathArg(params.path);
623
643
  const absolutePath = resolve(ctx.cwd, requestedPath);
624
644
  const output = await execLeanCtx(pi, ["ls", absolutePath]);
625
645
  const decorated = withFooter(output, { limit: params.limit, always: true });
@@ -634,11 +654,16 @@ export default async function (pi: ExtensionAPI) {
634
654
  registerTool({
635
655
  name: "ctx_find",
636
656
  label: "ctx_find",
637
- description: "Find files by glob. Prefer over native find/fd (gitignore-aware). Use limit to reduce output size.",
657
+ description: "Find files by glob. Prefer over native find/fd (gitignore-aware). `path` is required — pass the directory you are working in. Use limit to reduce output size.",
638
658
  promptSnippet: "Find files by glob pattern",
639
659
  parameters: findSchema,
660
+ renderCall(args, theme, context) {
661
+ return nativeFindTool.renderCall
662
+ ? nativeFindTool.renderCall(args, theme, context)
663
+ : (context.lastComponent ?? new Text("", 0, 0));
664
+ },
640
665
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
641
- const requestedPath = normalizePathArg(params.path || ".");
666
+ const requestedPath = normalizePathArg(params.path);
642
667
  const absolutePath = resolve(ctx.cwd, requestedPath);
643
668
  const output = await execLeanCtx(pi, ["find", params.pattern, absolutePath]);
644
669
  const decorated = withFooter(output, { limit: params.limit, always: true });
@@ -653,11 +678,16 @@ export default async function (pi: ExtensionAPI) {
653
678
  registerTool({
654
679
  name: "ctx_grep",
655
680
  label: "ctx_grep",
656
- description: "Search code. Prefer over native Grep/ripgrep (compact, ranked). Use limit to cap matches, context for surrounding lines.",
681
+ description: "Search code. Prefer over native Grep/ripgrep (compact, ranked). `path` is required — pass the directory you are working in. Use limit to cap matches, context for surrounding lines.",
657
682
  promptSnippet: "Search file contents for patterns",
658
683
  parameters: grepSchema,
684
+ renderCall(args, theme, context) {
685
+ return nativeGrepTool.renderCall
686
+ ? nativeGrepTool.renderCall(args, theme, context)
687
+ : (context.lastComponent ?? new Text("", 0, 0));
688
+ },
659
689
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
660
- const requestedPath = normalizePathArg(params.path || ".");
690
+ const requestedPath = normalizePathArg(params.path);
661
691
  const absolutePath = resolve(ctx.cwd, requestedPath);
662
692
  const searchArgs = ["rg", "--line-number", "--color=never"];
663
693
  if (params.ignoreCase) searchArgs.push("-i");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-lean-ctx",
3
- "version": "3.8.1",
3
+ "version": "3.8.2",
4
4
  "description": "Pi Coding Agent extension \u2014 routes bash/read/grep/find/ls through lean-ctx for strong token savings. The embedded MCP bridge (on by default) adds a persistent session cache so unchanged re-reads cost ~13 tokens.",
5
5
  "keywords": [
6
6
  "pi-package",