@nexrall/code-core 1.4.63 → 1.4.66

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 (59) hide show
  1. package/README.md +2 -2
  2. package/dist/agent/agentRegistry.d.ts +14 -3
  3. package/dist/agent/agentRegistry.d.ts.map +1 -1
  4. package/dist/agent/agentRegistry.js +136 -6
  5. package/dist/agent/agentTypes.d.ts +53 -3
  6. package/dist/agent/agentTypes.d.ts.map +1 -1
  7. package/dist/agent/agentTypes.js +200 -153
  8. package/dist/agent/backgroundAgents.d.ts +66 -0
  9. package/dist/agent/backgroundAgents.d.ts.map +1 -0
  10. package/dist/agent/backgroundAgents.js +145 -0
  11. package/dist/agent/loop.d.ts +44 -7
  12. package/dist/agent/loop.d.ts.map +1 -1
  13. package/dist/agent/loop.js +946 -263
  14. package/dist/agent/memory.d.ts +11 -0
  15. package/dist/agent/memory.d.ts.map +1 -1
  16. package/dist/agent/memory.js +23 -3
  17. package/dist/agent/modelCatalogue.d.ts +15 -0
  18. package/dist/agent/modelCatalogue.d.ts.map +1 -1
  19. package/dist/agent/modelCatalogue.js +46 -0
  20. package/dist/agent/planMode.d.ts +14 -0
  21. package/dist/agent/planMode.d.ts.map +1 -1
  22. package/dist/agent/planMode.js +145 -17
  23. package/dist/agent/readDedupe.d.ts +15 -0
  24. package/dist/agent/readDedupe.d.ts.map +1 -0
  25. package/dist/agent/readDedupe.js +146 -0
  26. package/dist/agent/securityLint.js +2 -2
  27. package/dist/agent/toolPrefetch.d.ts +44 -0
  28. package/dist/agent/toolPrefetch.d.ts.map +1 -0
  29. package/dist/agent/toolPrefetch.js +101 -0
  30. package/dist/agent/trust.d.ts +0 -5
  31. package/dist/agent/trust.d.ts.map +1 -1
  32. package/dist/agent/trust.js +41 -0
  33. package/dist/api/client.d.ts +15 -1
  34. package/dist/api/client.d.ts.map +1 -1
  35. package/dist/api/client.js +88 -8
  36. package/dist/index.d.ts +1 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +1 -0
  39. package/dist/permissions/destructive.d.ts +9 -7
  40. package/dist/permissions/destructive.d.ts.map +1 -1
  41. package/dist/permissions/destructive.js +55 -8
  42. package/dist/permissions/destructiveTokens.d.ts +29 -0
  43. package/dist/permissions/destructiveTokens.d.ts.map +1 -0
  44. package/dist/permissions/destructiveTokens.js +469 -0
  45. package/dist/permissions/modePolicy.d.ts +22 -8
  46. package/dist/permissions/modePolicy.d.ts.map +1 -1
  47. package/dist/permissions/modePolicy.js +25 -10
  48. package/dist/tools/executor.d.ts +36 -0
  49. package/dist/tools/executor.d.ts.map +1 -1
  50. package/dist/tools/executor.js +408 -85
  51. package/dist/tools/tsLangService.d.ts.map +1 -1
  52. package/dist/tools/tsLangService.js +107 -21
  53. package/dist/types.d.ts +101 -7
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/types.js +12 -1
  56. package/dist/util/miniYaml.d.ts +10 -0
  57. package/dist/util/miniYaml.d.ts.map +1 -0
  58. package/dist/util/miniYaml.js +149 -0
  59. package/package.json +2 -10
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
@@ -44,9 +44,17 @@ export interface StoredAgent {
44
44
  seq: number;
45
45
  /** Rough JSON size, cached so the byte cap doesn't re-serialise on every write. */
46
46
  bytes: number;
47
+ /**
48
+ * The conversation (AgentLoopOptions.sessionId) that created it. Every main agent's
49
+ * scope is 'root', so without this any chat in a shared process (VS Code panels,
50
+ * desktop tasks) could resume another chat's sub-agents.
51
+ */
52
+ sessionKey?: string;
47
53
  }
