surgent 0.8.0-alpha.0 → 0.10.7

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 (103) hide show
  1. package/bin/build.mjs +53 -0
  2. package/bin/surgent.js +14 -13
  3. package/dist/optimizer/README.md +12 -4
  4. package/dist/optimizer/index.js +523 -1024
  5. package/dist/optimizer/index.js.map +4 -4
  6. package/dist/optimizer/package.json +2 -2
  7. package/package.json +11 -11
  8. package/src/agent/built-in/documenter.md +17 -17
  9. package/src/agent/built-in/general.md +70 -69
  10. package/src/agent/built-in/planner.md +13 -13
  11. package/src/agent/built-in/scout.md +17 -19
  12. package/src/agent/command.ts +76 -44
  13. package/src/agent/config.ts +167 -0
  14. package/src/agent/helpers.ts +44 -39
  15. package/src/agent/index.ts +32 -10
  16. package/src/agent/storage.ts +96 -186
  17. package/src/agent/types.ts +6 -0
  18. package/src/checkpoint/git.ts +12 -8
  19. package/src/checkpoint/index.ts +84 -20
  20. package/src/checkpoint/snapshot.ts +1 -1
  21. package/src/checkpoint/stage.ts +4 -2
  22. package/src/checkpoint/store.ts +6 -13
  23. package/src/cleanup/index.ts +1 -3
  24. package/src/commands/helpers.ts +7 -9
  25. package/src/commands/index.ts +1 -1
  26. package/src/commands/render.ts +14 -15
  27. package/src/optimizer/README.md +12 -4
  28. package/src/optimizer/deduplicator/index.ts +23 -13
  29. package/src/optimizer/deduplicator/resources.ts +35 -63
  30. package/src/optimizer/deduplicator/state.ts +48 -106
  31. package/src/optimizer/entries.ts +20 -99
  32. package/src/optimizer/index.ts +6 -7
  33. package/src/optimizer/inspector/helpers.ts +1 -19
  34. package/src/optimizer/inspector/index.ts +6 -7
  35. package/src/optimizer/inspector/inspect.ts +3 -14
  36. package/src/optimizer/languages/symbols.ts +2 -10
  37. package/src/optimizer/languages/types.ts +0 -4
  38. package/src/optimizer/languages/typescript.ts +6 -0
  39. package/src/optimizer/mapper/files.ts +60 -67
  40. package/src/optimizer/mapper/index.ts +91 -99
  41. package/src/optimizer/pruner/cleanup.ts +0 -89
  42. package/src/optimizer/pruner/index.ts +42 -33
  43. package/src/optimizer/reducer/bash.ts +100 -0
  44. package/src/optimizer/reducer/grep.ts +104 -0
  45. package/src/optimizer/reducer/index.ts +81 -0
  46. package/src/permission/constants.ts +2 -1
  47. package/src/permission/helpers.ts +14 -4
  48. package/src/permission/index.ts +8 -9
  49. package/src/permission/resolution.ts +26 -36
  50. package/src/permission/types.ts +2 -2
  51. package/src/questionnaire/component.ts +21 -12
  52. package/src/questionnaire/helpers.ts +11 -67
  53. package/src/questionnaire/index.ts +24 -11
  54. package/src/questionnaire/schemas.ts +12 -8
  55. package/src/questionnaire/types.ts +3 -3
  56. package/src/redactor/index.ts +30 -15
  57. package/src/redactor/patterns.ts +6 -6
  58. package/src/redactor/results.ts +156 -0
  59. package/src/redactor/secrets.ts +20 -64
  60. package/src/state.ts +3 -1
  61. package/src/subagent/helpers.ts +18 -9
  62. package/src/subagent/index.ts +57 -29
  63. package/src/subagent/sdk.ts +9 -5
  64. package/src/subagent/storage.ts +1 -2
  65. package/src/subagent/subsession.ts +46 -14
  66. package/src/subagent/types.ts +14 -7
  67. package/src/subagent/validation.ts +11 -54
  68. package/src/ui/components/bash-mode.ts +20 -12
  69. package/src/ui/components/frame.ts +4 -0
  70. package/src/ui/components/scrollable-view.ts +23 -7
  71. package/src/utils.ts +16 -6
  72. package/src/web-tools/providers/brave.ts +7 -2
  73. package/src/web-tools/providers/firecrawl.ts +47 -15
  74. package/src/web-tools/providers/index.ts +2 -2
  75. package/src/web-tools/providers/jina.ts +2 -1
  76. package/src/web-tools/providers/native.ts +2 -1
  77. package/src/web-tools/providers/tavily.ts +43 -22
  78. package/src/web-tools/web-fetch/index.ts +10 -11
  79. package/src/web-tools/web-fetch/storage.ts +17 -2
  80. package/src/web-tools/web-login/index.ts +10 -9
  81. package/src/web-tools/web-login/input.ts +55 -0
  82. package/src/web-tools/web-search/index.ts +3 -3
  83. package/src/cleanup/helpers.ts +0 -24
  84. package/src/cleanup/permission.ts +0 -76
  85. package/src/mcp-client/call-tool.ts +0 -143
  86. package/src/mcp-client/client.ts +0 -90
  87. package/src/mcp-client/command.ts +0 -257
  88. package/src/mcp-client/helpers.ts +0 -153
  89. package/src/mcp-client/index.ts +0 -21
  90. package/src/mcp-client/list-tools.ts +0 -84
  91. package/src/mcp-client/storage.ts +0 -190
  92. package/src/mcp-client/types.ts +0 -34
  93. package/src/mcp-client/validation.ts +0 -115
  94. package/src/optimizer/compactor/bash.ts +0 -141
  95. package/src/optimizer/compactor/grep.ts +0 -209
  96. package/src/optimizer/compactor/index.ts +0 -155
  97. package/src/optimizer/deduplicator/helpers.ts +0 -75
  98. package/src/optimizer/deduplicator/types.ts +0 -14
  99. package/src/optimizer/inspector/types.ts +0 -7
  100. package/src/optimizer/mapper/types.ts +0 -6
  101. package/src/optimizer/pruner/context.ts +0 -46
  102. package/src/optimizer/pruner/session.ts +0 -34
  103. package/src/optimizer/pruner/types.ts +0 -18
