@nexrall/code-core 1.4.65 → 1.4.67

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 (83) hide show
  1. package/README.md +2 -2
  2. package/dist/agent/agentTypes.d.ts +8 -4
  3. package/dist/agent/agentTypes.d.ts.map +1 -1
  4. package/dist/agent/agentTypes.js +20 -147
  5. package/dist/agent/askOnce.d.ts +12 -0
  6. package/dist/agent/askOnce.d.ts.map +1 -0
  7. package/dist/agent/askOnce.js +41 -0
  8. package/dist/agent/compaction.d.ts +244 -0
  9. package/dist/agent/compaction.d.ts.map +1 -0
  10. package/dist/agent/compaction.js +976 -0
  11. package/dist/agent/fileLocks.d.ts +34 -0
  12. package/dist/agent/fileLocks.d.ts.map +1 -0
  13. package/dist/agent/fileLocks.js +114 -0
  14. package/dist/agent/hooks.d.ts +324 -0
  15. package/dist/agent/hooks.d.ts.map +1 -0
  16. package/dist/agent/hooks.js +1228 -0
  17. package/dist/agent/iterationPolicy.d.ts +121 -0
  18. package/dist/agent/iterationPolicy.d.ts.map +1 -0
  19. package/dist/agent/iterationPolicy.js +297 -0
  20. package/dist/agent/lifecycleHost.d.ts +55 -0
  21. package/dist/agent/lifecycleHost.d.ts.map +1 -0
  22. package/dist/agent/lifecycleHost.js +294 -0
  23. package/dist/agent/loop.d.ts +11 -491
  24. package/dist/agent/loop.d.ts.map +1 -1
  25. package/dist/agent/loop.js +418 -3032
  26. package/dist/agent/memory.d.ts +11 -0
  27. package/dist/agent/memory.d.ts.map +1 -1
  28. package/dist/agent/memory.js +23 -3
  29. package/dist/agent/planMode.d.ts +14 -0
  30. package/dist/agent/planMode.d.ts.map +1 -1
  31. package/dist/agent/planMode.js +146 -17
  32. package/dist/agent/securityLint.js +2 -2
  33. package/dist/agent/sharedTasks.d.ts +7 -0
  34. package/dist/agent/sharedTasks.d.ts.map +1 -1
  35. package/dist/agent/sharedTasks.js +16 -0
  36. package/dist/agent/subAgentBudget.d.ts +65 -0
  37. package/dist/agent/subAgentBudget.d.ts.map +1 -0
  38. package/dist/agent/subAgentBudget.js +269 -0
  39. package/dist/agent/subTask.d.ts +6 -0
  40. package/dist/agent/subTask.d.ts.map +1 -0
  41. package/dist/agent/subTask.js +713 -0
  42. package/dist/agent/subTaskSupport.d.ts +156 -0
  43. package/dist/agent/subTaskSupport.d.ts.map +1 -0
  44. package/dist/agent/subTaskSupport.js +409 -0
  45. package/dist/agent/toolDescriptions.d.ts +3 -0
  46. package/dist/agent/toolDescriptions.d.ts.map +1 -0
  47. package/dist/agent/toolDescriptions.js +116 -0
  48. package/dist/api/client.d.ts +1 -1
  49. package/dist/api/client.d.ts.map +1 -1
  50. package/dist/api/client.js +17 -0
  51. package/dist/index.d.ts +3 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +3 -0
  54. package/dist/mcp/client.d.ts +104 -0
  55. package/dist/mcp/client.d.ts.map +1 -1
  56. package/dist/mcp/client.js +136 -2
  57. package/dist/mcp/httpClient.d.ts +17 -1
  58. package/dist/mcp/httpClient.d.ts.map +1 -1
  59. package/dist/mcp/httpClient.js +120 -19
  60. package/dist/mcp/manager.d.ts +77 -2
  61. package/dist/mcp/manager.d.ts.map +1 -1
  62. package/dist/mcp/manager.js +275 -9
  63. package/dist/mcp/sseClient.d.ts +7 -1
  64. package/dist/mcp/sseClient.d.ts.map +1 -1
  65. package/dist/mcp/sseClient.js +45 -1
  66. package/dist/mcp/stats.d.ts +41 -0
  67. package/dist/mcp/stats.d.ts.map +1 -0
  68. package/dist/mcp/stats.js +108 -0
  69. package/dist/permissions/destructive.d.ts +11 -7
  70. package/dist/permissions/destructive.d.ts.map +1 -1
  71. package/dist/permissions/destructive.js +59 -8
  72. package/dist/permissions/destructiveTokens.d.ts +34 -0
  73. package/dist/permissions/destructiveTokens.d.ts.map +1 -0
  74. package/dist/permissions/destructiveTokens.js +475 -0
  75. package/dist/permissions/modePolicy.d.ts +12 -8
  76. package/dist/permissions/modePolicy.d.ts.map +1 -1
  77. package/dist/permissions/modePolicy.js +19 -12
  78. package/dist/permissions/rules.d.ts +4 -1
  79. package/dist/permissions/rules.d.ts.map +1 -1
  80. package/dist/permissions/rules.js +29 -0
  81. package/dist/types.d.ts +47 -3
  82. package/dist/types.d.ts.map +1 -1
  83. package/package.json +8 -7
