pi-lean-ctx 3.6.0 → 3.6.1

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 CHANGED
@@ -2,14 +2,25 @@
2
2
 
3
3
  [Pi Coding Agent](https://github.com/badlogic/pi-mono) extension that provides `ctx_`-prefixed tools backed by [lean-ctx](https://leanctx.com) for **60–90% token savings**.
4
4
 
5
- - **Default**: CLI-only (no MCP required)
5
+ - **Default**: CLI-only, additive mode (no MCP required, Pi builtins preserved)
6
6
  - **Optional**: enable MCP tools (`LEAN_CTX_PI_ENABLE_MCP=1`) or run `lean-ctx init --agent pi --mode mcp`
7
+ - **Optional**: replace mode (`LEAN_CTX_PI_MODE=replace`) disables Pi builtins
8
+
9
+ ## Tool Mode
10
+
11
+ By default, pi-lean-ctx runs in **additive mode**: Pi's built-in tools (`read`, `bash`, `ls`, `find`, `grep`) remain available alongside the `ctx_*` tools. Agents can use either set.
12
+
13
+ To switch to **replace mode** (disables Pi builtins, only `ctx_*` tools available):
14
+
15
+ ```bash
16
+ export LEAN_CTX_PI_MODE=replace
17
+ ```
7
18
 
8
19
  ## What it does
9
20
 
10
21
  ### ctx_ Tools (CLI-backed)
11
22
 
12
- Replaces Pi's built-in `read`, `bash`, `ls`, `find`, `grep` with `ctx_`-prefixed versions:
23
+ Adds `ctx_`-prefixed tools alongside Pi's builtins (or replaces them in `replace` mode):
13
24
 
14
25
  | Tool | Replaces | Compression |
15
26
  |------|----------|-------------|
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import {
3
3
  createBashToolDefinition,
4
4
  createReadToolDefinition,
@@ -6,8 +6,8 @@ import {
6
6
  getLanguageFromPath,
7
7
  highlightCode,
8
8
  truncateHead,
9
- } from "@mariozechner/pi-coding-agent";
10
- import { Text } from "@mariozechner/pi-tui";
9
+ } from "@earendil-works/pi-coding-agent";
10
+ import { Text } from "@earendil-works/pi-tui";
11
11
  import { Type } from "@sinclair/typebox";
12
12
  import { existsSync, readFileSync } from "node:fs";
13
13
  import { readFile, stat } from "node:fs/promises";
@@ -35,8 +35,12 @@ const IMAGE_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp"]);
35
35
  const CODE_FULL_READ_MAX_BYTES = 8 * 1024;
36
36
  const CODE_SIGNATURES_MIN_BYTES = 96 * 1024;
37
37
 
38
- // Pi builtins we replace with ctx_ prefixed versions
38
+ // Pi builtins that can be replaced with ctx_ prefixed versions.
39
+ // LEAN_CTX_PI_MODE controls behavior:
40
+ // "additive" (default) — keep Pi builtins, add ctx_* alongside
41
+ // "replace" — disable Pi builtins, only expose ctx_*
39
42
  const DISABLED_BUILTIN_TOOLS = new Set(["read", "bash", "ls", "find", "grep"]);
43
+ const PI_MODE = (process.env.LEAN_CTX_PI_MODE || "additive").toLowerCase();
40
44
  // Max bytes constant for truncation warnings (same as Pi's DEFAULT_MAX_BYTES)
41
45
  const DEFAULT_MAX_BYTES = 8192;
42
46
 
@@ -278,7 +282,7 @@ function isMcpAdapterConfigured(): boolean {
278
282
 
279
283
  async function execLeanCtx(pi: ExtensionAPI, args: string[]) {
280
284
  const bin = resolveBinary();
281
- const result = await pi.exec(bin, args, { env: { ...process.env, LEAN_CTX_COMPRESS: "1" } });
285
+ const result = await pi.exec(bin, args, { env: { ...process.env, LEAN_CTX_COMPRESS: "1", LEAN_CTX_SAVINGS_FOOTER: "always" } });
282
286
  if (result.code !== 0) {
283
287
  const msg = (result.stderr || result.stdout || `lean-ctx failed: ${args.join(" ")}`).trim();
284
288
  throw new Error(msg);
@@ -288,19 +292,22 @@ async function execLeanCtx(pi: ExtensionAPI, args: string[]) {
288
292
 
289
293
  export default async function (pi: ExtensionAPI) {
290
294
  // Defer setActiveTools to session_start — runtime actions aren't available during extension load
291
- // Must run on every session_start since active tools are per-session
292
- pi.on("session_start", () => {
293
- const activeTools = pi.getActiveTools().filter((name) => !DISABLED_BUILTIN_TOOLS.has(name));
294
- pi.setActiveTools(activeTools);
295
- });
295
+ // In "replace" mode, disable Pi builtins and only expose ctx_* tools.
296
+ // In "additive" mode (default), keep Pi builtins alongside ctx_* tools.
297
+ if (PI_MODE === "replace") {
298
+ pi.on("session_start", () => {
299
+ const activeTools = pi.getActiveTools().filter((name) => !DISABLED_BUILTIN_TOOLS.has(name));
300
+ pi.setActiveTools(activeTools);
301
+ });
302
+ }
296
303
 
297
304
  const baseBashTool = createBashToolDefinition(process.cwd(), {
298
305
  spawnHook: ({ command, cwd, env }) => {
299
306
  const bin = resolveBinary();
300
307
  return {
301
- command: `${shellQuote(bin)} -c sh -lc ${shellQuote(command)}`,
308
+ command: `${shellQuote(bin)} -c ${shellQuote(command)}`,
302
309
  cwd,
303
- env: { ...env, LEAN_CTX_COMPRESS: "1" },
310
+ env: { ...env, LEAN_CTX_COMPRESS: "1", LEAN_CTX_SAVINGS_FOOTER: "always" },
304
311
  };
305
312
  },
306
313
  });
@@ -328,6 +335,16 @@ export default async function (pi: ExtensionAPI) {
328
335
  "Use ctx_shell only for commands with side effects: build, test, install, git, run scripts.",
329
336
  ],
330
337
  parameters: bashSchemaWithRaw,
338
+ renderCall(args, theme, context) {
339
+ return baseBashTool.renderCall
340
+ ? baseBashTool.renderCall(args, theme, context)
341
+ : (context.lastComponent ?? new Text("", 0, 0));
342
+ },
343
+ renderResult(result, options, theme, context) {
344
+ return baseBashTool.renderResult
345
+ ? baseBashTool.renderResult(result, options, theme, context)
346
+ : (context.lastComponent ?? new Text("", 0, 0));
347
+ },
331
348
  async execute(toolCallId, params, signal, onUpdate, ctx) {
332
349
  const isRaw = !!params.raw;
333
350
  const toolParams = { command: params.command, timeout: params.timeout };
@@ -525,7 +542,7 @@ export default async function (pi: ExtensionAPI) {
525
542
  searchArgs.push(params.pattern, absolutePath);
526
543
 
527
544
  const bin = resolveBinary();
528
- const result = await pi.exec(bin, ["-c", ...searchArgs], { env: { ...process.env, LEAN_CTX_COMPRESS: "1" } });
545
+ const result = await pi.exec(bin, ["-c", ...searchArgs], { env: { ...process.env, LEAN_CTX_COMPRESS: "1", LEAN_CTX_SAVINGS_FOOTER: "always" } });
529
546
  if (result.code >= 2) {
530
547
  const msg = (result.stderr || result.stdout || `lean-ctx grep failed: ${params.pattern}`).trim();
531
548
  throw new Error(msg);
@@ -1,6 +1,6 @@
1
1
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
2
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
3
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
4
4
  import { Type } from "@sinclair/typebox";
5
5
  import type { McpBridgeRetryState, McpBridgeStatus } from "./types.js";
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-lean-ctx",
3
- "version": "3.6.0",
3
+ "version": "3.6.1",
4
4
  "description": "Pi Coding Agent extension (CLI-first) — routes bash/read/grep/find/ls through lean-ctx CLI for strong token savings. Optional MCP bridge can register advanced tools.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -25,8 +25,8 @@
25
25
  "@modelcontextprotocol/sdk": "^1.29.0"
26
26
  },
27
27
  "peerDependencies": {
28
- "@mariozechner/pi-coding-agent": ">=0.50.0",
29
- "@mariozechner/pi-tui": "*"
28
+ "@earendil-works/pi-coding-agent": ">=0.50.0",
29
+ "@earendil-works/pi-tui": "*"
30
30
  },
31
31
  "pi": {
32
32
  "extensions": [