package/bin/build.mjs ADDED
@@ -0,0 +1,53 @@
1
+ import { build } from "esbuild";
2
+ import { copyFile, mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { dirname, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
7
+ const projectRoot = resolve(scriptDir, "..");
8
+ const optimizerDir = resolve(projectRoot, "dist", "optimizer");
9
+ const rootPackage = JSON.parse(await readFile(resolve(projectRoot, "package.json"), "utf8"));
10
+
11
+ await rm(optimizerDir, { recursive: true, force: true });
12
+ await mkdir(optimizerDir, { recursive: true });
13
+ await build({
14
+ entryPoints: [resolve(projectRoot, "src", "optimizer", "index.ts")],
15
+ outfile: resolve(optimizerDir, "index.js"),
16
+ bundle: true,
17
+ format: "esm",
18
+ packages: "external",
19
+ platform: "node",
20
+ sourcemap: true,
21
+ target: "node22",
22
+ });
23
+
24
+ const optimizerPackage = {
25
+ name: "pi-optimizer",
26
+ version: rootPackage.version,
27
+ description: "Context optimization tools for pi coding agent",
28
+ type: "module",
29
+ main: "./index.js",
30
+ exports: "./index.js",
31
+ engines: rootPackage.engines,
32
+ license: rootPackage.license,
33
+ keywords: ["pi-package", "pi-coding-agent", "context-optimization"],
34
+ pi: { extensions: ["./index.js"] },
35
+ dependencies: {
36
+ picomatch: rootPackage.dependencies.picomatch,
37
+ "tree-sitter": rootPackage.dependencies["tree-sitter"],
38
+ },
39
+ peerDependencies: {
40
+ "@earendil-works/pi-coding-agent": "*",
41
+ "@earendil-works/pi-tui": "*",
42
+ typebox: "*",
43
+ },
44
+ };
45
+
46
+ await Promise.all([
47
+ writeFile(resolve(optimizerDir, "package.json"), `${JSON.stringify(optimizerPackage, null, 2)}\n`),
48
+ copyFile(resolve(projectRoot, "LICENSE"), resolve(optimizerDir, "LICENSE")),
49
+ copyFile(
50
+ resolve(projectRoot, "src", "optimizer", "README.md"),
51
+ resolve(optimizerDir, "README.md"),
52
+ ),
53
+ ]);
package/bin/surgent.js CHANGED
@@ -11,20 +11,22 @@ import { fileURLToPath } from "node:url";
11
11
  process.title = "surgent";
12
12
  const args = process.argv.slice(2);
13
13
 
14
+ const GLOBAL_PI_DIR = resolve(homedir(), ".pi", "agent");
14
15
  const PACKAGE_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..");
15
16
  const AGENT_ENTRY_URL = import.meta.resolve("@earendil-works/pi-coding-agent");
16
17
  const LOCAL_PI_SUBDIRS = ["agents", "plans"];
18
+ const GLOBAL_PI_SUBDIRS = ["agents", "grammars"];
17
19
  const BASE_TOOLS = ["ls", "find", "grep", "code_map", "inspect", "read"];
18
20
  const BUILT_IN_META = {
19
21
  documenter: {
20
- tools: [...BASE_TOOLS, "edit", "write", "questionnaire"],
22
+ tools: BASE_TOOLS.concat(["edit", "write", "questionnaire"]),
21
23
  "files.write": ["**/*.md"],
22
24
  },
23
25
  planner: {
24
- tools: [...BASE_TOOLS, "web_fetch", "web_search", "questionnaire"],
26
+ tools: BASE_TOOLS.concat(["web_fetch", "web_search", "questionnaire"]),
25
27
  },
26
28
  scout: {
27
- tools: [...BASE_TOOLS, "web_fetch", "web_search"],
29
+ tools: BASE_TOOLS.concat(["web_fetch", "web_search"]),
28
30
  },
29
31
  };
30
32
 
@@ -33,9 +35,8 @@ function isMissingFileError(error) {
33
35
  }
34
36
 
35
37
  async function initBuiltInMeta() {
36
- const settingsPath = resolve(homedir(), ".pi", "agent", "settings.json");
38
+ const settingsPath = resolve(GLOBAL_PI_DIR, "settings.json");
37
39
  let settings;
38
-
39
40
  try {
40
41
  settings = JSON.parse(await readFile(settingsPath, "utf8"));
41
42
  } catch (error) {
@@ -129,7 +130,7 @@ async function syncPiIgnore(cwd) {
129
130
  return;
130
131
  }
131
132
 
132
- await writeFile(piIgnorePath, gitIgnoreContents);
133
+ await writeFile(piIgnorePath, `.pi\n\n${gitIgnoreContents}`);
133
134
  }
134
135
 
135
136
  function isJsonModeActive(args) {
@@ -195,16 +196,16 @@ if (args.includes("--help") || args.includes("-h")) {
195
196
  await runRewrittenHelp(args);
196
197
  } else {
197
198
  const cwd = process.cwd();
199
+ const srcDir = resolve(PACKAGE_DIR, "src");
198
200
  if (!isJsonModeActive(args)) {
199
- await ensurePiExcluded(cwd);
200
- await syncPiIgnore(cwd);
201
- }
202
- for (const localPiSubdir of LOCAL_PI_SUBDIRS) {
203
- await mkdir(resolve(cwd, ".pi", localPiSubdir), { recursive: true });
201
+ await Promise.all([ensurePiExcluded(cwd), syncPiIgnore(cwd)]);
204
202
  }
203
+ const [entries] = await Promise.all([
204
+ readdir(srcDir, { withFileTypes: true }),
205
+ ...LOCAL_PI_SUBDIRS.map((dir) => mkdir(resolve(cwd, ".pi", dir), { recursive: true })),
206
+ ...GLOBAL_PI_SUBDIRS.map((dir) => mkdir(resolve(GLOBAL_PI_DIR, dir), { recursive: true })),
207
+ ]);
205
208
 
206
- const srcDir = resolve(PACKAGE_DIR, "src");
207
- const entries = await readdir(srcDir, { withFileTypes: true });
208
209
  const extensionArgs = entries
209
210
  .filter((entry) => entry.isDirectory())
210
211
  .flatMap((entry) => ["--extension", resolve(srcDir, entry.name)]);
@@ -13,13 +13,21 @@ Long coding sessions accumulate large tool results, repeated file content, and o
13
13
  - Adds `code_map`, which uses Tree-sitter to index symbols and declarations before files are read in full.
14
14
  - Adds `inspect`, which returns one selected symbol body for targeted code reading and edits.
15
15
  - Supports TypeScript, JavaScript, Python, Go, Java, and Rust code navigation.
16
- - Compacts Bash output by stripping terminal control sequences and collapsing repeated or similar lines.
17
- - Formats grep results by grouping matches under file paths and stores smaller summaries in session history.
18
- - Removes older `read` and `inspect` results when newer results fully cover same content.
19
- - Prunes empty tool results and superseded tool calls from model context and persisted sessions.
16
+ - Losslessly compresses consecutive Bash lines with at most one varying alphanumeric token: `status {204, 404, 500}`. Order, duplicates, and raw bytes remain recoverable; `{{` / `}}` escape literal braces. Compression applies only when shorter. Bash output limits still apply.
17
+ - Reduces grep output during execution by grouping matches under file paths.
18
+ - Filters older eligible `inspect` exchanges and pre-write `read`/`inspect` exchanges from model requests using a session-start snapshot.
19
+ - Persistently prunes eligible error and empty tool results, together with their tool calls, through append-only context edits.
20
20
 
21
21
  These changes reduce context growth, improve prompt-cache reuse, and leave more room for requirements, code, and reasoning.
22
22
 
23
+ ## Context filtering
24
+
25
+ At `session_start`, optimizer snapshots the current branch. For model requests only, it hides older eligible `inspect` exchanges for the same normalized file path and exact returned symbol, and older same-file `read`/`inspect` exchanges superseded by a successful `write`. Both tool calls and results are hidden. There is no general `read` deduplication, and edits or shell commands do not invalidate earlier results.
26
+
27
+ Changes after startup are deferred until the next session start. Session tree navigation clears the snapshot. This transient filtering leaves raw history, the TUI, exports, and Pi's canonical context for native compaction unchanged.
28
+
29
+ Separately, when the agent settles after successful completion, eligible error results (except Bash errors) and recognized empty `ls`/`find` results are pruned with their tool calls through persistent, append-only context edits. These change future model context without rewriting raw history.
30
+
23
31
  ## Requirements
24
32
 
25
33
  - Node.js 22.19 or newer