package/README.md CHANGED
@@ -122,9 +122,9 @@ const cmds = loadSlashCommands(process.cwd());
122
122
  const review = findSlashCommand(cmds, 'review');
123
123
  const prompt = expandCommand(review, 'main..feature-branch', process.cwd());
124
124
 
125
- // Built-in 'reviewer' agent (read-only, usable as subagent_type: 'reviewer')
125
+ // Built-in 'explorer' agent (read-only, usable as subagent_type: 'explorer')
126
126
  const agents = loadAgentTypes(process.cwd());
127
- const reviewer = findAgentType(agents, 'reviewer');
127
+ const explorer = findAgentType(agents, 'explorer');
128
128
  ```
129
129
 
130
130
  ## Checkpoint / rewind
@@ -19,7 +19,7 @@ export interface AgentType {
19
19
  * When true, this agent's write tools may only target TEST files.
20
20
  *
21
21
  * Needed because a tool allowlist is all-or-nothing per tool: granting
22
- * `edit_file` grants it for every path. The `test-writer` agent must be able to
22
+ * `edit_file` grants it for every path. A user-defined test-writer agent must be able to
23
23
  * write tests while being unable to "fix" production source to make a test
24
24
  * pass — the single most common way a test-writing agent destroys signal — and
25
25
  * a prompt instruction alone cannot guarantee that. Enforced in loop.ts's
@@ -53,7 +53,7 @@ export interface AgentType {
53
53
  * delegation prompt instead.
54
54
  *
55
55
  * Only for agents that neither write files nor make judgement calls about conventions
56
- * — a reviewer or test-writer needs the project's rules, an explorer does not.
56
+ * — a reviewer or test-writer needs the project's rules, an explorer or planner does not.
57
57
  */
58
58
  lightPrompt?: boolean;
59
59
  /** Tools this agent may NOT use, on top of (or instead of) an allowlist. Claude Code's `disallowedTools`. */
@@ -82,8 +82,12 @@ export interface AgentType {
82
82
  hooks?: AgentHooks;
83
83
  }
84
84
  export interface AgentHookDef {
85
- type: 'command';
86
- command: string;
85
+ type: 'command' | 'http';
86
+ command?: string;
87
+ /** `type:"http"`: POST the hook payload here. */
88
+ url?: string;
89
+ headers?: Record<string, string>;
90
+ allowedEnvVars?: string[];
87
91
  timeout_ms?: number;
88
92
  }
89
93
  export interface AgentHookEntry {
@@ -1 +1 @@
1
- {"version":3,"file":"agentTypes.d.ts","sourceRoot":"","sources":["../../src/agent/agentTypes.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,cAAc,CAAC;IACrE;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,6GAA6G;IAC7G,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8GAA8G;IAC9G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,gHAAgH;IAChH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,+GAA+G;IAC/G,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAAG,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE;AACvF,MAAM,WAAW,cAAc;IAAG,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,YAAY,EAAE,CAAA;CAAE;AAC3E,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,uFAAuF;IACvF,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAgY5D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAOnD;AAgBD,eAAO,MAAM,YAAY,8IAKf,CAAC;AAEX,2MAA2M;AAC3M,eAAO,MAAM,kBAAkB,4CAA6C,CAAC;AAC7E,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CASpE;AAyOD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,CAAC,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAuCnF;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CAE3D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,SAAS,EAAO,GACtB;IAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAuBlD;AAED,yFAAyF;AACzF,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAEzC;AAED,2FAA2F;AAC3F,wBAAgB,aAAa,IAAI,SAAS,EAAE,CAE3C;AACD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAY1D;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAIjG"}
1
+ {"version":3,"file":"agentTypes.d.ts","sourceRoot":"","sources":["../../src/agent/agentTypes.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,cAAc,CAAC;IACrE;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,6GAA6G;IAC7G,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8GAA8G;IAC9G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,gHAAgH;IAChH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,+GAA+G;IAC/G,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,cAAc;IAAG,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,YAAY,EAAE,CAAA;CAAE;AAC3E,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,uFAAuF;IACvF,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAoP5D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAOnD;AAgBD,eAAO,MAAM,YAAY,8IAKf,CAAC;AAEX,2MAA2M;AAC3M,eAAO,MAAM,kBAAkB,4CAA6C,CAAC;AAC7E,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CASpE;AAyOD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,CAAC,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CA+CnF;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CAE3D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,SAAS,EAAO,GACtB;IAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAuBlD;AAED,yFAAyF;AACzF,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAEzC;AAED,2FAA2F;AAC3F,wBAAgB,aAAa,IAAI,SAAS,EAAE,CAE3C;AACD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAY1D;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAIjG"}
@@ -65,7 +65,7 @@ function parseMemoryScope(v) {
65
65
  // capability on whichever client it runs.
66
66
  //
67
67
  // This exists because it was previously inlined per agent, and the one agent that
68
- // had it (`reviewer`) listed five VS Code-only tools, leaving it with just five
68
+ // had it listed five VS Code-only tools, leaving that agent with just five
69
69
  // usable tools when run from the CLI — a silent capability gap that is very easy
70
70
  // to reintroduce by copy-pasting a list.
71
71
  const READ_ONLY_TOOLS = [
@@ -111,20 +111,8 @@ const READ_ONLY_TOOLS = [
111
111
  * only way to stop it being "helpfully" re-added.
112
112
  */
113
113
  // web_search is a client-side tool now (executor.ts webSearch), so it must be granted
114
- // explicitly — planner/devops-advisor were told to use it and then refused.
114
+ // explicitly — planner was told to use it and then refused.
115
115
  const RESEARCH_TOOLS = [...READ_ONLY_TOOLS, 'fetch_url', 'web_search'];
116
- /** Read-only + the write tools, for agents that produce code. */
117
- const WRITE_TOOLS = [
118
- ...READ_ONLY_TOOLS,
119
- 'write_file', 'edit_file', 'multi_edit', 'create_directory', 'move_file', 'copy_file',
120
- // notebook_edit is a write tool like any other, and allowsTestOnlyWrite already
121
- // knows its shape (`source` is cell CONTENT, not a path). Omitting it just meant
122
- // test-writer silently could not touch notebooks.
123
- 'notebook_edit',
124
- // Office document generation — same write-access tier as write_file, just a
125
- // structured content shape instead of raw text (see tools/executor.ts).
126
- 'write_docx', 'write_xlsx', 'write_pptx',
127
- ];
128
116
  const BUILTIN_AGENTS = [
129
117
  {
130
118
  // The catch-all, matching Claude Code's `general-purpose`.
@@ -165,66 +153,6 @@ const BUILTIN_AGENTS = [
165
153
  '(with file paths), what you ran and its outcome, and anything you deliberately left undone.',
166
154
  source: 'builtin',
167
155
  },
168
- {
169
- name: 'reviewer',
170
- description: 'Read-only code reviewer — finds correctness bugs, edge cases, and security issues in a diff or file set. Cannot modify files.',
171
- tools: READ_ONLY_TOOLS,
172
- source: 'builtin',
173
- prompt: [
174
- 'You are a meticulous senior code reviewer. You NEVER modify files — you only read, search, and report.',
175
- '',
176
- 'Method:',
177
- '1. Read the full context around every change you are asked to review; never judge a hunk in isolation.',
178
- '2. Hunt specifically for: correctness bugs, unhandled edge cases (empty/null/unicode/concurrency/timezone),',
179
- ' security issues (injection, path traversal, secrets in code, unsafe deserialization), breaking API',
180
- ' changes (search for callers first), silent behaviour changes, and swallowed errors.',
181
- '3. Verify test coverage: are the changed paths tested? Were assertions weakened or tests deleted?',
182
- '4. Only use bash for read-only commands (git diff/log/show, grep, test runs). Never run mutating commands.',
183
- '',
184
- 'Report format: 🔴 Critical / 🟡 Warning / 🟢 Suggestion, each with file:line and a concrete fix,',
185
- 'then a final verdict (APPROVE or REQUEST CHANGES) with a one-paragraph rationale.',
186
- ].join('\n'),
187
- },
188
- // Promoted from the security-audit plugin to a builtin.
189
- //
190
- // Leaving it plugin-only was indefensible next to `reviewer` being builtin:
191
- // reviewer's own prompt already tells it to look for security issues, so
192
- // security IS treated as default work — yet the specialist agent for it was
193
- // invisible unless the user happened to know the plugin existed. For an agent
194
- // that WRITES code, "you only get a security review if you knew to install
195
- // something" is the wrong default.
196
- {
197
- name: 'security-auditor',
198
- description: 'Read-only security auditor — hunts injection, authz, secrets, and validation flaws in a path or diff. Cannot modify files.',
199
- tools: READ_ONLY_TOOLS,
200
- // No `model` override — inherits the session's, same as general-purpose.
201
- // A previous version forced 'pro' (Claude Opus 5) here, which silently
202
- // billed Anthropic even for a session running entirely on OpenAI/DeepSeek/
203
- // Qwen. Consistency with the main conversation's provider matters more
204
- // than defaulting every specialist to a fixed tier.
205
- source: 'builtin',
206
- prompt: [
207
- 'You are a security auditor. You find real, exploitable flaws — not style issues.',
208
- '',
209
- 'Method:',
210
- '1. Map the attack surface FIRST: entry points (HTTP routes, message handlers, CLI args, file/network',
211
- ' input, deserialization), then trace user-controlled data inward to where it is used.',
212
- '2. For each finding: file:line, the flaw class, a one-line exploit scenario, and the concrete fix.',
213
- '3. Grade severity honestly: Critical = remote compromise or data breach; High = auth bypass/IDOR;',
214
- ' Medium = needs unusual preconditions; Low = hardening.',
215
- '',
216
- 'Classes worth the most attention, in order: injection (SQL/command/template/prototype), broken',
217
- 'authz (missing ownership checks, IDOR, trusting client-supplied ids), secrets committed to source,',
218
- 'path traversal, SSRF, unsafe deserialization, missing rate limits on expensive or auth endpoints,',
219
- 'and crypto misuse (hand-rolled comparison, predictable randomness).',
220
- '',
221
- 'Hard rules:',
222
- '- READ-ONLY: never modify, create or delete files. bash only for read-only inspection.',
223
- '- NEVER print a discovered secret\'s value. Report its location and advise rotation.',
224
- '- Distinguish EXPLOITABLE from theoretical, and say which one each finding is.',
225
- '- "No issues found in scope X" is a valid, useful result. Do not pad the report to look thorough.',
226
- ].join('\n'),
227
- },
228
156
  // The gap Claude Code fills with its built-in `Explore`: read-heavy codebase
229
157
  // search that would otherwise flood the parent's context. Defaults to the
230
158
  // cheapest model on purpose — "find every caller of X" has no need of a
@@ -265,10 +193,14 @@ const BUILTIN_AGENTS = [
265
193
  // quietly become "start editing".
266
194
  {
267
195
  name: 'planner',
196
+ // Lean prompt, as Claude Code's Plan builtin: it researches and reports, and the MAIN
197
+ // agent (which has nexrall.md and the conversation) judges the plan against project
198
+ // rules. Conventions that must bind the plan belong in the delegation prompt.
199
+ lightPrompt: true,
268
200
  description: 'Read-only planning agent — researches a change and returns a concrete step-by-step implementation plan with risks and affected files. Cannot modify files.',
269
201
  tools: RESEARCH_TOOLS,
270
202
  // No `model` override — inherits the session's, for the same reason as
271
- // explorer/security-auditor above: a fixed alias silently billed Anthropic
203
+ // explorer above: a fixed alias silently billed Anthropic
272
204
  // regardless of the user's chosen provider.
273
205
  source: 'builtin',
274
206
  prompt: [
@@ -289,74 +221,6 @@ const BUILTIN_AGENTS = [
289
221
  '- Anything genuinely ambiguous, stated as an open question rather than a silent assumption.',
290
222
  ].join('\n'),
291
223
  },
292
- // Promoted from the test-gen plugin. Needs write access — it produces test
293
- // files — but is deliberately forbidden from touching source, because "make the
294
- // tests pass" is the single most common way an agent destroys signal.
295
- {
296
- name: 'test-writer',
297
- description: 'Writes tests that follow the project\'s existing conventions. May create/edit TEST files only — never production source.',
298
- tools: WRITE_TOOLS,
299
- // Enforced, not merely requested: the permission gate refuses a write whose
300
- // path is not a test file. Without this the allowlist would grant edit_file
301
- // for every path and the rule below would be a suggestion the model is free
302
- // to rationalise its way past.
303
- testFilesOnly: true,
304
- source: 'builtin',
305
- prompt: [
306
- 'You write tests. You may create and edit TEST files only.',
307
- '',
308
- 'Hard rules — these are the ways test-writing agents destroy value, so they are non-negotiable:',
309
- '- NEVER modify production source to make a test pass. If the code looks wrong, REPORT it and stop.',
310
- '- NEVER weaken, delete or skip an existing assertion or test.',
311
- '- A test that cannot fail is worse than no test. Every test must be able to fail for one clear reason.',
312
- '',
313
- 'Method:',
314
- '1. Read the existing tests FIRST and copy their conventions exactly — runner, file naming, layout,',
315
- ' assertion style, fixture/helper patterns. Never introduce a new framework.',
316
- '2. Test observable behaviour and the contract, not private internals.',
317
- '3. Cover the boring-but-real cases: empty input, null/undefined, unicode and non-BMP characters,',
318
- ' boundaries, error paths, concurrency where it applies.',
319
- '4. No sleeps or wall-clock dependence — those produce the flaky tests that get deleted later.',
320
- '5. RUN the tests you wrote and report the real output. Never claim a test passes without running it.',
321
- ].join('\n'),
322
- },
323
- // The DevOps gap — answered with a READ-ONLY advisor, not an operator.
324
- //
325
- // A "DevOps agent" with write/apply access is a genuinely different risk class
326
- // from the others here: its mistakes are `kubectl delete`, a bad `terraform
327
- // apply`, a broken deploy pipeline — often not revertible and affecting
328
- // production rather than a working tree. So this one diagnoses and proposes a
329
- // diff; a human applies it. That asymmetry is the whole design.
330
- {
331
- name: 'devops-advisor',
332
- description: 'Read-only CI/CD, container, and infrastructure advisor — diagnoses pipelines, Dockerfiles, and k8s manifests and proposes concrete fixes as a diff. Never applies changes.',
333
- tools: RESEARCH_TOOLS,
334
- // No `model` override — inherits the session's, for the same reason as the
335
- // other specialists above.
336
- source: 'builtin',
337
- prompt: [
338
- 'You are an infrastructure and delivery advisor. You DIAGNOSE and PROPOSE. You never apply changes.',
339
- '',
340
- 'Hard rules:',
341
- '- READ-ONLY, and stricter than the other read-only agents: bash is for INSPECTION only',
342
- ' (git log/diff, cat, grep, `kubectl get/describe`, `docker images`, `terraform plan`).',
343
- ' NEVER run anything that mutates infrastructure — no apply/delete/scale/rollout/restart/push,',
344
- ' no `terraform apply`, no `helm upgrade`. If a fix needs such a command, WRITE IT OUT for a human.',
345
- '- Never print secret values from env files, k8s Secrets or CI variables. Reference them by name.',
346
- '',
347
- 'Method:',
348
- '1. Read what actually exists — workflow files, Dockerfiles, manifests, kustomize overlays, the',
349
- ' deploy scripts — before drawing any conclusion. Never reason from what a stack "usually" looks like.',
350
- '2. Follow the real path a change takes to production, and name the step that is broken or missing.',
351
- '3. Check the failure modes that bite hardest: CI path filters that skip files a workload actually',
352
- ' needs, image tags that do not match what is deployed, missing health probes, absent resource',
353
- ' limits, secrets baked into images, ports/timeouts inconsistent between proxy and app, and',
354
- ' migrations that must run before the new image is live.',
355
- '',
356
- 'Output: the diagnosis, the evidence (file:line or command output), the proposed change as a diff or',
357
- 'exact file content, and the command a human should run to apply and verify it.',
358
- ].join('\n'),
359
- },
360
224
  ];