54
+ export declare function enableAgentTranscriptPersistence(dir?: string): void;
55
+ export declare function disableAgentTranscriptPersistence(): void;
48
56
  /** Store a finished sub-agent's transcript. Returns its resumable id. */
49
- export declare function rememberAgent(agentName: string | null, description: string, messages: Message[], ownerScope?: string): string;
57
+ export declare function rememberAgent(agentName: string | null, description: string, messages: Message[], ownerScope?: string, sessionKey?: string): string;
50
58
  /**
51
59
  * May `scope` resume/modify the agent stored under `id`?
52
60
  *
@@ -55,10 +63,13 @@ export declare function rememberAgent(agentName: string | null, description: str
55
63
  * and inventing a prefix convention to fake it would be a second guessable capability.
56
64
  * The main agent is included because it owns the session and already sees every result.
57
65
  */
58
- export declare function canResume(stored: StoredAgent, scope: string): boolean;
66
+ export declare function canResume(stored: StoredAgent, scope: string, sessionKey?: string): boolean;
59
67
  /** Append a resumed run's new messages to an existing agent. */
60
- export declare function updateAgent(id: string, messages: Message[], scope?: string): void;
68
+ export declare function updateAgent(id: string, messages: Message[], scope?: string, sessionKey?: string): void;
61
69
  export declare function getAgent(id: string): StoredAgent | undefined;
70
+ /** Mark an agent as being resumed. False if another run already holds it. */
71
+ export declare function claimAgentForResume(id: string): boolean;
72
+ export declare function releaseAgentForResume(id: string): void;
62
73
  /** Newest first — the order a "which agents can I resume?" list wants. */
63
74
  export declare function listAgents(): StoredAgent[];
64
75
  /** Test seam. Not exported through index.ts's public surface by intent. */
