@nexrall/code-core 1.4.25 → 1.4.26
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/agentRegistry.d.ts +45 -0
- package/dist/agent/agentRegistry.d.ts.map +1 -0
- package/dist/agent/agentRegistry.js +138 -0
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +112 -8
- package/dist/agent/planMode.d.ts +20 -0
- package/dist/agent/planMode.d.ts.map +1 -0
- package/dist/agent/planMode.js +252 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/permissions/rules.d.ts.map +1 -1
- package/dist/permissions/rules.js +14 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Message } from '../types';
|
|
2
|
+
export interface StoredAgent {
|
|
3
|
+
id: string;
|
|
4
|
+
/**
|
|
5
|
+
* The agent type this ran as, or null for an unnamed (general-purpose) run.
|
|
6
|
+
*
|
|
7
|
+
* Stored so resumption can be re-authorised against the CURRENT permission
|
|
8
|
+
* rules. Without it, an id would be a permanent bypass of any deny rule added
|
|
9
|
+
* after the agent first ran.
|
|
10
|
+
*/
|
|
11
|
+
agentName: string | null;
|
|
12
|
+
/** Full conversation: the sub-agent's own user/assistant/tool messages. */
|
|
13
|
+
messages: Message[];
|
|
14
|
+
/** The description shown in the UI, for `/agents --resumable` style listings. */
|
|
15
|
+
description: string;
|
|
16
|
+
createdAt: number;
|
|
17
|
+
updatedAt: number;
|
|
18
|
+
/**
|
|
19
|
+
* Monotonic touch counter, used for ordering instead of `updatedAt`.
|
|
20
|
+
*
|
|
21
|
+
* Date.now() has millisecond resolution and these operations take
|
|
22
|
+
* microseconds, so two agents touched in the same tick compare EQUAL and a
|
|
23
|
+
* stable sort silently falls back to insertion order — i.e. "most recent"
|
|
24
|
+
* would have been wrong exactly when several things happen at once, which is
|
|
25
|
+
* the normal case for parallel sub-tasks. The timestamps are kept because
|
|
26
|
+
* they are meaningful to humans; the ordering does not depend on them.
|
|
27
|
+
*/
|
|
28
|
+
seq: number;
|
|
29
|
+
/** Rough JSON size, cached so the byte cap doesn't re-serialise on every write. */
|
|
30
|
+
bytes: number;
|
|
31
|
+
}
|
|
32
|
+
/** Store a finished sub-agent's transcript. Returns its resumable id. */
|
|
33
|
+
export declare function rememberAgent(agentName: string | null, description: string, messages: Message[]): string;
|
|
34
|
+
/** Append a resumed run's new messages to an existing agent. */
|
|
35
|
+
export declare function updateAgent(id: string, messages: Message[]): void;
|
|
36
|
+
export declare function getAgent(id: string): StoredAgent | undefined;
|
|
37
|
+
/** Newest first — the order a "which agents can I resume?" list wants. */
|
|
38
|
+
export declare function listAgents(): StoredAgent[];
|
|
39
|
+
/** Test seam. Not exported through index.ts's public surface by intent. */
|
|
40
|
+
export declare function _resetAgentRegistry(): void;
|
|
41
|
+
export declare const _limits: {
|
|
42
|
+
MAX_AGENTS: number;
|
|
43
|
+
MAX_TOTAL_BYTES: number;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=agentRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentRegistry.d.ts","sourceRoot":"","sources":["../../src/agent/agentRegistry.ts"],"names":[],"mappings":"AAAA,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,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,GAClB,MAAM,CAeR;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAYjE;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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports._limits = void 0;
|
|
4
|
+
exports.rememberAgent = rememberAgent;
|
|
5
|
+
exports.updateAgent = updateAgent;
|
|
6
|
+
exports.getAgent = getAgent;
|
|
7
|
+
exports.listAgents = listAgents;
|
|
8
|
+
exports._resetAgentRegistry = _resetAgentRegistry;
|
|
9
|
+
// ─── Resumable sub-agents ────────────────────────────────────────────────────
|
|
10
|
+
//
|
|
11
|
+
// A sub-agent normally starts with a blank slate: fresh context, no memory of a
|
|
12
|
+
// previous run. That is the whole point for one-shot research — but it makes
|
|
13
|
+
// follow-up work absurdly expensive. "Now also check the auth path" re-reads
|
|
14
|
+
// every file the last run already read, because the only way to add to a
|
|
15
|
+
// finished sub-task is to describe the whole job again from scratch.
|
|
16
|
+
//
|
|
17
|
+
// This registry keeps a completed sub-agent's transcript in memory so a later
|
|
18
|
+
// `task` call can continue it instead of restarting it. Claude Code does the
|
|
19
|
+
// same thing; the design decisions worth writing down are the ones about what
|
|
20
|
+
// NOT to do:
|
|
21
|
+
//
|
|
22
|
+
// • IN-MEMORY, process-lifetime only. Deliberately not written to disk. A
|
|
23
|
+
// transcript is unredacted tool output — file contents, command output,
|
|
24
|
+
// whatever a repo happens to contain. Persisting it would create a new
|
|
25
|
+
// durable copy of material the user never asked us to store, in a new place
|
|
26
|
+
// they would have to know to clean up. Losing resumability when the process
|
|
27
|
+
// exits is a much smaller cost than that.
|
|
28
|
+
//
|
|
29
|
+
// • BOUNDED, by entries and by bytes. A transcript is the largest object this
|
|
30
|
+
// process handles, and an agent loop that spawns sub-agents in a cycle would
|
|
31
|
+
// otherwise grow the heap until the CLI dies — a leak that shows up only in
|
|
32
|
+
// the longest sessions, i.e. the ones where losing work hurts most.
|
|
33
|
+
//
|
|
34
|
+
// • Resumption re-checks permission at the CALL SITE, not here. An id is a
|
|
35
|
+
// capability: if a rule denies `task(explorer)` after an explorer agent has
|
|
36
|
+
// already run, resuming by id must not hand that agent back. This module
|
|
37
|
+
// therefore stores the agent's NAME alongside its history, so the caller can
|
|
38
|
+
// re-evaluate the current rules against it. See runSubTask.
|
|
39
|
+
/** Max resumable agents kept alive. Oldest is evicted first. */
|
|
40
|
+
const MAX_AGENTS = 20;
|
|
41
|
+
/**
|
|
42
|
+
* Max total transcript bytes across all stored agents (~8 MB of JSON).
|
|
43
|
+
*
|
|
44
|
+
* Sized to comfortably hold a handful of long research runs while staying far
|
|
45
|
+
* below the point where it competes with the model context for memory. Eviction
|
|
46
|
+
* is by age, not by size, so one enormous transcript cannot pin out many small
|
|
47
|
+
* useful ones.
|
|
48
|
+
*/
|
|
49
|
+
const MAX_TOTAL_BYTES = 8 * 1024 * 1024;
|
|
50
|
+
/**
|
|
51
|
+
* Insertion-ordered store. A Map is enough: Maps iterate in insertion order, so
|
|
52
|
+
* "oldest" is simply the first key, and re-inserting on update moves an entry to
|
|
53
|
+
* the back — giving LRU-by-touch for free without a second data structure.
|
|
54
|
+
*/
|
|
55
|
+
const _agents = new Map();
|
|
56
|
+
let _counter = 0;
|
|
57
|
+
let _seq = 0;
|
|
58
|
+
function totalBytes() {
|
|
59
|
+
let n = 0;
|
|
60
|
+
for (const a of _agents.values())
|
|
61
|
+
n += a.bytes;
|
|
62
|
+
return n;
|
|
63
|
+
}
|
|
64
|
+
function evictUntilWithinLimits() {
|
|
65
|
+
while (_agents.size > MAX_AGENTS) {
|
|
66
|
+
const oldest = _agents.keys().next().value;
|
|
67
|
+
if (oldest === undefined)
|
|
68
|
+
break;
|
|
69
|
+
_agents.delete(oldest);
|
|
70
|
+
}
|
|
71
|
+
// Byte cap is checked second: an entry that is individually enormous should
|
|
72
|
+
// still be storable (it is the most expensive thing to recompute), but it
|
|
73
|
+
// must not drag the total past the cap alongside its neighbours.
|
|
74
|
+
while (totalBytes() > MAX_TOTAL_BYTES && _agents.size > 1) {
|
|
75
|
+
const oldest = _agents.keys().next().value;
|
|
76
|
+
if (oldest === undefined)
|
|
77
|
+
break;
|
|
78
|
+
_agents.delete(oldest);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function sizeOf(messages) {
|
|
82
|
+
try {
|
|
83
|
+
return JSON.stringify(messages).length;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// A transcript that cannot be serialised (cycles shouldn't happen, but a
|
|
87
|
+
// crash here would take down a completed sub-task's result) is treated as
|
|
88
|
+
// large so it gets evicted early rather than silently counted as free.
|
|
89
|
+
return MAX_TOTAL_BYTES;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Store a finished sub-agent's transcript. Returns its resumable id. */
|
|
93
|
+
function rememberAgent(agentName, description, messages) {
|
|
94
|
+
const id = `agent_${++_counter}`;
|
|
95
|
+
const now = Date.now();
|
|
96
|
+
_agents.set(id, {
|
|
97
|
+
id,
|
|
98
|
+
agentName,
|
|
99
|
+
description,
|
|
100
|
+
messages,
|
|
101
|
+
createdAt: now,
|
|
102
|
+
updatedAt: now,
|
|
103
|
+
seq: ++_seq,
|
|
104
|
+
bytes: sizeOf(messages),
|
|
105
|
+
});
|
|
106
|
+
evictUntilWithinLimits();
|
|
107
|
+
return id;
|
|
108
|
+
}
|
|
109
|
+
/** Append a resumed run's new messages to an existing agent. */
|
|
110
|
+
function updateAgent(id, messages) {
|
|
111
|
+
const existing = _agents.get(id);
|
|
112
|
+
if (!existing)
|
|
113
|
+
return;
|
|
114
|
+
existing.messages = messages;
|
|
115
|
+
existing.updatedAt = Date.now();
|
|
116
|
+
existing.seq = ++_seq;
|
|
117
|
+
existing.bytes = sizeOf(messages);
|
|
118
|
+
// Re-insert so this becomes the most recently used entry, protecting an
|
|
119
|
+
// actively-continued agent from being evicted by a burst of new one-shots.
|
|
120
|
+
_agents.delete(id);
|
|
121
|
+
_agents.set(id, existing);
|
|
122
|
+
evictUntilWithinLimits();
|
|
123
|
+
}
|
|
124
|
+
function getAgent(id) {
|
|
125
|
+
return _agents.get(id);
|
|
126
|
+
}
|
|
127
|
+
/** Newest first — the order a "which agents can I resume?" list wants. */
|
|
128
|
+
function listAgents() {
|
|
129
|
+
return [..._agents.values()].sort((a, b) => b.seq - a.seq);
|
|
130
|
+
}
|
|
131
|
+
/** Test seam. Not exported through index.ts's public surface by intent. */
|
|
132
|
+
function _resetAgentRegistry() {
|
|
133
|
+
_agents.clear();
|
|
134
|
+
_counter = 0;
|
|
135
|
+
_seq = 0;
|
|
136
|
+
}
|
|
137
|
+
exports._limits = { MAX_AGENTS, MAX_TOTAL_BYTES };
|
|
138
|
+
//# sourceMappingURL=agentRegistry.js.map
|
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;
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/loop.js
CHANGED
|
@@ -59,6 +59,8 @@ const executor_1 = require("../tools/executor");
|
|
|
59
59
|
const agentTypes_1 = require("./agentTypes");
|
|
60
60
|
const skills_1 = require("./skills");
|
|
61
61
|
const rules_1 = require("../permissions/rules");
|
|
62
|
+
const planMode_1 = require("./planMode");
|
|
63
|
+
const agentRegistry_1 = require("./agentRegistry");
|
|
62
64
|
const sandbox_1 = require("../tools/sandbox");
|
|
63
65
|
const index_1 = require("../plugins/index");
|
|
64
66
|
const testIntegrity_1 = require("./testIntegrity");
|
|
@@ -541,7 +543,49 @@ async function runSubTask(input, options, agentTypes) {
|
|
|
541
543
|
// ENOENT stats — against a sub-agent that is about to run for seconds to
|
|
542
544
|
// minutes. Note runAgentLoop re-reads for the sub-agent anyway, so the old
|
|
543
545
|
// behaviour was already inconsistent: fresh for the child, stale for the lookup.
|
|
544
|
-
|
|
546
|
+
// ── Resolve a resume target ─────────────────────────────────────────────────
|
|
547
|
+
//
|
|
548
|
+
// `resume_agent_id` continues a previous sub-agent. The stored transcript
|
|
549
|
+
// carries the agent's NAME, and that name — not the one the model passed — is
|
|
550
|
+
// what gets authorised below.
|
|
551
|
+
//
|
|
552
|
+
// This matters because an id would otherwise be a permanent capability: deny
|
|
553
|
+
// `task(explorer)` today and a model holding yesterday's explorer id could
|
|
554
|
+
// still resume it, with the deny rule looking like it was applied. Re-deriving
|
|
555
|
+
// the name from storage also stops a mismatched `subagent_type` from being
|
|
556
|
+
// used to launder a denied agent under an allowed name.
|
|
557
|
+
const resumeId = typeof input.resume_agent_id === 'string' ? input.resume_agent_id.trim() : '';
|
|
558
|
+
const resumed = resumeId ? (0, agentRegistry_1.getAgent)(resumeId) : undefined;
|
|
559
|
+
if (resumeId && !resumed) {
|
|
560
|
+
return {
|
|
561
|
+
error: `No resumable sub-agent with id "${resumeId}". Ids live only for the current session and the ` +
|
|
562
|
+
'oldest are dropped when too many accumulate, so this one has expired or never existed. ' +
|
|
563
|
+
'Start a fresh sub-task with a self-contained prompt instead.',
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
const requestedType = resumed
|
|
567
|
+
? (resumed.agentName ?? '')
|
|
568
|
+
: (typeof input.subagent_type === 'string' ? input.subagent_type : '');
|
|
569
|
+
// ── Enforce `deny: ["task(<name>)"]` ─────────────────────────────────────────
|
|
570
|
+
//
|
|
571
|
+
// This is the load-bearing check; filtering the catalogue in runAgentLoop only
|
|
572
|
+
// stops the agent being SUGGESTED. It must run BEFORE resolution, because the
|
|
573
|
+
// reload-on-miss path below deliberately re-reads from disk UNFILTERED — a
|
|
574
|
+
// denied agent is absent from the snapshot, would therefore "miss", and would
|
|
575
|
+
// then be found by that reload and run. Denying by omission is not denying.
|
|
576
|
+
//
|
|
577
|
+
// Phrased as a policy refusal, not "unknown type": the model must not respond
|
|
578
|
+
// by trying to create the agent file it thinks is missing.
|
|
579
|
+
if (requestedType) {
|
|
580
|
+
const decision = (0, rules_1.evaluatePermission)((0, rules_1.loadSettings)(options.workDir).permissions, 'task', { subagent_type: requestedType }, options.workDir);
|
|
581
|
+
if (decision === 'deny') {
|
|
582
|
+
return {
|
|
583
|
+
error: `The sub-agent "${requestedType}" is disabled by a permission rule in this project ` +
|
|
584
|
+
`(permissions.deny in settings.json). This is a deliberate policy choice, not a missing file — ` +
|
|
585
|
+
'do not create it and do not retry. Do the work yourself, or use a different sub-agent.',
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
}
|
|
545
589
|
let agent = (0, agentTypes_1.findAgentType)(agentTypes, requestedType);
|
|
546
590
|
let knownTypes = agentTypes;
|
|
547
591
|
if (requestedType && !agent) {
|
|
@@ -584,9 +628,16 @@ async function runSubTask(input, options, agentTypes) {
|
|
|
584
628
|
}
|
|
585
629
|
return options.requestPermission(req);
|
|
586
630
|
};
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
631
|
+
// ── Resume: continue a previous sub-agent instead of starting cold ──────────
|
|
632
|
+
//
|
|
633
|
+
// The new prompt is appended as another user turn to the stored transcript, so
|
|
634
|
+
// the agent keeps every file it read and every conclusion it reached. Without
|
|
635
|
+
// this, "now also check the auth path" means re-describing the entire job and
|
|
636
|
+
// re-reading everything — the most common and most expensive kind of waste in
|
|
637
|
+
// a delegated workflow.
|
|
638
|
+
const subMessages = resumed
|
|
639
|
+
? [...resumed.messages, { role: 'user', content: [{ type: 'text', text: prompt }] }]
|
|
640
|
+
: [{ role: 'user', content: [{ type: 'text', text: prompt }] }];
|
|
590
641
|
// A dedicated abort signal for this sub-agent, distinct from the parent's own
|
|
591
642
|
// options.abortSignal (user hit Ctrl+C). Set to true either when the parent
|
|
592
643
|
// aborts OR when the stall timeout below fires, whichever happens first —
|
|
@@ -609,6 +660,9 @@ async function runSubTask(input, options, agentTypes) {
|
|
|
609
660
|
_agentScope: `sub_${++_subTaskCounter}`, // isolated todo store per sub-agent
|
|
610
661
|
editorContext: null, // fresh isolated context for sub-agent
|
|
611
662
|
model: agent?.model ?? options.model,
|
|
663
|
+
// Plan mode is inherited, never relaxed. If the main agent could spawn a
|
|
664
|
+
// sub-agent that writes, the lock would be one `task` call from useless.
|
|
665
|
+
planMode: options.planMode,
|
|
612
666
|
nexrallMd: subNexrallMd,
|
|
613
667
|
abortSignal: subAbort,
|
|
614
668
|
requestPermission: gatedPermission,
|
|
@@ -671,7 +725,23 @@ async function runSubTask(input, options, agentTypes) {
|
|
|
671
725
|
}
|
|
672
726
|
// Normal completion: the final assistant message is the sub-agent's answer.
|
|
673
727
|
const text = capSubTaskText(extractSubTaskText(result, true));
|
|
674
|
-
|
|
728
|
+
// Store the transcript so a follow-up can continue this agent rather than
|
|
729
|
+
// re-running it from scratch, and tell the parent the id.
|
|
730
|
+
//
|
|
731
|
+
// Only on NORMAL completion. A timed-out or failed run is deliberately not
|
|
732
|
+
// resumable: its transcript ends mid-thought, often mid-tool-call, and
|
|
733
|
+
// resuming from that state invites the model to build on work whose status
|
|
734
|
+
// it cannot determine. Those paths already salvage their partial output as
|
|
735
|
+
// TEXT, which is the safe way to carry that information forward.
|
|
736
|
+
const agentId = resumed
|
|
737
|
+
? ((0, agentRegistry_1.updateAgent)(resumed.id, result), resumed.id)
|
|
738
|
+
: (0, agentRegistry_1.rememberAgent)(agent?.name ?? null, (typeof input.description === 'string' && input.description.trim()) || prompt.slice(0, 80), result);
|
|
739
|
+
const body = text || '(sub-task completed with no text output)';
|
|
740
|
+
return {
|
|
741
|
+
output: `${body}\n\n[resumable: this sub-agent is "${agentId}". To ask IT a follow-up — keeping ` +
|
|
742
|
+
'everything it already read and concluded — call task again with resume_agent_id="' + agentId +
|
|
743
|
+
'" instead of writing a new prompt from scratch.]',
|
|
744
|
+
};
|
|
675
745
|
}
|
|
676
746
|
catch (err) {
|
|
677
747
|
// Same salvage rule as the timeout path above, for the other way a sub-agent
|
|
@@ -1342,17 +1412,36 @@ async function runAgentLoop(initialMessages, options) {
|
|
|
1342
1412
|
const hooks = loadHooks(options.workDir);
|
|
1343
1413
|
const depth = options._depth ?? 0;
|
|
1344
1414
|
const agentScope = options._agentScope ?? 'root';
|
|
1415
|
+
// Settings are read before the agent catalogue because a `deny` rule can
|
|
1416
|
+
// switch a sub-agent off, and an agent that may not run must not be
|
|
1417
|
+
// advertised (see below).
|
|
1418
|
+
const settings = (0, rules_1.loadSettings)(options.workDir);
|
|
1345
1419
|
// Discover custom sub-agent types. Only the top-level agent is told the
|
|
1346
1420
|
// catalogue (sub-agents can't spawn further), but every level resolves types.
|
|
1347
|
-
|
|
1421
|
+
//
|
|
1422
|
+
// Denied agents are filtered OUT of the catalogue rather than left in it to be
|
|
1423
|
+
// refused on dispatch. Listing an agent you have forbidden trains the model to
|
|
1424
|
+
// spend a tool call discovering the refusal, and "available types: …" on the
|
|
1425
|
+
// error path would name it again. Enforcement still happens at dispatch
|
|
1426
|
+
// (runSubTask) — this is the cosmetic half; that is the load-bearing half.
|
|
1427
|
+
const agentTypes = (0, agentTypes_1.loadAgentTypes)(options.workDir).filter((t) => (0, rules_1.evaluatePermission)(settings.permissions, 'task', { subagent_type: t.name }, options.workDir) !== 'deny');
|
|
1348
1428
|
const agentsCatalogue = depth === 0 ? (0, agentTypes_1.summariseAgents)(agentTypes) : '';
|
|
1349
1429
|
// Skills catalogue — unlike agentsCatalogue, available at every depth: a skill is
|
|
1350
1430
|
// just a reusable prompt template (via use_skill), not another spawn point, so
|
|
1351
1431
|
// sub-agents benefit from the same playbooks without the recursion concerns that
|
|
1352
1432
|
// gate agentsCatalogue to the top level.
|
|
1353
1433
|
const skillsCatalogue = (0, skills_1.summariseSkills)((0, skills_1.loadSkills)(options.workDir));
|
|
1434
|
+
// Plan mode instructions ride the project-instructions channel, which is
|
|
1435
|
+
// authoritative in the system prompt. Prepended rather than appended: the
|
|
1436
|
+
// lock has to be read before the project conventions it overrides.
|
|
1437
|
+
//
|
|
1438
|
+
// Telling the model is not the enforcement (checkPlanMode at the call site is)
|
|
1439
|
+
// — it exists so the model spends the turn planning instead of discovering the
|
|
1440
|
+
// lock one refused tool call at a time.
|
|
1441
|
+
const planAwareNexrallMd = options.planMode
|
|
1442
|
+
? planMode_1.PLAN_MODE_INSTRUCTIONS + (options.nexrallMd ? `\n\n---\n\n${options.nexrallMd}` : '')
|
|
1443
|
+
: options.nexrallMd;
|
|
1354
1444
|
// Optional OS-level bash sandbox (opt-in via settings.json "sandbox").
|
|
1355
|
-
const settings = (0, rules_1.loadSettings)(options.workDir);
|
|
1356
1445
|
const sandboxCfg = (0, sandbox_1.parseSandboxConfig)(settings.raw.sandbox) ?? undefined;
|
|
1357
1446
|
// Soft iteration budget + optional auto-continue past it (see resolvers above).
|
|
1358
1447
|
const maxIterations = resolveMaxIterations(options.maxIterations, settings.raw);
|
|
@@ -1569,7 +1658,7 @@ async function runAgentLoop(initialMessages, options) {
|
|
|
1569
1658
|
effort: options.effort,
|
|
1570
1659
|
env: options.env,
|
|
1571
1660
|
editorContext: options.editorContext,
|
|
1572
|
-
nexrallMd:
|
|
1661
|
+
nexrallMd: planAwareNexrallMd,
|
|
1573
1662
|
clientType: options.clientType,
|
|
1574
1663
|
abortSignal: options.abortSignal,
|
|
1575
1664
|
extraTools: options.mcpManager?.getAnthropicTools(),
|
|
@@ -1794,6 +1883,21 @@ async function runAgentLoop(initialMessages, options) {
|
|
|
1794
1883
|
options.onToolResult(name, result);
|
|
1795
1884
|
return { block: { ...block, id }, result };
|
|
1796
1885
|
}
|
|
1886
|
+
// ── Plan mode: a session-wide read-only lock ────────────────────────
|
|
1887
|
+
//
|
|
1888
|
+
// Checked BEFORE requestPermission on purpose. Routing it through the
|
|
1889
|
+
// permission prompt would ask the user to approve something that is
|
|
1890
|
+
// not theirs to approve in that moment, and a model told "denied by
|
|
1891
|
+
// user" reliably re-asks. This refusal instead says plainly that no
|
|
1892
|
+
// answer here can unlock it.
|
|
1893
|
+
if (options.planMode) {
|
|
1894
|
+
const refusal = (0, planMode_1.checkPlanMode)(name, input);
|
|
1895
|
+
if (refusal) {
|
|
1896
|
+
result = { error: refusal.message };
|
|
1897
|
+
options.onToolResult(name, result);
|
|
1898
|
+
return { block: { ...block, id }, result };
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1797
1901
|
// Request permission
|
|
1798
1902
|
const description = humanDescription(name, input);
|
|
1799
1903
|
let permitted;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PlanModeRefusal {
|
|
2
|
+
/** Machine-readable reason, for tests and telemetry. */
|
|
3
|
+
reason: 'mutating-tool' | 'bash-not-read-only';
|
|
4
|
+
/** Message shown to the MODEL. Must stop it retrying or asking for approval. */
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Is this bash command provably read-only?
|
|
9
|
+
*
|
|
10
|
+
* "Provably" is doing real work: unknown verbs are refused, not guessed at.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isReadOnlyCommand(command: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Should this tool call be refused because the session is in plan mode?
|
|
15
|
+
* Returns null when the call is allowed.
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkPlanMode(tool: string, input: Record<string, unknown>): PlanModeRefusal | null;
|
|
18
|
+
/** Text appended to the system prompt while plan mode is active. */
|
|
19
|
+
export declare const PLAN_MODE_INSTRUCTIONS: string;
|
|
20
|
+
//# sourceMappingURL=planMode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planMode.d.ts","sourceRoot":"","sources":["../../src/agent/planMode.ts"],"names":[],"mappings":"AAwHA,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,MAAM,EAAE,eAAe,GAAG,oBAAoB,CAAC;IAC/C,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAgE1D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,eAAe,GAAG,IAAI,CAoCxB;AAED,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,QAqBvB,CAAC"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─── Plan mode ───────────────────────────────────────────────────────────────
|
|
3
|
+
//
|
|
4
|
+
// A session-wide read-only lock. The model may research as deeply as it likes
|
|
5
|
+
// and must finish by PROPOSING a plan; it cannot change anything until a human
|
|
6
|
+
// leaves plan mode. Claude Code ships the same idea, and the reason to copy it
|
|
7
|
+
// is that "read the codebase, then tell me what you'd do" is otherwise
|
|
8
|
+
// unenforceable — you are relying on the model choosing not to edit, which is a
|
|
9
|
+
// promise, not a guarantee.
|
|
10
|
+
//
|
|
11
|
+
// The design rule here is FAIL CLOSED. Everything that is not provably
|
|
12
|
+
// side-effect-free is refused. A false refusal costs the user one message
|
|
13
|
+
// ("this needs plan mode off"); a false permit silently mutates a repo the user
|
|
14
|
+
// believed was frozen. Those are not symmetric, so ambiguity always loses.
|
|
15
|
+
//
|
|
16
|
+
// Note this is a DIFFERENT axis from the sub-agent tool allowlist in
|
|
17
|
+
// agentTypes.ts. That restricts one delegated worker; this restricts the whole
|
|
18
|
+
// session including the main agent and every sub-agent it spawns.
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.PLAN_MODE_INSTRUCTIONS = void 0;
|
|
21
|
+
exports.isReadOnlyCommand = isReadOnlyCommand;
|
|
22
|
+
exports.checkPlanMode = checkPlanMode;
|
|
23
|
+
/**
|
|
24
|
+
* Tools that cannot alter anything outside the conversation.
|
|
25
|
+
*
|
|
26
|
+
* Deliberately an ALLOWLIST. A denylist would mean every tool added later is
|
|
27
|
+
* writable-by-default in plan mode, and the person adding it has no reason to
|
|
28
|
+
* think about plan mode at all — the failure would ship silently. With an
|
|
29
|
+
* allowlist, a new tool is refused until someone deliberately classifies it,
|
|
30
|
+
* and the refusal is visible the first time anybody tries it.
|
|
31
|
+
*/
|
|
32
|
+
const READ_ONLY_TOOLS = new Set([
|
|
33
|
+
'read_file', 'search_files', 'glob', 'list_directory', 'notebook_read',
|
|
34
|
+
// Planning bookkeeping. todo_write persists only to the session's own todo
|
|
35
|
+
// list, not the repo, so it stays available — a plan mode that cannot draft
|
|
36
|
+
// a checklist is missing the point of plan mode.
|
|
37
|
+
'todo_write', 'todo_read',
|
|
38
|
+
// Reading memory is fine; memory_write is NOT here on purpose. Memory is
|
|
39
|
+
// durable state that survives the session, so writing it is a real mutation
|
|
40
|
+
// even though no file in the repo changes.
|
|
41
|
+
'memory_read',
|
|
42
|
+
'use_skill',
|
|
43
|
+
'fetch_url', 'web_search',
|
|
44
|
+
// Delegating research is ALLOWED, and this is safe rather than a hole:
|
|
45
|
+
// runSubTask passes planMode down, so the sub-agent is under the same lock and
|
|
46
|
+
// its own write tools are refused by this very function one level deeper.
|
|
47
|
+
//
|
|
48
|
+
// Worth allowing rather than blanket-refusing, because plan mode exists to
|
|
49
|
+
// support deep research and the explorer agent is the cheapest way to do bulk
|
|
50
|
+
// searching without flooding the main context. Blocking `task` would have made
|
|
51
|
+
// the mode's headline use case worse, for no security gain.
|
|
52
|
+
'task',
|
|
53
|
+
// VS Code language server — all pure queries.
|
|
54
|
+
'get_symbols', 'get_workspace_symbols', 'find_references', 'go_to_definition',
|
|
55
|
+
'get_hover', 'get_diagnostics',
|
|
56
|
+
// Reading output from an ALREADY-running background shell. Starting one is
|
|
57
|
+
// gated with the rest of bash below; draining a buffer is not a new effect.
|
|
58
|
+
'bash_output',
|
|
59
|
+
]);
|
|
60
|
+
/**
|
|
61
|
+
* Commands allowed through `bash` in plan mode.
|
|
62
|
+
*
|
|
63
|
+
* bash is the hard case: it is one tool that spans `git log` and `rm -rf /`,
|
|
64
|
+
* so plan mode is only as strong as this list. Hence a strict allowlist of
|
|
65
|
+
* verbs known to be read-only, plus the argument screening in
|
|
66
|
+
* `isReadOnlyCommand` for the several that are read-only ONLY in some forms.
|
|
67
|
+
*/
|
|
68
|
+
const READ_ONLY_BASH = new Set([
|
|
69
|
+
'ls', 'cat', 'head', 'tail', 'wc', 'file', 'stat', 'du', 'df', 'pwd', 'which',
|
|
70
|
+
'type', 'echo', 'printf', 'basename', 'dirname', 'realpath', 'readlink',
|
|
71
|
+
'grep', 'egrep', 'fgrep', 'rg', 'ag', 'ack', 'find', 'fd', 'locate',
|
|
72
|
+
'diff', 'comm', 'cmp', 'sort', 'uniq', 'cut', 'tr', 'column', 'jq', 'yq',
|
|
73
|
+
'date', 'whoami', 'hostname', 'uname', 'env', 'printenv', 'id', 'groups',
|
|
74
|
+
'ps', 'top', 'uptime', 'free', 'node', 'python', 'python3',
|
|
75
|
+
'tree', 'less', 'more', 'nl', 'tac', 'strings', 'md5sum', 'sha256sum',
|
|
76
|
+
'true', 'false', 'test', 'sleep', 'seq', 'expr',
|
|
77
|
+
]);
|
|
78
|
+
/**
|
|
79
|
+
* Subcommands that are read-only for tools whose safety depends on the verb.
|
|
80
|
+
*
|
|
81
|
+
* `git` is the reason this exists: `git log` and `git push --force` share one
|
|
82
|
+
* binary, so classifying by executable name alone is useless here.
|
|
83
|
+
*/
|
|
84
|
+
const READ_ONLY_SUBCOMMANDS = {
|
|
85
|
+
git: new Set([
|
|
86
|
+
'log', 'show', 'diff', 'status', 'blame', 'branch', 'tag', 'remote',
|
|
87
|
+
'describe', 'rev-parse', 'rev-list', 'ls-files', 'ls-tree', 'ls-remote',
|
|
88
|
+
'cat-file', 'shortlog', 'reflog', 'whatchanged', 'grep', 'config',
|
|
89
|
+
'check-ignore', 'merge-base', 'name-rev', 'count-objects', 'verify-commit',
|
|
90
|
+
]),
|
|
91
|
+
// Package managers: only their query verbs.
|
|
92
|
+
npm: new Set(['ls', 'list', 'view', 'info', 'outdated', 'why', 'config', 'ping', 'search']),
|
|
93
|
+
pnpm: new Set(['ls', 'list', 'view', 'info', 'outdated', 'why', 'config']),
|
|
94
|
+
yarn: new Set(['list', 'info', 'why', 'config']),
|
|
95
|
+
cargo: new Set(['tree', 'metadata', 'search']),
|
|
96
|
+
go: new Set(['list', 'version', 'env', 'vet', 'doc']),
|
|
97
|
+
docker: new Set(['ps', 'images', 'logs', 'inspect', 'version', 'info', 'top', 'port', 'diff', 'stats']),
|
|
98
|
+
kubectl: new Set(['get', 'describe', 'logs', 'explain', 'top', 'version', 'api-resources', 'api-versions']),
|
|
99
|
+
// gh: read verbs only. `gh run rerun`, `gh pr merge` etc. are excluded, and
|
|
100
|
+
// the nested-verb check in isReadOnlyCommand handles `gh pr view` vs `gh pr merge`.
|
|
101
|
+
gh: new Set(['browse']),
|
|
102
|
+
};
|
|
103
|
+
/** Second-level read verbs for CLIs shaped as `<tool> <noun> <verb>`. */
|
|
104
|
+
const READ_ONLY_NESTED = {
|
|
105
|
+
gh: new Set(['view', 'list', 'status', 'diff', 'checks']),
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Shell metacharacters that can smuggle a second command past verb inspection.
|
|
109
|
+
*
|
|
110
|
+
* We could parse the chain and check each segment — `destructive.ts` does
|
|
111
|
+
* something like that — but plan mode is a deliberate, temporary restriction:
|
|
112
|
+
* the honest answer to "can I run this compound pipeline while frozen?" is
|
|
113
|
+
* "no, and it costs you nothing to wait". Rejecting the whole shape is far
|
|
114
|
+
* easier to get right than parsing shell grammar, and being wrong here means
|
|
115
|
+
* writing to a repo the user thinks is locked.
|
|
116
|
+
*
|
|
117
|
+
* `|` is included: `cat x | tee y` writes, and so does `... | sh`.
|
|
118
|
+
*/
|
|
119
|
+
const SHELL_CONTROL = /[\n\r;&|`]|\$\(|>>|>|<\(/;
|
|
120
|
+
function firstWords(command) {
|
|
121
|
+
return command.trim().split(/\s+/).filter(Boolean);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Is this bash command provably read-only?
|
|
125
|
+
*
|
|
126
|
+
* "Provably" is doing real work: unknown verbs are refused, not guessed at.
|
|
127
|
+
*/
|
|
128
|
+
function isReadOnlyCommand(command) {
|
|
129
|
+
const cmd = command.trim();
|
|
130
|
+
if (!cmd)
|
|
131
|
+
return false;
|
|
132
|
+
// Any chaining/redirection/substitution — refuse the whole thing.
|
|
133
|
+
if (SHELL_CONTROL.test(cmd))
|
|
134
|
+
return false;
|
|
135
|
+
const words = firstWords(cmd);
|
|
136
|
+
if (!words.length)
|
|
137
|
+
return false;
|
|
138
|
+
// `VAR=x cmd` — skip leading environment assignments to find the real verb.
|
|
139
|
+
let i = 0;
|
|
140
|
+
while (i < words.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(words[i]))
|
|
141
|
+
i++;
|
|
142
|
+
if (i >= words.length)
|
|
143
|
+
return false;
|
|
144
|
+
let verb = words[i];
|
|
145
|
+
// Strip a path prefix: /usr/bin/git → git
|
|
146
|
+
const slash = verb.lastIndexOf('/');
|
|
147
|
+
if (slash >= 0)
|
|
148
|
+
verb = verb.slice(slash + 1);
|
|
149
|
+
// `sudo anything` is refused outright regardless of the verb behind it: plan
|
|
150
|
+
// mode is a promise about this machine, and privilege escalation is exactly
|
|
151
|
+
// where a mistaken allow is least recoverable.
|
|
152
|
+
if (verb === 'sudo' || verb === 'doas' || verb === 'su')
|
|
153
|
+
return false;
|
|
154
|
+
const rest = words.slice(i + 1).filter((w) => !w.startsWith('-'));
|
|
155
|
+
const subs = READ_ONLY_SUBCOMMANDS[verb];
|
|
156
|
+
if (subs) {
|
|
157
|
+
const sub = rest[0];
|
|
158
|
+
if (!sub) {
|
|
159
|
+
// Bare `git` / `npm` just prints help — harmless.
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
if (subs.has(sub)) {
|
|
163
|
+
// `git config --global x y` WRITES. Only the read form (no value) passes.
|
|
164
|
+
if (verb === 'git' && sub === 'config') {
|
|
165
|
+
const args = words.slice(i + 2).filter((w) => !w.startsWith('-'));
|
|
166
|
+
return args.length <= 1;
|
|
167
|
+
}
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
const nested = READ_ONLY_NESTED[verb];
|
|
171
|
+
if (nested && rest[1] && nested.has(rest[1]))
|
|
172
|
+
return true;
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
if (!READ_ONLY_TOOLS.has(verb) && !READ_ONLY_BASH.has(verb))
|
|
176
|
+
return false;
|
|
177
|
+
// Interpreters can execute arbitrary code inline; only allow the trivial
|
|
178
|
+
// read-only forms (`node --version`). `node -e "fs.rmSync(...)"` must not pass.
|
|
179
|
+
if (verb === 'node' || verb === 'python' || verb === 'python3') {
|
|
180
|
+
return words.slice(i + 1).every((w) => w === '--version' || w === '-V' || w === '-v');
|
|
181
|
+
}
|
|
182
|
+
// `find` can execute and delete.
|
|
183
|
+
if (verb === 'find' && words.some((w) => w === '-exec' || w === '-execdir' || w === '-delete')) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
// Reading a file with `test`/`stat` is fine, but `tee` is not in the list at
|
|
187
|
+
// all, and `echo`/`printf` are only safe because redirection is already
|
|
188
|
+
// rejected by SHELL_CONTROL above.
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Should this tool call be refused because the session is in plan mode?
|
|
193
|
+
* Returns null when the call is allowed.
|
|
194
|
+
*/
|
|
195
|
+
function checkPlanMode(tool, input) {
|
|
196
|
+
if (tool === 'bash') {
|
|
197
|
+
const command = typeof input.command === 'string' ? input.command : '';
|
|
198
|
+
// Starting a background process in a "frozen" session is a side effect that
|
|
199
|
+
// outlives the refusal, so it is refused even for an otherwise-safe verb.
|
|
200
|
+
if (input.run_in_background === true) {
|
|
201
|
+
return {
|
|
202
|
+
reason: 'bash-not-read-only',
|
|
203
|
+
message: 'Plan mode is ON: background processes cannot be started. Finish researching and propose ' +
|
|
204
|
+
'your plan; the user will leave plan mode if they want it carried out.',
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (isReadOnlyCommand(command))
|
|
208
|
+
return null;
|
|
209
|
+
return {
|
|
210
|
+
reason: 'bash-not-read-only',
|
|
211
|
+
message: `Plan mode is ON, so \`bash\` is limited to provably read-only commands and this one was not ` +
|
|
212
|
+
'recognised as such (chained commands, redirection and command substitution are always refused). ' +
|
|
213
|
+
'Do NOT ask the user to approve it and do NOT try a variation to get around this — it is a ' +
|
|
214
|
+
'session-wide lock, not a per-call prompt. Use read-only inspection instead, and put the command ' +
|
|
215
|
+
'in your plan as a step to run once plan mode is off.',
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
if (READ_ONLY_TOOLS.has(tool))
|
|
219
|
+
return null;
|
|
220
|
+
return {
|
|
221
|
+
reason: 'mutating-tool',
|
|
222
|
+
message: `Plan mode is ON, so \`${tool}\` is unavailable — this session may not modify anything yet. ` +
|
|
223
|
+
'Do NOT ask for approval: no answer the user gives at this prompt can unlock it, because it is a ' +
|
|
224
|
+
'session-wide lock they control directly. Research with read-only tools and finish by proposing ' +
|
|
225
|
+
'a concrete plan (files to change, in order, and how to verify). The user will exit plan mode to ' +
|
|
226
|
+
'let you carry it out.',
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
/** Text appended to the system prompt while plan mode is active. */
|
|
230
|
+
exports.PLAN_MODE_INSTRUCTIONS = [
|
|
231
|
+
'# PLAN MODE IS ACTIVE',
|
|
232
|
+
'',
|
|
233
|
+
'This session is READ-ONLY. You cannot edit files, write files, run mutating commands, or start',
|
|
234
|
+
'background processes. This is enforced outside your control — it is not a permission prompt, and',
|
|
235
|
+
'the user cannot approve an exception from inside this turn.',
|
|
236
|
+
'',
|
|
237
|
+
'Therefore:',
|
|
238
|
+
'- NEVER ask "shall I go ahead and make this change?" — you cannot, whatever the answer.',
|
|
239
|
+
'- NEVER attempt a mutating tool "just to see" — it will be refused and wastes the turn.',
|
|
240
|
+
'- NEVER try to reach a blocked command another way (a different flag, a script, an interpreter).',
|
|
241
|
+
'',
|
|
242
|
+
'Your job is to research thoroughly, then deliver a plan:',
|
|
243
|
+
'1. What you found — the specific files, functions and line numbers that matter.',
|
|
244
|
+
'2. What you propose to change — file by file, in dependency order.',
|
|
245
|
+
'3. Risks and unknowns — what could break, what you could not verify, what you assumed.',
|
|
246
|
+
'4. How it will be verified — the exact build/test/lint command that proves it works.',
|
|
247
|
+
'',
|
|
248
|
+
'Be concrete. "Update the auth logic" is not a plan; "add a `refreshToken` field to AuthConfig in',
|
|
249
|
+
'auth/index.ts:42, then thread it through client.ts:118" is. The user will review the plan and',
|
|
250
|
+
'leave plan mode to have it carried out.',
|
|
251
|
+
].join('\n');
|
|
252
|
+
//# sourceMappingURL=planMode.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export * from './mcp/manager';
|
|
|
17
17
|
export * from './checkpoint/manager';
|
|
18
18
|
export * from './commands/loader';
|
|
19
19
|
export * from './agent/agentTypes';
|
|
20
|
+
export * from './agent/planMode';
|
|
21
|
+
export * from './agent/agentRegistry';
|
|
20
22
|
export * from './permissions/rules';
|
|
21
23
|
export * from './permissions/destructive';
|
|
22
24
|
export * from './plugins/index';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,8 @@ __exportStar(require("./mcp/manager"), exports);
|
|
|
33
33
|
__exportStar(require("./checkpoint/manager"), exports);
|
|
34
34
|
__exportStar(require("./commands/loader"), exports);
|
|
35
35
|
__exportStar(require("./agent/agentTypes"), exports);
|
|
36
|
+
__exportStar(require("./agent/planMode"), exports);
|
|
37
|
+
__exportStar(require("./agent/agentRegistry"), exports);
|
|
36
38
|
__exportStar(require("./permissions/rules"), exports);
|
|
37
39
|
__exportStar(require("./permissions/destructive"), exports);
|
|
38
40
|
__exportStar(require("./plugins/index"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/permissions/rules.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAsBD,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAoB5D;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/permissions/rules.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAsBD,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAoB5D;AA8ID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,MAAM,GACd,kBAAkB,GAAG,IAAI,CAK3B"}
|
|
@@ -174,6 +174,20 @@ function matchValues(tool, input, workDir) {
|
|
|
174
174
|
case 'stock_photo':
|
|
175
175
|
vals.push(str(input.path));
|
|
176
176
|
break;
|
|
177
|
+
// Sub-agent dispatch. Matching on the agent NAME is what makes
|
|
178
|
+
// `deny: ["task(explorer)"]` mean "this repo may not use the explorer
|
|
179
|
+
// agent" — the Claude-Code way of switching off a built-in you don't want.
|
|
180
|
+
//
|
|
181
|
+
// Without this case, `task` fell through to `default`, which reads
|
|
182
|
+
// `input.path` — a key the task tool does not have. Every patterned task
|
|
183
|
+
// rule therefore matched nothing and silently did nothing, which is the
|
|
184
|
+
// worst failure mode for a deny rule: it looks configured and isn't.
|
|
185
|
+
//
|
|
186
|
+
// A bare `task` rule (no pattern) still matches any dispatch, so
|
|
187
|
+
// `deny: ["task"]` disables sub-agents wholesale.
|
|
188
|
+
case 'task':
|
|
189
|
+
vals.push(str(input.subagent_type));
|
|
190
|
+
break;
|
|
177
191
|
default:
|
|
178
192
|
pushPath(str(input.path));
|
|
179
193
|
break;
|
package/dist/types.d.ts
CHANGED
|
@@ -321,6 +321,15 @@ export interface AgentLoopOptions {
|
|
|
321
321
|
env?: EnvContext;
|
|
322
322
|
editorContext?: EditorContext | null;
|
|
323
323
|
nexrallMd?: string;
|
|
324
|
+
/**
|
|
325
|
+
* Session-wide read-only lock ("plan mode"). When true the loop refuses every
|
|
326
|
+
* mutating tool BEFORE requestPermission is consulted, so no user answer at a
|
|
327
|
+
* permission prompt can unlock it — only leaving plan mode can.
|
|
328
|
+
*
|
|
329
|
+
* Inherited by every sub-agent: a lock the main agent can delegate its way
|
|
330
|
+
* out of is not a lock.
|
|
331
|
+
*/
|
|
332
|
+
planMode?: boolean;
|
|
324
333
|
/** Client type — controls which tools Claude is told about. */
|
|
325
334
|
clientType?: string;
|
|
326
335
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexrall/code-core",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.26",
|
|
4
4
|
"description": "Core agent loop, tools, and extension primitives for Nexrall Code — embed an AI coding agent in any Node.js application.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Nexrall <support@nexrall.com> (https://nexrall.com)",
|