@nexrall/code-core 1.4.22 → 1.4.24
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/dist/agent/agentTypes.d.ts +35 -2
- package/dist/agent/agentTypes.d.ts.map +1 -1
- package/dist/agent/agentTypes.js +241 -6
- package/dist/agent/loop.d.ts +56 -0
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +286 -24
- package/dist/agent/securityLint.d.ts +27 -0
- package/dist/agent/securityLint.d.ts.map +1 -0
- package/dist/agent/securityLint.js +195 -0
- package/dist/api/client.d.ts +12 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +351 -77
- package/dist/auth/index.d.ts +21 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +53 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/tools/executor.d.ts.map +1 -1
- package/dist/tools/executor.js +124 -18
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -8,10 +8,43 @@ export interface AgentType {
|
|
|
8
8
|
/** System instructions (the markdown body below the frontmatter). */
|
|
9
9
|
prompt: string;
|
|
10
10
|
source: 'project' | 'global' | 'builtin' | 'plugin';
|
|
11
|
+
/**
|
|
12
|
+
* When true, this agent's write tools may only target TEST files.
|
|
13
|
+
*
|
|
14
|
+
* Needed because a tool allowlist is all-or-nothing per tool: granting
|
|
15
|
+
* `edit_file` grants it for every path. The `test-writer` agent must be able to
|
|
16
|
+
* write tests while being unable to "fix" production source to make a test
|
|
17
|
+
* pass — the single most common way a test-writing agent destroys signal — and
|
|
18
|
+
* a prompt instruction alone cannot guarantee that. Enforced in loop.ts's
|
|
19
|
+
* permission gate, where it is a real refusal rather than a request.
|
|
20
|
+
*/
|
|
21
|
+
testFilesOnly?: boolean;
|
|
11
22
|
}
|
|
12
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Discover all agent types. Precedence: project > global > plugin > builtin.
|
|
25
|
+
*
|
|
26
|
+
* Results are returned in a STABLE order (builtins in declared order, then
|
|
27
|
+
* user-supplied ones alphabetically) rather than in discovery order. The
|
|
28
|
+
* system-prompt catalogue is built from this, and a set that reshuffles between
|
|
29
|
+
* runs would silently bust the prompt cache on the block it lives in — filesystem
|
|
30
|
+
* readdir order is not guaranteed to be stable across machines or platforms.
|
|
31
|
+
*/
|
|
13
32
|
export declare function loadAgentTypes(workDir: string): AgentType[];
|
|
14
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* One line per agent for the system prompt's <available_subagents> block.
|
|
35
|
+
*
|
|
36
|
+
* Reports each agent's CAPABILITY CLASS rather than enumerating its allowlist.
|
|
37
|
+
* The full lists (~15 tool names each) went into every single request while
|
|
38
|
+
* telling the model nothing it needs in order to choose: what matters when
|
|
39
|
+
* delegating is "can this one edit files?" and "what is it for?", not whether
|
|
40
|
+
* `get_hover` happens to be included. With six builtins the verbatim lists cost
|
|
41
|
+
* ~670 tokens per request, most of it near-identical boilerplate that also
|
|
42
|
+
* weakens the signal it was meant to carry.
|
|
43
|
+
*
|
|
44
|
+
* The per-agent description already states its own restrictions in prose, and the
|
|
45
|
+
* allowlist is enforced at the permission gate regardless of what is advertised
|
|
46
|
+
* here — so this is purely a summary, never the mechanism.
|
|
47
|
+
*/
|
|
15
48
|
export declare function summariseAgents(types: AgentType[]): string;
|
|
16
49
|
export declare function findAgentType(types: AgentType[], name: string | undefined): AgentType | undefined;
|
|
17
50
|
//# sourceMappingURL=agentTypes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentTypes.d.ts","sourceRoot":"","sources":["../../src/agent/agentTypes.ts"],"names":[],"mappings":"AAuBA,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,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;IAClC,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"agentTypes.d.ts","sourceRoot":"","sources":["../../src/agent/agentTypes.ts"],"names":[],"mappings":"AAuBA,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,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;IAClC,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACpD;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA4RD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CAmB3D;AACD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAY1D;AAQD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAIjG"}
|
package/dist/agent/agentTypes.js
CHANGED
|
@@ -43,11 +43,37 @@ const index_1 = require("../plugins/index");
|
|
|
43
43
|
// ── Built-in agent types ──────────────────────────────────────────────────────
|
|
44
44
|
// Shipped defaults; lowest precedence (project > global > builtin), so a user
|
|
45
45
|
// can override any of them with a same-name .nexrall/agents/<name>.md file.
|
|
46
|
+
// Shared read-only tool set.
|
|
47
|
+
//
|
|
48
|
+
// An allowlist only ever GRANTS — a name that doesn't exist on the current client
|
|
49
|
+
// is simply never offered to the model, so listing the VS Code language-server
|
|
50
|
+
// tools alongside the CLI ones is safe and gives each agent the best available
|
|
51
|
+
// capability on whichever client it runs.
|
|
52
|
+
//
|
|
53
|
+
// This exists because it was previously inlined per agent, and the one agent that
|
|
54
|
+
// had it (`reviewer`) listed five VS Code-only tools, leaving it with just five
|
|
55
|
+
// usable tools when run from the CLI — a silent capability gap that is very easy
|
|
56
|
+
// to reintroduce by copy-pasting a list.
|
|
57
|
+
const READ_ONLY_TOOLS = [
|
|
58
|
+
// Universal
|
|
59
|
+
'read_file', 'search_files', 'glob', 'list_directory', 'bash', 'bash_output',
|
|
60
|
+
'notebook_read', 'todo_write', 'todo_read',
|
|
61
|
+
// VS Code language server (ignored on the CLI)
|
|
62
|
+
'get_symbols', 'get_workspace_symbols', 'find_references', 'go_to_definition',
|
|
63
|
+
'get_hover', 'get_diagnostics',
|
|
64
|
+
];
|
|
65
|
+
/** Read-only + the network, for agents that must consult external sources. */
|
|
66
|
+
const RESEARCH_TOOLS = [...READ_ONLY_TOOLS, 'web_search', 'fetch_url'];
|
|
67
|
+
/** Read-only + the write tools, for agents that produce code. */
|
|
68
|
+
const WRITE_TOOLS = [
|
|
69
|
+
...READ_ONLY_TOOLS,
|
|
70
|
+
'write_file', 'edit_file', 'multi_edit', 'create_directory', 'move_file', 'copy_file',
|
|
71
|
+
];
|
|
46
72
|
const BUILTIN_AGENTS = [
|
|
47
73
|
{
|
|
48
74
|
name: 'reviewer',
|
|
49
75
|
description: 'Read-only code reviewer — finds correctness bugs, edge cases, and security issues in a diff or file set. Cannot modify files.',
|
|
50
|
-
tools:
|
|
76
|
+
tools: READ_ONLY_TOOLS,
|
|
51
77
|
source: 'builtin',
|
|
52
78
|
prompt: [
|
|
53
79
|
'You are a meticulous senior code reviewer. You NEVER modify files — you only read, search, and report.',
|
|
@@ -64,6 +90,162 @@ const BUILTIN_AGENTS = [
|
|
|
64
90
|
'then a final verdict (APPROVE or REQUEST CHANGES) with a one-paragraph rationale.',
|
|
65
91
|
].join('\n'),
|
|
66
92
|
},
|
|
93
|
+
// Promoted from the security-audit plugin to a builtin.
|
|
94
|
+
//
|
|
95
|
+
// Leaving it plugin-only was indefensible next to `reviewer` being builtin:
|
|
96
|
+
// reviewer's own prompt already tells it to look for security issues, so
|
|
97
|
+
// security IS treated as default work — yet the specialist agent for it was
|
|
98
|
+
// invisible unless the user happened to know the plugin existed. For an agent
|
|
99
|
+
// that WRITES code, "you only get a security review if you knew to install
|
|
100
|
+
// something" is the wrong default.
|
|
101
|
+
{
|
|
102
|
+
name: 'security-auditor',
|
|
103
|
+
description: 'Read-only security auditor — hunts injection, authz, secrets, and validation flaws in a path or diff. Cannot modify files.',
|
|
104
|
+
tools: READ_ONLY_TOOLS,
|
|
105
|
+
model: 'pro',
|
|
106
|
+
source: 'builtin',
|
|
107
|
+
prompt: [
|
|
108
|
+
'You are a security auditor. You find real, exploitable flaws — not style issues.',
|
|
109
|
+
'',
|
|
110
|
+
'Method:',
|
|
111
|
+
'1. Map the attack surface FIRST: entry points (HTTP routes, message handlers, CLI args, file/network',
|
|
112
|
+
' input, deserialization), then trace user-controlled data inward to where it is used.',
|
|
113
|
+
'2. For each finding: file:line, the flaw class, a one-line exploit scenario, and the concrete fix.',
|
|
114
|
+
'3. Grade severity honestly: Critical = remote compromise or data breach; High = auth bypass/IDOR;',
|
|
115
|
+
' Medium = needs unusual preconditions; Low = hardening.',
|
|
116
|
+
'',
|
|
117
|
+
'Classes worth the most attention, in order: injection (SQL/command/template/prototype), broken',
|
|
118
|
+
'authz (missing ownership checks, IDOR, trusting client-supplied ids), secrets committed to source,',
|
|
119
|
+
'path traversal, SSRF, unsafe deserialization, missing rate limits on expensive or auth endpoints,',
|
|
120
|
+
'and crypto misuse (hand-rolled comparison, predictable randomness).',
|
|
121
|
+
'',
|
|
122
|
+
'Hard rules:',
|
|
123
|
+
'- READ-ONLY: never modify, create or delete files. bash only for read-only inspection.',
|
|
124
|
+
'- NEVER print a discovered secret\'s value. Report its location and advise rotation.',
|
|
125
|
+
'- Distinguish EXPLOITABLE from theoretical, and say which one each finding is.',
|
|
126
|
+
'- "No issues found in scope X" is a valid, useful result. Do not pad the report to look thorough.',
|
|
127
|
+
].join('\n'),
|
|
128
|
+
},
|
|
129
|
+
// The gap Claude Code fills with its built-in `Explore`: read-heavy codebase
|
|
130
|
+
// search that would otherwise flood the parent's context. Defaults to the
|
|
131
|
+
// cheapest model on purpose — "find every caller of X" has no need of a
|
|
132
|
+
// frontier model, and this is the agent most likely to be spawned in bulk.
|
|
133
|
+
{
|
|
134
|
+
name: 'explorer',
|
|
135
|
+
description: 'Fast read-only codebase explorer — locates files, symbols, and call sites and reports concise findings. Use to keep bulk searching out of the main context. Cannot modify files.',
|
|
136
|
+
tools: READ_ONLY_TOOLS,
|
|
137
|
+
model: 'turbo',
|
|
138
|
+
source: 'builtin',
|
|
139
|
+
prompt: [
|
|
140
|
+
'You map code. You NEVER modify anything.',
|
|
141
|
+
'',
|
|
142
|
+
'Method:',
|
|
143
|
+
'1. Prefer structural search over text search where available (get_workspace_symbols, find_references,',
|
|
144
|
+
' go_to_definition); fall back to search_files/glob otherwise.',
|
|
145
|
+
'2. Read only the sections you need — use read_file with offset/limit on large files instead of',
|
|
146
|
+
' pulling in thousands of lines.',
|
|
147
|
+
'3. Follow the real call graph rather than guessing from names.',
|
|
148
|
+
'',
|
|
149
|
+
'Your ONLY output is a compact report: the file:line locations that matter, how they relate, and the',
|
|
150
|
+
'direct answer to the question you were given. This exists to keep bulk search OUT of the parent\'s',
|
|
151
|
+
'context, so do not paste large file contents back — cite locations and summarise. Say plainly when',
|
|
152
|
+
'something does not exist; a confident wrong answer is far worse than "not found".',
|
|
153
|
+
].join('\n'),
|
|
154
|
+
},
|
|
155
|
+
// Matches Claude Code's built-in `Plan`: research a change and return a
|
|
156
|
+
// strategy, deliberately WITHOUT write access so "make a plan" can never
|
|
157
|
+
// quietly become "start editing".
|
|
158
|
+
{
|
|
159
|
+
name: 'planner',
|
|
160
|
+
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.',
|
|
161
|
+
tools: RESEARCH_TOOLS,
|
|
162
|
+
model: 'pro',
|
|
163
|
+
source: 'builtin',
|
|
164
|
+
prompt: [
|
|
165
|
+
'You produce implementation plans. You NEVER modify files — planning and doing are separate steps,',
|
|
166
|
+
'and this agent exists so "plan it" cannot silently turn into "change it".',
|
|
167
|
+
'',
|
|
168
|
+
'Method:',
|
|
169
|
+
'1. Read the actual code before proposing anything. No plan may rest on an assumed API shape.',
|
|
170
|
+
'2. Find every affected call site (find_references / search_files) and list them.',
|
|
171
|
+
'3. Order the steps so the tree stays working after each one — types, then implementation, then',
|
|
172
|
+
' tests, then exports/registration.',
|
|
173
|
+
'',
|
|
174
|
+
'Output:',
|
|
175
|
+
'- Goal, in one sentence.',
|
|
176
|
+
'- Numbered steps, each with the exact files touched and what changes in them.',
|
|
177
|
+
'- Risks + the specific thing that could break, and how it would be detected.',
|
|
178
|
+
'- How to verify (the exact test/build command for THIS project, taken from package.json/Makefile).',
|
|
179
|
+
'- Anything genuinely ambiguous, stated as an open question rather than a silent assumption.',
|
|
180
|
+
].join('\n'),
|
|
181
|
+
},
|
|
182
|
+
// Promoted from the test-gen plugin. Needs write access — it produces test
|
|
183
|
+
// files — but is deliberately forbidden from touching source, because "make the
|
|
184
|
+
// tests pass" is the single most common way an agent destroys signal.
|
|
185
|
+
{
|
|
186
|
+
name: 'test-writer',
|
|
187
|
+
description: 'Writes tests that follow the project\'s existing conventions. May create/edit TEST files only — never production source.',
|
|
188
|
+
tools: WRITE_TOOLS,
|
|
189
|
+
// Enforced, not merely requested: the permission gate refuses a write whose
|
|
190
|
+
// path is not a test file. Without this the allowlist would grant edit_file
|
|
191
|
+
// for every path and the rule below would be a suggestion the model is free
|
|
192
|
+
// to rationalise its way past.
|
|
193
|
+
testFilesOnly: true,
|
|
194
|
+
source: 'builtin',
|
|
195
|
+
prompt: [
|
|
196
|
+
'You write tests. You may create and edit TEST files only.',
|
|
197
|
+
'',
|
|
198
|
+
'Hard rules — these are the ways test-writing agents destroy value, so they are non-negotiable:',
|
|
199
|
+
'- NEVER modify production source to make a test pass. If the code looks wrong, REPORT it and stop.',
|
|
200
|
+
'- NEVER weaken, delete or skip an existing assertion or test.',
|
|
201
|
+
'- A test that cannot fail is worse than no test. Every test must be able to fail for one clear reason.',
|
|
202
|
+
'',
|
|
203
|
+
'Method:',
|
|
204
|
+
'1. Read the existing tests FIRST and copy their conventions exactly — runner, file naming, layout,',
|
|
205
|
+
' assertion style, fixture/helper patterns. Never introduce a new framework.',
|
|
206
|
+
'2. Test observable behaviour and the contract, not private internals.',
|
|
207
|
+
'3. Cover the boring-but-real cases: empty input, null/undefined, unicode and non-BMP characters,',
|
|
208
|
+
' boundaries, error paths, concurrency where it applies.',
|
|
209
|
+
'4. No sleeps or wall-clock dependence — those produce the flaky tests that get deleted later.',
|
|
210
|
+
'5. RUN the tests you wrote and report the real output. Never claim a test passes without running it.',
|
|
211
|
+
].join('\n'),
|
|
212
|
+
},
|
|
213
|
+
// The DevOps gap — answered with a READ-ONLY advisor, not an operator.
|
|
214
|
+
//
|
|
215
|
+
// A "DevOps agent" with write/apply access is a genuinely different risk class
|
|
216
|
+
// from the others here: its mistakes are `kubectl delete`, a bad `terraform
|
|
217
|
+
// apply`, a broken deploy pipeline — often not revertible and affecting
|
|
218
|
+
// production rather than a working tree. So this one diagnoses and proposes a
|
|
219
|
+
// diff; a human applies it. That asymmetry is the whole design.
|
|
220
|
+
{
|
|
221
|
+
name: 'devops-advisor',
|
|
222
|
+
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.',
|
|
223
|
+
tools: RESEARCH_TOOLS,
|
|
224
|
+
model: 'pro',
|
|
225
|
+
source: 'builtin',
|
|
226
|
+
prompt: [
|
|
227
|
+
'You are an infrastructure and delivery advisor. You DIAGNOSE and PROPOSE. You never apply changes.',
|
|
228
|
+
'',
|
|
229
|
+
'Hard rules:',
|
|
230
|
+
'- READ-ONLY, and stricter than the other read-only agents: bash is for INSPECTION only',
|
|
231
|
+
' (git log/diff, cat, grep, `kubectl get/describe`, `docker images`, `terraform plan`).',
|
|
232
|
+
' NEVER run anything that mutates infrastructure — no apply/delete/scale/rollout/restart/push,',
|
|
233
|
+
' no `terraform apply`, no `helm upgrade`. If a fix needs such a command, WRITE IT OUT for a human.',
|
|
234
|
+
'- Never print secret values from env files, k8s Secrets or CI variables. Reference them by name.',
|
|
235
|
+
'',
|
|
236
|
+
'Method:',
|
|
237
|
+
'1. Read what actually exists — workflow files, Dockerfiles, manifests, kustomize overlays, the',
|
|
238
|
+
' deploy scripts — before drawing any conclusion. Never reason from what a stack "usually" looks like.',
|
|
239
|
+
'2. Follow the real path a change takes to production, and name the step that is broken or missing.',
|
|
240
|
+
'3. Check the failure modes that bite hardest: CI path filters that skip files a workload actually',
|
|
241
|
+
' needs, image tags that do not match what is deployed, missing health probes, absent resource',
|
|
242
|
+
' limits, secrets baked into images, ports/timeouts inconsistent between proxy and app, and',
|
|
243
|
+
' migrations that must run before the new image is live.',
|
|
244
|
+
'',
|
|
245
|
+
'Output: the diagnosis, the evidence (file:line or command output), the proposed change as a diff or',
|
|
246
|
+
'exact file content, and the command a human should run to apply and verify it.',
|
|
247
|
+
].join('\n'),
|
|
248
|
+
},
|
|
67
249
|
];
|
|
68
250
|
function parseFrontmatter(raw) {
|
|
69
251
|
const m = /^\s*---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(raw);
|
|
@@ -81,6 +263,10 @@ function parseModel(v) {
|
|
|
81
263
|
const s = (v ?? '').toLowerCase();
|
|
82
264
|
return s === 'turbo' || s === 'pro' || s === 'ultra' ? s : undefined;
|
|
83
265
|
}
|
|
266
|
+
/** Parse a frontmatter boolean, accepting the usual truthy spellings. */
|
|
267
|
+
function parseBool(v) {
|
|
268
|
+
return /^(true|yes|1|on)$/i.test((v ?? '').trim());
|
|
269
|
+
}
|
|
84
270
|
function parseToolList(v) {
|
|
85
271
|
if (!v)
|
|
86
272
|
return undefined;
|
|
@@ -116,6 +302,11 @@ function loadDir(dir, source, into) {
|
|
|
116
302
|
model: parseModel(meta.model),
|
|
117
303
|
prompt: body,
|
|
118
304
|
source,
|
|
305
|
+
// Exposed to user/plugin definitions too — `test_files_only: true` (or
|
|
306
|
+
// `testFilesOnly`) lets anyone build a test-writing agent that genuinely
|
|
307
|
+
// cannot touch production source, rather than only the builtin getting
|
|
308
|
+
// that guarantee.
|
|
309
|
+
...(parseBool(meta.test_files_only ?? meta.testfilesonly) ? { testFilesOnly: true } : {}),
|
|
119
310
|
});
|
|
120
311
|
}
|
|
121
312
|
catch {
|
|
@@ -123,7 +314,15 @@ function loadDir(dir, source, into) {
|
|
|
123
314
|
}
|
|
124
315
|
}
|
|
125
316
|
}
|
|
126
|
-
/**
|
|
317
|
+
/**
|
|
318
|
+
* Discover all agent types. Precedence: project > global > plugin > builtin.
|
|
319
|
+
*
|
|
320
|
+
* Results are returned in a STABLE order (builtins in declared order, then
|
|
321
|
+
* user-supplied ones alphabetically) rather than in discovery order. The
|
|
322
|
+
* system-prompt catalogue is built from this, and a set that reshuffles between
|
|
323
|
+
* runs would silently bust the prompt cache on the block it lives in — filesystem
|
|
324
|
+
* readdir order is not guaranteed to be stable across machines or platforms.
|
|
325
|
+
*/
|
|
127
326
|
function loadAgentTypes(workDir) {
|
|
128
327
|
const out = new Map();
|
|
129
328
|
loadDir(path.join(workDir, '.nexrall', 'agents'), 'project', out);
|
|
@@ -134,19 +333,55 @@ function loadAgentTypes(workDir) {
|
|
|
134
333
|
if (!out.has(agent.name))
|
|
135
334
|
out.set(agent.name, agent);
|
|
136
335
|
}
|
|
137
|
-
|
|
336
|
+
// Builtins first in their declared order (the common, cache-friendly case), then
|
|
337
|
+
// everything user-supplied alphabetically.
|
|
338
|
+
const builtinOrder = new Map(BUILTIN_AGENTS.map((a, i) => [a.name, i]));
|
|
339
|
+
return [...out.values()].sort((a, b) => {
|
|
340
|
+
const ai = builtinOrder.get(a.name);
|
|
341
|
+
const bi = builtinOrder.get(b.name);
|
|
342
|
+
if (ai !== undefined && bi !== undefined)
|
|
343
|
+
return ai - bi;
|
|
344
|
+
if (ai !== undefined)
|
|
345
|
+
return -1;
|
|
346
|
+
if (bi !== undefined)
|
|
347
|
+
return 1;
|
|
348
|
+
return a.name.localeCompare(b.name);
|
|
349
|
+
});
|
|
138
350
|
}
|
|
139
|
-
/**
|
|
351
|
+
/**
|
|
352
|
+
* One line per agent for the system prompt's <available_subagents> block.
|
|
353
|
+
*
|
|
354
|
+
* Reports each agent's CAPABILITY CLASS rather than enumerating its allowlist.
|
|
355
|
+
* The full lists (~15 tool names each) went into every single request while
|
|
356
|
+
* telling the model nothing it needs in order to choose: what matters when
|
|
357
|
+
* delegating is "can this one edit files?" and "what is it for?", not whether
|
|
358
|
+
* `get_hover` happens to be included. With six builtins the verbatim lists cost
|
|
359
|
+
* ~670 tokens per request, most of it near-identical boilerplate that also
|
|
360
|
+
* weakens the signal it was meant to carry.
|
|
361
|
+
*
|
|
362
|
+
* The per-agent description already states its own restrictions in prose, and the
|
|
363
|
+
* allowlist is enforced at the permission gate regardless of what is advertised
|
|
364
|
+
* here — so this is purely a summary, never the mechanism.
|
|
365
|
+
*/
|
|
140
366
|
function summariseAgents(types) {
|
|
141
367
|
if (!types.length)
|
|
142
368
|
return '';
|
|
143
369
|
return types
|
|
144
370
|
.map((t) => {
|
|
145
|
-
const
|
|
146
|
-
|
|
371
|
+
const canWrite = !t.tools || t.tools.some((x) => WRITE_TOOL_HINTS.has(x));
|
|
372
|
+
const access = t.testFilesOnly
|
|
373
|
+
? 'writes TEST files only'
|
|
374
|
+
: canWrite ? 'can modify files' : 'read-only';
|
|
375
|
+
const model = t.model ? `, ${t.model} model` : '';
|
|
376
|
+
return `- ${t.name} (${access}${model}): ${t.description}`;
|
|
147
377
|
})
|
|
148
378
|
.join('\n');
|
|
149
379
|
}
|
|
380
|
+
/** Tool names that imply write access, for the summary line above. */
|
|
381
|
+
const WRITE_TOOL_HINTS = new Set([
|
|
382
|
+
'write_file', 'edit_file', 'multi_edit', 'notebook_edit',
|
|
383
|
+
'delete_file', 'move_file', 'copy_file',
|
|
384
|
+
]);
|
|
150
385
|
function findAgentType(types, name) {
|
|
151
386
|
if (!name)
|
|
152
387
|
return undefined;
|
package/dist/agent/loop.d.ts
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
import type { Message, AgentLoopOptions, EnvContext } from '../types';
|
|
2
2
|
export declare function resolveMaxIterations(optionValue: number | undefined, settingsRaw: Record<string, unknown>): number;
|
|
3
|
+
/**
|
|
4
|
+
* Minimal concurrency gate. Hand-rolled rather than pulling in `p-limit` because
|
|
5
|
+
* the CLI ships as a single esbuild bundle with no node_modules, and this is a
|
|
6
|
+
* dozen lines.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createLimiter(max: number): <T>(fn: () => Promise<T>) => Promise<T>;
|
|
9
|
+
/**
|
|
10
|
+
* Reduce a sub-agent's message history to the text its parent should receive.
|
|
11
|
+
*
|
|
12
|
+
* Pure + exported so the salvage rules can be tested without running a real
|
|
13
|
+
* sub-agent (which needs a live model stream and, for the timeout path, ten
|
|
14
|
+
* minutes of wall clock).
|
|
15
|
+
*
|
|
16
|
+
* `preferLast` — the normal completion path — returns the final assistant
|
|
17
|
+
* message, which is the sub-agent's actual answer.
|
|
18
|
+
*
|
|
19
|
+
* `preferLast: false` is the SALVAGE path, used when the sub-agent was cut off.
|
|
20
|
+
* A stopped sub-agent usually has no closing summary at all (it was killed
|
|
21
|
+
* mid-tool-round), so the last assistant message is frequently empty or a
|
|
22
|
+
* fragment. Concatenating what it did produce is far more useful to the parent
|
|
23
|
+
* model than nothing: it can build on the work instead of redoing it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function extractSubTaskText(messages: Message[], preferLast?: boolean): string;
|
|
26
|
+
/** Apply the parent-context cap to a sub-task's text, keeping head + tail. */
|
|
27
|
+
export declare function capSubTaskText(text: string, max?: number): string;
|
|
28
|
+
/**
|
|
29
|
+
* Summarise what a cut-short sub-agent actually accomplished, so the parent model
|
|
30
|
+
* can continue from it rather than starting over.
|
|
31
|
+
*
|
|
32
|
+
* This is the whole point of the salvage path. Previously a timed-out sub-agent
|
|
33
|
+
* returned ONLY an error string: ten minutes of work, dozens of tool calls and
|
|
34
|
+
* any files it wrote were invisible to the parent, which typically responded by
|
|
35
|
+
* re-running the same work from scratch — while the tokens for the discarded run
|
|
36
|
+
* had already been billed in full.
|
|
37
|
+
*/
|
|
38
|
+
export declare function summariseSubTaskProgress(messages: Message[]): string;
|
|
3
39
|
/** The context window (tokens) for a model alias — the same lookup runAgentLoop uses internally. */
|
|
4
40
|
export declare function contextWindowFor(model?: 'turbo' | 'pro' | 'ultra'): number;
|
|
5
41
|
/** Auto-prune / auto-compact thresholds as fractions of the context window — for UI display (e.g. `/context`). */
|
|
@@ -11,6 +47,26 @@ export declare function compactionThresholds(): {
|
|
|
11
47
|
export declare function estimateBodyBytes(messages: Message[]): number;
|
|
12
48
|
/** Tools that mutate the filesystem — used by the verification nudge (GAP D). */
|
|
13
49
|
export declare const WRITE_TOOL_NAMES: Set<string>;
|
|
50
|
+
/**
|
|
51
|
+
* May an agent restricted to `testFilesOnly` perform this tool call?
|
|
52
|
+
*
|
|
53
|
+
* A tool allowlist is all-or-nothing per tool: granting `edit_file` grants it for
|
|
54
|
+
* every path in the repo. The `test-writer` agent needs write access to produce
|
|
55
|
+
* tests, but must NOT be able to "fix" production source so a failing test goes
|
|
56
|
+
* green — the single most common way a test-writing agent destroys the signal it
|
|
57
|
+
* was asked to create. Its prompt says so; this makes it a refusal rather than a
|
|
58
|
+
* request.
|
|
59
|
+
*
|
|
60
|
+
* Pure + exported so the rules are testable directly, without running a real
|
|
61
|
+
* sub-agent.
|
|
62
|
+
*
|
|
63
|
+
* KNOWN LIMIT, stated rather than hidden: this gates the file TOOLS, not `bash`.
|
|
64
|
+
* A determined model could still write source via `bash: echo ... > src/x.ts`.
|
|
65
|
+
* Closing that means parsing shell redirection, which is not reliably doable — so
|
|
66
|
+
* this is a strong guardrail against the realistic failure mode, not a sandbox.
|
|
67
|
+
* Real isolation is the sandbox config (tools/sandbox.ts), a separate mechanism.
|
|
68
|
+
*/
|
|
69
|
+
export declare function allowsTestOnlyWrite(tool: string, input: Record<string, unknown> | undefined): boolean;
|
|
14
70
|
/** Heuristic: does a bash command look like it's running tests/build/lint/typecheck? (GAP D) */
|
|
15
71
|
export declare const VERIFY_CMD_RE: RegExp;
|
|
16
72
|
/**
|
package/dist/agent/loop.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAMP,gBAAgB,EAChB,UAAU,EACX,MAAM,UAAU,CAAC;AAyKlB,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAWR;
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"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"}
|