@@ -1 +1 @@
1
- {"version":3,"file":"agentRegistry.d.ts","sourceRoot":"","sources":["../../src/agent/agentRegistry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AA8CxC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;;;;;;;;;;;OAcG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;OASG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;CACf;AA4CD,yEAAyE;AACzE,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,OAAO,EAAE,EACnB,UAAU,SAAS,GAClB,MAAM,CAkBR;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAErE;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,SAAS,GAAG,IAAI,CAgBjF;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAE5D;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,IAAI,WAAW,EAAE,CAE1C;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,IAAI,IAAI,CAI1C;AAED,eAAO,MAAM,OAAO;;;CAAkC,CAAC"}
1
+ {"version":3,"file":"agentRegistry.d.ts","sourceRoot":"","sources":["../../src/agent/agentRegistry.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AA8CxC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;;;;;;;;;;;OAcG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;OASG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAsDD,wBAAgB,gCAAgC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAInE;AAED,wBAAgB,iCAAiC,IAAI,IAAI,CAAwB;AAoCjF,yEAAyE;AACzE,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,OAAO,EAAE,EACnB,UAAU,SAAS,EACnB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAoBR;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAG1F;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,SAAS,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAiBtG;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAU5D;AAMD,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAIvD;AACD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAuB;AAE9E,0EAA0E;AAC1E,wBAAgB,UAAU,IAAI,WAAW,EAAE,CAE1C;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,IAAI,IAAI,CAI1C;AAED,eAAO,MAAM,OAAO;;;CAAkC,CAAC"}
@@ -1,13 +1,53 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports._limits = void 0;
37
+ exports.enableAgentTranscriptPersistence = enableAgentTranscriptPersistence;
38
+ exports.disableAgentTranscriptPersistence = disableAgentTranscriptPersistence;
4
39
  exports.rememberAgent = rememberAgent;
5
40
  exports.canResume = canResume;
6
41
  exports.updateAgent = updateAgent;
7
42
  exports.getAgent = getAgent;
43
+ exports.claimAgentForResume = claimAgentForResume;
44
+ exports.releaseAgentForResume = releaseAgentForResume;
8
45
  exports.listAgents = listAgents;
9
46
  exports._resetAgentRegistry = _resetAgentRegistry;
10
47
  const node_crypto_1 = require("node:crypto");
48
+ const fs = __importStar(require("node:fs"));
49
+ const os = __importStar(require("node:os"));
50
+ const path = __importStar(require("node:path"));
11
51
  // ─── Resumable sub-agents ────────────────────────────────────────────────────
12
52
  //
13
53
  // A sub-agent normally starts with a blank slate: fresh context, no memory of a
@@ -91,8 +131,72 @@ function sizeOf(messages) {
91
131
  return MAX_TOTAL_BYTES;
92
132
  }
93
133
  }
134
+ // ── Disk persistence (opt-in, per host) ─────────────────────────────────────────
135
+ //
136
+ // Claude Code keeps sub-agent transcripts on disk, so "continue that agent" survives a
137
+ // restart. Hosts opt in with enableAgentTranscriptPersistence() at startup; library
138
+ // callers and tests stay purely in-memory. Ids carry 32 random bits, so knowing one is
139
+ // the capability (the model only ever learns ids from its own tool results).
140
+ let _persistDir = null;
141
+ const PERSIST_MAX_FILES = 100;
142
+ const PERSIST_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000;
143
+ function enableAgentTranscriptPersistence(dir) {
144
+ _persistDir = dir ?? process.env.NEXRALL_AGENT_TRANSCRIPTS_DIR ?? path.join(os.homedir(), '.nexrall', 'agent-transcripts');
145
+ try {
146
+ fs.mkdirSync(_persistDir, { recursive: true, mode: 0o700 });
147
+ }
148
+ catch {
149
+ _persistDir = null;
150
+ return;
151
+ }
152
+ prunePersisted();
153
+ }
154
+ function disableAgentTranscriptPersistence() { _persistDir = null; }
155
+ function persistedPath(id) {
156
+ if (!_persistDir || !/^agent_\d+_[0-9a-f]{8}$/.test(id))
157
+ return null;
158
+ return path.join(_persistDir, `${id}.json`);
159
+ }
160
+ function persist(agent) {
161
+ const p = persistedPath(agent.id);
162
+ if (!p)
163
+ return;
164
+ try {
165
+ fs.writeFileSync(p, JSON.stringify(agent), { mode: 0o600 });
166
+ }
167
+ catch { /* best effort */ }
168
+ }
169
+ function loadPersisted(id) {
170
+ const p = persistedPath(id);
171
+ if (!p)
172
+ return undefined;
173
+ try {
174
+ const a = JSON.parse(fs.readFileSync(p, 'utf-8'));
175
+ if (a?.id !== id || !Array.isArray(a.messages))
176
+ return undefined;
177
+ // A restarted process has fresh scope counters, so only the main agent ('root')
178
+ // may resume a transcript from a previous process.
179
+ return { ...a, ownerScope: 'root', seq: ++_seq };
180
+ }
181
+ catch {
182
+ return undefined;
183
+ }
184
+ }
185
+ function prunePersisted() {
186
+ if (!_persistDir)
187
+ return;
188
+ try {
189
+ const files = fs.readdirSync(_persistDir).filter((f) => f.endsWith('.json'))
190
+ .map((f) => { const full = path.join(_persistDir, f); return { full, t: fs.statSync(full).mtimeMs }; })
191
+ .sort((a, b) => b.t - a.t);
192
+ const now = Date.now();
193
+ files.forEach((f, i) => { if (i >= PERSIST_MAX_FILES || now - f.t > PERSIST_MAX_AGE_MS)
194
+ fs.rmSync(f.full, { force: true }); });
195
+ }
196
+ catch { /* best effort */ }
197
+ }
94
198
  /** Store a finished sub-agent's transcript. Returns its resumable id. */
95
- function rememberAgent(agentName, description, messages, ownerScope = 'root') {
199
+ function rememberAgent(agentName, description, messages, ownerScope = 'root', sessionKey) {
96
200
  // Unguessable, so an id cannot be ENUMERATED even before the ownership check runs.
97
201
  // Defence in depth only — randomness is not authorisation, `canResume` is.
98
202
  const id = `agent_${++_counter}_${(0, node_crypto_1.randomUUID)().slice(0, 8)}`;
@@ -107,7 +211,9 @@ function rememberAgent(agentName, description, messages, ownerScope = 'root') {
107
211
  updatedAt: now,
108
212
  seq: ++_seq,
109
213
  bytes: sizeOf(messages),
214
+ ...(sessionKey ? { sessionKey } : {}),
110
215
  });
216
+ persist(_agents.get(id));
111
217
  evictUntilWithinLimits();
112
218
  return id;
113
219
  }
@@ -119,18 +225,20 @@ function rememberAgent(agentName, description, messages, ownerScope = 'root') {
119
225
  * and inventing a prefix convention to fake it would be a second guessable capability.
120
226
  * The main agent is included because it owns the session and already sees every result.
121
227
  */
122
- function canResume(stored, scope) {
228
+ function canResume(stored, scope, sessionKey) {
229
+ if (stored.sessionKey && sessionKey && stored.sessionKey !== sessionKey)
230
+ return false;
123
231
  return stored.ownerScope === scope || scope === 'root';
124
232
  }
125
233
  /** Append a resumed run's new messages to an existing agent. */
126
- function updateAgent(id, messages, scope = 'root') {
127
- const existing = _agents.get(id);
234
+ function updateAgent(id, messages, scope = 'root', sessionKey) {
235
+ const existing = getAgent(id);
128
236
  if (!existing)
129
237
  return;
130
238
  // Same authorisation as reading. Without it a low-privilege descendant could overwrite a
131
239
  // privileged agent's transcript while its `agentName` stayed unchanged — indirect prompt
132
240
  // injection into whatever frame resumes it next.
133
- if (!canResume(existing, scope))
241
+ if (!canResume(existing, scope, sessionKey))
134
242
  return;
135
243
  existing.messages = messages;
136
244
  existing.updatedAt = Date.now();
@@ -140,11 +248,33 @@ function updateAgent(id, messages, scope = 'root') {
140
248
  // actively-continued agent from being evicted by a burst of new one-shots.
141
249
  _agents.delete(id);
142
250
  _agents.set(id, existing);
251
+ persist(existing);
143
252
  evictUntilWithinLimits();
144
253
  }
145
254
  function getAgent(id) {
146
- return _agents.get(id);
255
+ const live = _agents.get(id);
256
+ if (live)
257
+ return live;
258
+ // Evicted from memory or from a previous process — fall back to disk.
259
+ const fromDisk = loadPersisted(id);
260
+ if (fromDisk) {
261
+ _agents.set(id, fromDisk);
262
+ evictUntilWithinLimits();
263
+ }
264
+ return fromDisk;
265
+ }
266
+ // Ids currently being resumed. Two `task` calls in one message resuming the SAME agent
267
+ // would both start from the same transcript and the last to finish would silently
268
+ // overwrite the other's work (updateAgent is last-write-wins).
269
+ const _inUse = new Set();
270
+ /** Mark an agent as being resumed. False if another run already holds it. */
271
+ function claimAgentForResume(id) {
272
+ if (_inUse.has(id))
273
+ return false;
274
+ _inUse.add(id);
275
+ return true;
147
276
  }
277
+ function releaseAgentForResume(id) { _inUse.delete(id); }
148
278
  /** Newest first — the order a "which agents can I resume?" list wants. */
149
279
  function listAgents() {
150
280
  return [..._agents.values()].sort((a, b) => b.seq - a.seq);
@@ -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,13 +53,53 @@ 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
+ /** Tools this agent may NOT use, on top of (or instead of) an allowlist. Claude Code's `disallowedTools`. */
60
+ disallowedTools?: string[];
61
+ /** Model round-trips before the run stops and reports back (Claude Code's `maxTurns`). */
62
+ maxTurns?: number;
63
+ /** Reasoning effort for this agent's requests (low | medium | high | xhigh | max). Default: the session's. */
64
+ effort?: string;
65
+ /** Always run this agent in the background (the `task` call returns immediately). */
66
+ background?: boolean;
67
+ /** `worktree` — run in a fresh isolated worktree; removed afterwards if it made no changes. */
68
+ isolation?: 'worktree';
69
+ /** `plan` — read-only lock for this agent regardless of the session mode. Only narrowing modes are honoured. */
70
+ permissionMode?: 'plan';
71
+ /** Display colour hint for UIs. */
72
+ color?: string;
73
+ /** Skills whose instructions are preloaded into this agent's prompt (Claude Code's `skills`). */
74
+ skills?: string[];
75
+ /** MCP servers this agent may use; others' tools are neither sent nor allowed (Claude Code's `mcpServers`). */
76
+ mcpServers?: string[];
77
+ /**
78
+ * Hooks active only while THIS agent runs (Claude Code's agent-scoped `hooks`).
79
+ * Same execution model and trust gate as settings.json hooks — see trust.ts, which
80
+ * lists an agent file declaring hooks as a trust-sensitive file.
81
+ */
82
+ hooks?: AgentHooks;
83
+ }
84
+ export interface AgentHookDef {
85
+ type: 'command';
86
+ command: string;
87
+ timeout_ms?: number;
88
+ }
89
+ export interface AgentHookEntry {
90
+ matcher?: string;
91
+ hooks: AgentHookDef[];
92
+ }
93
+ export interface AgentHooks {
94
+ PreToolUse?: AgentHookEntry[];
95
+ PostToolUse?: AgentHookEntry[];
96
+ /** When this agent finishes (Claude Code: `Stop` in an agent file == SubagentStop). */
97
+ Stop?: AgentHookDef[];
59
98
  }
60
99
  /** Where a sub-agent's own persistent notes live. */
61
100
  export type AgentMemoryScope = 'project' | 'user' | 'local';
62
- export declare const VALID_MODELS: readonly ["claude-sonnet-5", "claude-opus-5-5", "claude-fable-5-1", "gpt-5.4", "gpt-5.4-mini", "gpt-4.1", "turbo", "pro", "ultra", "fast"];
101
+ export declare function normaliseToolName(t: string): string;
102
+ export declare const VALID_MODELS: readonly ["claude-sonnet-5-5", "claude-opus-5-5", "claude-fable-5-1", "gpt-5.4", "gpt-5.4-mini", "gpt-4.1", "turbo", "pro", "ultra", "fast"];
63
103
  /** The four tier aliases specifically (a subset of VALID_MODELS) — the only values `AgentType.model`/`Skill.model` narrow to when recognised; a real model id passes through as a plain string instead. */
64
104
  export declare const MODEL_TIER_ALIASES: readonly ["turbo", "pro", "ultra", "fast"];
65
105
  export type ModelTier = (typeof MODEL_TIER_ALIASES)[number];
@@ -94,6 +134,16 @@ export interface AgentWarning {
94
134
  * happen to contain uppercase.
95
135
  */
96
136
  export declare function parseModel(v: string | undefined): string | undefined;
137
+ /**
138
+ * Read and validate an agent file's `hooks:` block. Accepts Claude Code's shape —
139
+ * `{ PreToolUse|PostToolUse: [{ matcher?, hooks: [{ type: command, command, timeout? }] }],
140
+ * Stop|SubagentStop: [{ hooks: [...] }] }` — with `timeout` in SECONDS (Claude Code)
141
+ * or `timeout_ms`. Anything else is an error, never a partial guess.
142
+ */
143
+ export declare function parseAgentHooks(raw: string): {
144
+ hooks?: AgentHooks;
145
+ error?: string;
146
+ };
97
147
  /**
98
148
  * Discover all agent types. Precedence: project > global > plugin > builtin.
99
149
  *
@@ -1 +1 @@
1
- {"version":3,"file":"agentTypes.d.ts","sourceRoot":"","sources":["../../src/agent/agentTypes.ts"],"names":[],"mappings":"AAmCA,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;CACvB;AAED,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAkX5D,eAAO,MAAM,YAAY,4IAKf,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,CAMpE;AAoLD;;;;;;;;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":"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"}