361
225
  /**
362
226
  * Every tool name a client may offer, for validating a hand-written allowlist.
@@ -724,12 +588,21 @@ function parseAgentHooks(raw) {
724
588
  throw new Error(`${where}: expected a list of hooks`);
725
589
  return list.map((h, i) => {
726
590
  const o = h;
727
- if (!o || o.type !== 'command' || typeof o.command !== 'string' || !o.command.trim()) {
728
- throw new Error(`${where}[${i}]: each hook needs type: command and a command`);
729
- }
730
591
  const ms = typeof o.timeout_ms === 'number' ? o.timeout_ms
731
592
  : typeof o.timeout === 'number' ? o.timeout * 1000 : undefined;
732
- return { type: 'command', command: o.command, ...(ms && ms > 0 ? { timeout_ms: ms } : {}) };
593
+ const timeout = ms && ms > 0 ? { timeout_ms: ms } : {};
594
+ if (o && o.type === 'http' && typeof o.url === 'string' && o.url.trim()) {
595
+ if (!/^https?:\/\//i.test(o.url.trim()))
596
+ throw new Error(`${where}[${i}]: http hooks need an http(s) url`);
597
+ const headers = o.headers && typeof o.headers === 'object' && !Array.isArray(o.headers)
598
+ ? o.headers : undefined;
599
+ const allowed = Array.isArray(o.allowedEnvVars) ? o.allowedEnvVars.filter((v) => typeof v === 'string') : undefined;
600
+ return { type: 'http', url: o.url.trim(), ...(headers ? { headers } : {}), ...(allowed ? { allowedEnvVars: allowed } : {}), ...timeout };
601
+ }
602
+ if (!o || o.type !== 'command' || typeof o.command !== 'string' || !o.command.trim()) {
603
+ throw new Error(`${where}[${i}]: each hook needs type: command and a command, or type: http and a url`);
604
+ }
605
+ return { type: 'command', command: o.command, ...timeout };
733
606
  });
734
607
  };
735
608
  const entries = (list, ev) => {
@@ -0,0 +1,12 @@
1
+ import type { EnvContext } from '../types';
2
+ export interface AskOnceOptions {
3
+ model: string;
4
+ cwd: string;
5
+ env?: EnvContext;
6
+ timeoutMs?: number;
7
+ abortSignal?: {
8
+ aborted: boolean;
9
+ };
10
+ }
11
+ export declare function askModelOnce(prompt: string, opts: AskOnceOptions): Promise<string | null>;
12
+ //# sourceMappingURL=askOnce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askOnce.d.ts","sourceRoot":"","sources":["../../src/agent/askOnce.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAgB,UAAU,EAAW,MAAM,UAAU,CAAC;AAKlE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACpC;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwB/F"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ // A single tool-less model call: send one prompt, get the text back. Used by small
3
+ // judges (e.g. the CLI's /goal) that need an answer, not an agent loop. It never
4
+ // runs tools, never throws on a model/network failure (returns null) and never
5
+ // outlives its timeout, so a judge can never hang or crash the turn that asked.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.askModelOnce = askModelOnce;
8
+ const client_1 = require("../api/client");
9
+ /** The same marker prompt hooks use: matches no tool, so the backend sends none. */
10
+ const NO_TOOLS_MARKER = '\u0000hook-no-tools';
11
+ async function askModelOnce(prompt, opts) {
12
+ const ctl = { aborted: false };
13
+ const timer = setTimeout(() => { ctl.aborted = true; }, Math.max(1000, opts.timeoutMs ?? 45000));
14
+ const poll = opts.abortSignal
15
+ ? setInterval(() => { if (opts.abortSignal?.aborted)
16
+ ctl.aborted = true; }, 100)
17
+ : undefined;
18
+ try {
19
+ if (opts.abortSignal?.aborted)
20
+ return null;
21
+ const messages = [{ role: 'user', content: [{ type: 'text', text: prompt }] }];
22
+ const msg = await (0, client_1.streamChat)(messages, {
23
+ model: opts.model,
24
+ env: opts.env ?? { cwd: opts.cwd },
25
+ abortSignal: ctl,
26
+ toolAllowlist: [NO_TOOLS_MARKER],
27
+ }, () => { });
28
+ const blocks = Array.isArray(msg.content) ? msg.content : [];
29
+ const text = blocks.filter((b) => b.type === 'text' && typeof b.text === 'string').map((b) => b.text).join('\n');
30
+ return ctl.aborted ? null : text;
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ finally {
36
+ clearTimeout(timer);
37
+ if (poll)
38
+ clearInterval(poll);
39
+ }
40
+ }
41
+ //# sourceMappingURL=askOnce.js.map
@@ -0,0 +1,244 @@
1
+ import type { Message, AgentLoopOptions, EnvContext } from '../types';
2
+ import { streamChat } from '../api/client';
3
+ import { type MemoryScope } from './memory';
4
+ export declare const MODEL_CONTEXT_TOKENS: Record<string, number>;
5
+ /**
6
+ * Context window (tokens) for a model alias or real model id.
7
+ *
8
+ * Checks the LIVE catalogue (GET /api/code/models, modelCatalogue.ts) first —
9
+ * populated once per process by whichever client fetched it (CLI at session
10
+ * start, VS Code via _postModelCatalogue, desktop via its main-process
11
+ * fetch) — falling back to this hard-coded table when no live data exists yet
12
+ * (offline, older backend, or the catalogue simply hasn't been fetched by
13
+ * this call site). This is what lets a model added to the backend registry
14
+ * (services/providers/modelRegistry.js) get the CORRECT context window here
15
+ * even before this table is updated by hand for a new nexrall-code release —
16
+ * exactly the class of bug GPT-5.6's 922K-vs-1.05M mismatch was (see
17
+ * modelRegistry.js's own comment on that row).
18
+ *
19
+ * The static-table fallback is deliberately the SMALLEST window in the table
20
+ * rather than the largest. An unknown model is most likely a newly added one
21
+ * this client build predates, and guessing high is the failure that cannot be
22
+ * recovered from: the turn hits a provider 400 with no chance to compact.
23
+ * Guessing low only costs an earlier, lossy compaction — annoying, not broken.
24
+ */
25
+ export declare function contextWindowFor(model?: string): number;
26
+ /** Token counts at which auto-prune and auto-compact (summarise) fire for a model window. */
27
+ export declare function compactionLimits(contextWindow: number, settingsRaw?: Record<string, unknown>): {
28
+ prune: number;
29
+ compact: number;
30
+ };
31
+ /** Auto-prune / auto-compact thresholds as fractions of the context window — for UI display (e.g. `/context`). */
32
+ export declare function compactionThresholds(contextWindow?: number, settingsRaw?: Record<string, unknown>): {
33
+ prune: number;
34
+ compact: number;
35
+ };
36
+ export declare const PRUNE_MIN_RECLAIM_BYTES: number;
37
+ export declare const _lastApiCallEndedAt: Map<string, number>;
38
+ export declare function pruneReclaimFloor(lastCallEndedAt: number | undefined, now?: number): number;
39
+ export declare const COMPACT_KEEP_MIN = 6;
40
+ /**
41
+ * Bytes a compaction must reclaim to count as productive.
42
+ *
43
+ * Deliberately much smaller than PRUNE_MIN_RECLAIM_BYTES: a prune declines when the
44
+ * gain isn't worth busting the prompt cache, whereas by the time we are summarising
45
+ * we are already committed to rewriting the prefix — the only question is whether the
46
+ * summariser is making ANY headway. 32 KB is small enough that a genuinely useful
47
+ * compaction always clears it, large enough that shuffling a few bytes doesn't.
48
+ */
49
+ export declare const COMPACT_MIN_RECLAIM_BYTES: number;
50
+ /**
51
+ * Consecutive non-productive compaction attempts before auto-compaction is switched
52
+ * off for the rest of the run.
53
+ *
54
+ * 3 rather than 1 because the failure is often transient — a summariser stream that
55
+ * blipped will usually succeed on the next turn, and giving up instantly would lose
56
+ * the safety net for a whole long session over one network hiccup. 3 also bounds the
57
+ * wasted spend: at most three summariser calls, not hundreds.
58
+ */
59
+ export declare const COMPACT_MAX_FAILURES = 3;
60
+ export declare const MAX_BODY_BYTES: number;
61
+ /** Approximate serialised request-body size (bytes) for the messages array. */
62
+ export declare function estimateBodyBytes(messages: Message[]): number;
63
+ export declare function resolveAutoCompact(fromOptions: boolean | undefined, rawSettings: Record<string, unknown>): boolean;
64
+ /** Opt-out for the one-shot verification nudge (GAP D). Defaults to on. */
65
+ export declare function resolveVerificationNudge(rawSettings: Record<string, unknown>): boolean;
66
+ /** Tools that mutate the filesystem — used by the verification nudge (GAP D). */
67
+ export declare const WRITE_TOOL_NAMES: Set<string>;
68
+ /**
69
+ * May an agent restricted to `testFilesOnly` perform this tool call?
70
+ *
71
+ * A tool allowlist is all-or-nothing per tool: granting `edit_file` grants it for
72
+ * every path in the repo. A user-defined test-writer agent needs write access to produce
73
+ * tests, but must NOT be able to "fix" production source so a failing test goes
74
+ * green — the single most common way a test-writing agent destroys the signal it
75
+ * was asked to create. Its prompt says so; this makes it a refusal rather than a
76
+ * request.
77
+ *
78
+ * Pure + exported so the rules are testable directly, without running a real
79
+ * sub-agent.
80
+ *
81
+ * KNOWN LIMIT, stated rather than hidden: this gates the file TOOLS, not `bash`.
82
+ * A determined model could still write source via `bash: echo ... > src/x.ts`.
83
+ * Closing that means parsing shell redirection, which is not reliably doable — so
84
+ * this is a strong guardrail against the realistic failure mode, not a sandbox.
85
+ * Real isolation is the sandbox config (tools/sandbox.ts), a separate mechanism.
86
+ */
87
+ export declare function allowsTestOnlyWrite(tool: string, input: Record<string, unknown> | undefined): boolean;
88
+ /** Heuristic: does a bash command look like it's running tests/build/lint/typecheck? (GAP D) */
89
+ export declare const VERIFY_CMD_RE: RegExp;
90
+ /**
91
+ * Find the latest index ≤ maxIdx where history can be cut safely.
92
+ *
93
+ * A safe cut point is a **turn boundary**: an assistant message (which always
94
+ * begins a fresh turn after a user message). Cutting there guarantees that
95
+ * `messages[cut..]` starts with an assistant whose `tool_use` blocks are all
96
+ * answered by `tool_result`s that remain in the kept slice — so we never orphan
97
+ * a tool_result (which the API rejects). We deliberately allow cutting across
98
+ * tool_result-bearing user messages: the OLD implementation only cut at a
99
+ * *non*-tool_result user message, which never exists inside a single long
100
+ * agentic run (every user turn is a tool_result), so compaction was a no-op
101
+ * exactly when a long task needs it most.
102
+ */
103
+ export declare function findSafeCutIndex(messages: Message[], maxIdx: number): number;
104
+ /**
105
+ * Render messages to a plain-text transcript for the summariser (tool noise
106
+ * truncated per-block AND the whole transcript hard-capped). When the transcript
107
+ * would exceed MAX_TRANSCRIPT_CHARS we keep the HEAD (original task + early
108
+ * decisions) and the TAIL (most-recent, highest-signal context) and drop the
109
+ * middle — a middle-out elision that preserves both "what we set out to do" and
110
+ * "where we are now", which is what the continuation summary needs most.
111
+ */
112
+ /**
113
+ * Appends the backend-announced runtime-context block to the user message it was
114
+ * attached to. No-op if that message is not a user turn or already ends with the
115
+ * identical block. Exported for tests.
116
+ */
117
+ export declare function persistRuntimeContext(messages: Message[], idx: number, text: string): boolean;
118
+ export declare function transcriptOf(messages: Message[]): string;
119
+ export interface ProgressLedger {
120
+ filesTouched: Map<string, {
121
+ tool: string;
122
+ edits: number;
123
+ }>;
124
+ /**
125
+ * DISTINCT paths ever touched, including any since evicted from `filesTouched`.
126
+ *
127
+ * The Map is bounded (see ledgerRecord), so `filesTouched.size` is a window, not a
128
+ * total. The preamble states "FILES CHANGED THIS SESSION (N)" as a fact the model
129
+ * reasons about, so N must not silently shrink when eviction kicks in on a very long
130
+ * run — that would tell the model less work happened than actually did.
131
+ */
132
+ filesTouchedTotal: number;
133
+ verifications: Array<{
134
+ cmd: string;
135
+ ok: boolean;
136
+ epoch: number;
137
+ }>;
138
+ /** Test-integrity findings (reward-hacking signals) that must survive compaction. */
139
+ testIntegrity: Array<{
140
+ path: string;
141
+ reason: string;
142
+ }>;
143
+ /**
144
+ * TOTAL test-integrity findings ever recorded, including ones since trimmed.
145
+ *
146
+ * `testIntegrity` is a bounded window (older entries are spliced off once it grows
147
+ * past 2×LEDGER_MAX_NOTES), so its `.length` STOPS being a running total after the
148
+ * first trim. The one-shot nudge compares "how many findings exist" against "how
149
+ * many I've already surfaced", and comparing against a window that shrinks meant the
150
+ * count could never move ahead again — silently disabling the reward-hacking warning
151
+ * for the remainder of a long session, i.e. exactly when it matters most.
152
+ *
153
+ * This counter only ever increases, so it is a safe basis for that comparison.
154
+ */
155
+ testIntegrityTotal: number;
156
+ /**
157
+ * Monotonic mutation epoch: incremented on every successful source write. Two
158
+ * verification runs sharing an epoch had NO edit between them, so a PASS↔FAIL
159
+ * flip across that boundary proves the test is flaky (see detectFlaky).
160
+ */
161
+ epoch: number;
162
+ }
163
+ export declare function createLedger(): ProgressLedger;
164
+ /** Record one tool call's effect on the ledger (deterministic, no model call). */
165
+ export declare function ledgerRecord(ledger: ProgressLedger, toolName: string, input: Record<string, unknown> | undefined, ok: boolean, output?: string, exitCode?: number): void;
166
+ /** Render the ledger as a compact, verbatim block for the compaction preamble. */
167
+ export declare function ledgerSummary(ledger: ProgressLedger): string;
168
+ export declare const PRUNE_KEEP_RECENT = 8;
169
+ /**
170
+ * Lossy-but-structure-preserving prune: shrink OLD, large tool_result blocks in
171
+ * place, keeping the last PRUNE_KEEP_RECENT messages untouched. This is tried
172
+ * BEFORE summarisation because it:
173
+ * • keeps every turn and every tool_use/tool_result pair (API stays valid),
174
+ * • never makes an extra model call (summarisation does — cost + latency),
175
+ * • degrades gracefully on repeat (summarise-of-summarise loses the most on
176
+ * long runs; pruning just trims already-consumed output further).
177
+ *
178
+ * IMPORTANT: pruned state is encoded in the content string (PRUNE_MARKER_TAIL
179
+ * suffix), NOT as an extra property on the block — a stray field on a content
180
+ * block is rejected by the Anthropic API as an unknown key (400). This keeps the
181
+ * serialised body schema-clean while remaining idempotent across repeat calls.
182
+ *
183
+ * Returns the number of bytes reclaimed (0 if nothing was prunable).
184
+ *
185
+ * `minReclaimBytes` (default 0): if the TOTAL prunable amount is below this, the
186
+ * function makes NO changes and returns 0. This is a cache-safety gate — pruning
187
+ * even one old block changes the request prefix and invalidates the message-level
188
+ * prompt cache, so a tiny prune would bust the cache (re-write at 1.25×) for
189
+ * almost no size win. Measuring first, then applying only if worthwhile, keeps
190
+ * the "don't bust cache for a trivial gain" contract truly atomic (the old code
191
+ * mutated first and let the caller decide, which had already invalidated the
192
+ * cache by the time the caller declined).
193
+ */
194
+ export declare function pruneOldToolResults(messages: Message[], minReclaimBytes?: number): number;
195
+ /**
196
+ * The summariser's own model call failed — as opposed to running fine but not
197
+ * shrinking anything.
198
+ *
199
+ * These two outcomes used to be one `return false`, and collapsing them was a
200
+ * real bug: the in-loop circuit breaker disables auto-compaction permanently
201
+ * after COMPACT_MAX_FAILURES, on the sound theory that a compaction which cannot
202
+ * reclaim bytes will never start. But a summariser that THREW says nothing about
203
+ * whether compaction would help — only that the network/provider was unavailable
204
+ * for a moment. Feeding those into the same counter meant three transient blips
205
+ * (a 529 burst, a brief outage, a rate-limit spike) permanently switched off the
206
+ * one mechanism keeping the context under control, and the run then died at the
207
+ * context wall minutes later with its own recovery already disabled.
208
+ */
209
+ export declare class CompactionUnavailableError extends Error {
210
+ constructor();
211
+ }
212
+ /**
213
+ * Summarises the WHOLE conversation by appending the instruction to its final user
214
+ * message and sending it with the conversation's own request options — Claude Code's
215
+ * approach. The prefix is byte-identical to the previous request, so the history is a
216
+ * cache READ (0.10×) instead of a fresh uncached transcript of up to 600K chars.
217
+ * Returns '' when it cannot be used (last turn is not the user's) or yields no text.
218
+ */
219
+ export type CachedSummarizer = (instruction: string) => Promise<string>;
220
+ export declare function makeCachedSummarizer(messages: Message[], requestOptions: () => Parameters<typeof streamChat>[1], abortSignal?: {
221
+ aborted: boolean;
222
+ }): CachedSummarizer;
223
+ export declare function autoCompactMessages(messages: Message[], options: AgentLoopOptions, ledger?: ProgressLedger, summarizeCached?: CachedSummarizer): Promise<boolean>;
224
+ export declare function maybeCompactMemory(scope: MemoryScope, options: AgentLoopOptions): Promise<void>;
225
+ /** Rough token estimate for a resumed transcript — no API round-trip needed. */
226
+ export declare function estimateTokensRough(messages: Message[]): number;
227
+ /**
228
+ * Proactively compact `messages` in place if resuming this session would blow
229
+ * past the auto-compact threshold on the very first turn. Returns true if any
230
+ * compaction happened (so the caller can surface a one-line notice to the
231
+ * user). Safe to call on any message array, including empty/small ones (no-op).
232
+ *
233
+ * `model` picks the right context window (mirrors runAgentLoop's own lookup);
234
+ * `onNotice` is optional — pass it to show the same "auto-compacted" message
235
+ * the in-loop path shows, so the behaviour is visually consistent.
236
+ */
237
+ export declare function compactMessagesForResume(messages: Message[], opts: {
238
+ model?: string;
239
+ workDir: string;
240
+ clientType?: string;
241
+ env?: EnvContext;
242
+ onNotice?: (text: string) => void;
243
+ }): Promise<boolean>;
244
+ //# sourceMappingURL=compaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/agent/compaction.ts"],"names":[],"mappings":"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"}